Kotlin-to-Grapa Migration Guide
Important: Access Patterns for .get() and Indexing (Tested, v0.0.39)
Type .get("key") .get(index) Bracket Notation Dot Notation $ARRAY ✗ ✗ ✓ — $LIST ✗ ✗ ✓ ✓ $file ✓ ✗ — — $TABLE ✓ ✗ — — $OBJ ✗ ✗ ✓ ✓ $STR ✗ ✗ ✓ — See Basic Syntax Guide for details.
Kotlin-to-Grapa Migration Guide (WIP Features)
Main Table: Core Gaps (Tracked for Enhancement)
Kotlin Feature | Grapa Equivalent | Status/Note |
---|---|---|
import kotlin.math.* | — | GAP: No module/import system |
@file:JvmName("Foo") | — | GAP: No annotation/meta-programming |
coroutineScope { ... } | — | GAP: No coroutine/async support |
finally | — | GAP: No finally/ensure |
x!! (non-null assert) | — | GAP: No null assertion |
x?.foo() (safe call) | — | GAP: No safe call operator |
is (type check) | — | GAP: No direct type check operator |
as (type cast) | — | GAP: No direct type cast operator |
Nice to Have
Kotlin Feature | Grapa Equivalent | Note |
---|---|---|
sealed class | — | Advanced type, rarely needed |
enum class | — | Advanced type, rarely needed |
inline fun | — | Advanced meta-programming |
reified | — | Advanced meta-programming |
vararg | — | Advanced meta-programming |
tailrec fun | — | Advanced meta-programming |
operator fun | — | Advanced meta-programming |
infix fun | — | Advanced meta-programming |
extension fun | — | Advanced meta-programming |
@Annotation | — | Annotation, rarely needed |
inheritance | class (ParentClass) | Grapa supports inheritance |
method overriding | — | Use regular method definitions |
object/class composition | class {...} /object | Grapa supports composition |
Rarely Used
Kotlin Feature | Grapa Equivalent | Note |
---|---|---|
lateinit var x: Int | — | Rarely used, not blocking |
companion object | — | Rarely used, not blocking |
Work-in-Progress (WIP) Items
Some Kotlin idioms don't have direct Grapa equivalents yet. These are categorized by priority:
Core Gaps (True Language Gaps)
These represent fundamental language features that genuinely cannot be accomplished in Grapa:
- Module system:
import kotlin.math.*
- No module system - Annotations:
@file:JvmName("Foo")
- No annotation system - Coroutines:
coroutineScope { ... }
- No coroutine system - Finally/ensure:
finally
- No finally mechanism - Null assertion:
x!!
- No null assertion operator - Safe call:
x?.foo()
- No safe call operator - Type checking:
is
- No type checking operator - Type casting:
as
- No type casting operator - Sealed classes:
sealed class
- No sealed class system - Enum classes:
enum class
- No enum class system - Inline functions:
inline fun
- No inline function system - Reified generics:
reified
- No reified generics - Varargs:
vararg
- No vararg system - Tail recursion:
tailrec fun
- No tail recursion optimization - Operator functions:
operator fun
- No operator function system - Infix functions:
infix fun
- No infix function system - Extension functions:
extension fun
- No extension function system - Data classes:
data class
- No data class system - Companion objects:
companion object
- No companion object system
Nice to Have
These would improve developer experience but aren't essential:
- Late initialization:
lateinit var
- Use regular variables - Property delegation: - Use regular properties
- Lazy properties:
lazy
- Use regular properties - Observable properties: - Use regular properties
- Vetoable properties: - Use regular properties
- Property accessors: - Use regular methods
- Backing fields: - Use regular fields
- Property references: - Use regular references
- Function references:
::foo
- Use@"foo"
for variable references - Type references: - Use regular types
Rarely Used
These are advanced features that most developers won't miss:
- Kotlin-specific features: - Use Grapa equivalents
- Kotlin coroutines: - Use Grapa's threading
- Kotlin flow: - Use Grapa's event system
- Kotlin serialization: - Use Grapa's serialization
- Kotlin reflection: - Use Grapa's reflection
- Kotlin DSL: - Use Grapa's syntax
- Kotlin multiplatform: - Use Grapa's platform abstraction
- Kotlin native: - Use Grapa's compilation
- Kotlin JS: - Use Grapa's web support
- Kotlin Android: - Use Grapa's mobile support
Note: Many "missing" features are actually available in Grapa through different mechanisms. For example, Kotlin's coroutines are replaced by Grapa's built-in parallel processing with
.map()
and.filter()
, and Kotlin's null safety is replaced by Grapa's explicit null checking with.isnull()
.
Customizing Grapa for Familiar Syntax
If you prefer Kotlin-style function calls, you can define your own println()
function in Grapa:
println = op("value"=""){value.echo();};
println("Hello from Grapa!");
This can make migration easier for those used to Kotlin's println()
or similar functions.
Advanced: Grapa also allows advanced users to customize or extend the language syntax using
$RULE
or by modifying$global
rules. This enables you to inject your own grammar or override built-in behaviors to match your preferred style. For most users, we recommend learning the canonical Grapa method syntax, but this flexibility is available if needed.
Common Kotlin-to-Grapa Mappings
Kotlin | Grapa Equivalent |
---|---|
import kotlin.math.* | Built-in math functions (no import needed) |
File("file.txt").writeText(d) | $file().set("file.txt", d) |
thread { ... } | $thread().start(op() { ... }) |
Thread.sleep(1000) | $sys().sleep(1000) |
System.getenv("HOME") | $sys().getenv($HOME) |
exitProcess(0) | exit |
object : Foo {} | obj : Foo {} |
fun foo(x: Int) = ... | op(x){...} or op(x)("...") |
val x = ... | x = ... |
var x = ... | x = ... |
@file:JvmName("Foo") | WIP |
coroutineScope { ... } | WIP |
this | self |
super | super |
when (x) { ... } | switch(x) { ... } |
x = if (cond) a else b | x = (cond) ? a : b |
try { ... } catch { ... } | try { ... } catch (err) { ... } |
finally | WIP |
::foo (function ref) | Not relevant (functions are data, pass directly) |
x!! (non-null assert) | x.isnull() ? error : x (explicit null check) |
x?.foo() (safe call) | x.isnull() ? null : x.foo() (explicit null check) |
is (type check) | text.type() == $STR (type comparison) |
as (type cast) | x.str() , x.int() , x.float() (explicit conversion) |
data class | class ... {} or objects/lists (everything is data in Grapa) |
companion object | $global or $root for static/global |
lateinit var | Regular variables (assign when ready, no special syntax) |
Type Checking Examples
Grapa provides type checking using .type()
method and type constants:
/* Kotlin: if (value is String) { ... } */
/* Grapa equivalent: */
if (value.type() == $STR) {
"Value is a string".echo();
}
/* Kotlin: when (value) { is String -> ... is Int -> ... } */
/* Grapa equivalent: */
switch (value.type()) {
case $STR: "String value".echo();
case $INT: "Integer value".echo();
case $FLOAT: "Float value".echo();
case $ARRAY: "Array value".echo();
case $LIST: "List value".echo();
default: "Unknown type".echo();
}
/* Check multiple types */
if (value.type() == $STR || value.type() == $INT) {
"Value is string or integer".echo();
}
Common type constants: $STR
, $INT
, $FLOAT
, $BOOL
, $ARRAY
, $LIST
, $TABLE
, $TIME
, $ERR
Notes
- See Operators and System docs for more details.
- Grapa supports variable scoping with
$global
,$local
, and$root
. - Use
$sys().getenv()
for environment variables. - Use
$thread()
for threading and$sys().sleep()
for sleep. - Use
op(){}
for lambdas and function definitions.
Custom matches() Function for Regex
Kotlin users often use str.matches
for regex checks. You can define a similar function in Grapa:
// Define a matches function that returns true if the pattern is found
matches = op("text"="", "pattern"="") {
text.grep(pattern, "x").len() > 0;
};
// Usage
if (matches("hello world", "world")) {
"Found!".echo();
} else {
"Not found.".echo();
}
This is a handy workaround until Grapa adds a native .match()
method.
Note: While not as concise as Kotlin's operator syntax, this approach is explicit and clear about what operations are being performed.
Late Initialization Examples
Grapa doesn't need special lateinit
syntax because variables can be assigned at any time:
/* Kotlin: lateinit var name: String */
/* Grapa equivalent: Just declare and assign later */
MyClass = class {
name = ""; /* Can be empty initially */
/* Initialize when ready */
init = op() {
name = "John"; /* Assign when convenient */
};
/* Or assign conditionally */
setup = op(condition) {
if (condition) {
name = "Active User";
} else {
name = "Inactive User";
}
};
};
/* Usage */
obj = obj MyClass;
obj.init(); /* name is now "John" */
Key differences: - No special syntax - Just use regular variables - No null safety concerns - Grapa's dynamic typing handles this naturally - Flexible assignment - Assign whenever convenient - No compile-time constraints - Runtime assignment is always possible