Rust-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 ✗ ✗ ✗ ✓ *$TABLE .get() requires two arguments: key and field.
- For $LIST and $OBJ, use bracket or dot notation (e.g., obj["key"], obj.key, obj[2]).
- For $ARRAY, use bracket notation (e.g., arr[1]).
- Only $file and $TABLE support .get().
- This is based on direct testing in Grapa v0.0.39.
This guide helps Rust users transition to Grapa by mapping common Rust idioms, patterns, and code to their Grapa equivalents.
See Also: - Basic Syntax Guide - Operator Reference
Syntax Mapping Table
Rust | Grapa |
---|---|
let mut x = 5; | x = 5; |
x += 1; | x += 1; |
let s = String::from("hi"); | s = "hi"; |
s.push_str("!"); | s += "!"; |
let arr = vec![1,2,3]; | arr = [1, 2, 3]; |
arr[0] | arr[0] arr.get(0) |
let map = HashMap::new(); | obj = {} |
map["key"] | obj["key"] obj.key obj."key" |
for x in arr { ... } | i = 0; while (i < arr.len()) { x = arr[i]; ...; i += 1; } arr.map(op(x) { ... }) (n).range(0,1).map(op(i) { ... }) |
if cond { ... } else { ... } | if (cond) { ... } else { ... } |
fn f(x: i32) -> i32 { ... } | f = op(x) { ... }; |
/* comment */ (block only, own line) | /* comment */ (block only, own line) |
Some(x) / None | x / null |
Result<T, E> | value or $ERR |
match x { ... } | if/else chain |
arr.iter().map(|x| x+1) | arr.map(op(x) { x + 1; }) |
arr.iter().filter(|x| *x > 0) | arr.filter(op(x) { x > 0; }) |
arr.iter().fold(0, |a, x| a + x) | arr.reduce(op(a, x) { a + x; }, 0) |
arr.len() | arr.len() |
format!("{} {}", a, b) | ("" + a.str() + " " + b.str()) |
Note: Both
x = x + 1;
andx += 1;
(ands = s + "x";
ands += "x";
) are valid in Grapa. The+=
form is idiomatic and preferred in most cases.Note:
.get("key")
is only for$file
and$TABLE
. For$LIST
/$OBJ
, useobj["key"]
,obj.key
, orobj."key"
. For$ARRAY
, usearr[index]
orarr.get(index)
.
Access Patterns: Objects, Lists, Arrays, Files, and Tables
Below are all valid ways to access elements in Grapa data structures. See the canonical Basic Syntax Guide for the latest tested rules.
$LIST and $OBJ
obj = {"a": 1, "b": 2, "c": 3};
value = obj["b"]; /* Returns 2 */
value = obj.key; /* Returns value for key 'key' if present */
value = obj."b"; /* Returns 2 */
/* $LIST only: */
value = obj[1]; /* Returns 2 (by index) */
name = obj.getname(1); /* Returns "b" (key name at index 1) */
- Dot notation (
obj.key
) and bracket notation (obj["key"]
) are both valid for $LIST/$OBJ. .get()
is NOT valid for $LIST/$OBJ.
$ARRAY
arr = [10, 20, 30];
value = arr[1]; /* Returns 20 */
value = arr.get(1); /* Returns 20 */
- Use bracket notation or
.get(index)
for $ARRAY. - Dot notation and
.get("key")
are NOT valid for $ARRAY.
$file
files = $file().ls();
file_info = files.get(0); /* Correct */
- Always use
.get(index)
for $file results. - Bracket and dot notation are NOT valid for $file.
$TABLE
table = $file().table("ROW");
table.mkfield("name", "STR", "VAR");
table.set("user1", "Alice", "name");
value = table.get("user1", "name"); /* Correct */
- Always use
.get(key, field)
for $TABLE. - Bracket and dot notation are NOT valid for $TABLE.
Reference Table: | Type | .get("key") | .get(index) | Bracket Notation | Dot Notation | |-----------|:-----------:|:-----------:|:----------------:|:------------:| | $ARRAY | ✗ | ✗ | ✓ | — | | $LIST | ✗ | ✗ | ✓ | ✓ | | $file | ✓ | ✗ | — | — | | $TABLE | ✓ | ✗ | — | — | | $OBJ | ✗ | ✗ | ✗ | ✓ | $TABLE .get() requires two arguments: key and field.
See Basic Syntax Guide for empirical test results and future updates.
Common Pitfalls
- No
for
/foreach
loops—usewhile
or.range()
+functional methods - No
match
—useif/else
chains - No
.push()
/.append()
—use+=
for append - No
/* comment */
comments—only block comments (/* ... */
), always on their own line - No implicit truthy/falsy—use explicit boolean checks
- All statements and blocks must end with a semicolon (
;
) - Use
.map()
,.reduce()
,.filter()
as methods, not global functions - Use
.range()
for sequence generation instead of manual while loops - Use
.range()
with.reduce()
for for-loop-like accumulation or collection tasks - Use
.range().map()
and.range().filter()
for parallel sequence generation and filtering. For large arrays, always specify a thread count to avoid too many threads - Use
.iferr()
for simple error fallback; useif (result.type() == $ERR)
only for explicit error handling
Example Code Pairs
Rust:
// Sum squares of even numbers
let result = arr.iter().filter(|x| *x % 2 == 0).map(|x| x * x).sum::<i32>();
result = arr.filter(op(x) { x % 2 == 0; }).map(op(x) { x * x; }).reduce(op(a, b) { a + b; }, 0);
Rust:
// Read file lines
use std::fs;
let lines = fs::read_to_string("file.txt").unwrap().lines().collect::<Vec<_>>();
lines = $file().read("file.txt").split("\n");
Rust:
// HashMap access
let value = map["key"];
value = obj["key"];
value = obj.key;
value = obj."key";
Rust:
// File access (custom struct or map)
let value = file["key"];
value = file.get("key");
Rust:
// Generate numbers 0..9
let seq: Vec<_> = (0..10).collect();
seq = (10).range(0,1);
Rust:
// Sum numbers 0..9
let sum: i32 = (0..10).sum();
sum = (10).range(0,1).reduce(op(acc, x) { acc += x; }, 0);
Rust:
// Collect even numbers 0..9
let evens: Vec<_> = (0..10).filter(|x| x % 2 == 0).collect();
evens = (10).range(0,1).filter(op(x) { x % 2 == 0; });
Rust:
// Error fallback
let result = some_operation().unwrap_or(0);
result = some_operation().iferr(0);
Warning:
.map()
and.filter()
are parallel by default. For large arrays, specify a thread count:big = (1000000).range(0,1).map(op(x) { x * x; }, 8); // Limit to 8 threads
See Also
If you have more Rust idioms you want mapped to Grapa, please open an issue or PR!
Custom match() Function for Regex
Rust users often use regex::Regex::is_match
for regex checks. You can define a similar function in Grapa:
// Define a match function that returns true if the pattern is found
match = op("text"="", "pattern"="") {
text.grep(pattern, "x").len() > 0;
};
// Usage
if (match("hello world", "world")) {
"Found!".echo();
} else {
"Not found.".echo();
}
This is a handy workaround until Grapa adds a native .match()
method.
Clarification on .get() Usage: -
.get()
is required for$file
and$TABLE
access. -.get()
is not supported for$ARRAY
,$LIST
, or$OBJ
as of this writing. - Use bracket and dot notation for$ARRAY
,$LIST
, and$OBJ
. - If more objects support.get()
in the future, this guide will be updated.Comment Style: - Only block comments (
/* ... */
) are supported in Grapa, and must always be on their own line. -//
and#
comments are not supported and will cause errors.
Work-in-Progress (WIP) Items
Some Rust 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:
- Ownership system:
let x = String::new();
- Grapa has automatic memory management - Static typing:
let x: i32
- Grapa uses dynamic typing by design (see note below) - Borrowing:
&mut x
- Grapa has no borrowing, all values are owned - Lifetimes:
'a
- Grapa has automatic lifetime management - Unsafe blocks:
unsafe { }
- Grapa is memory-safe by design - Raw pointers:
*const T
- Grapa has no raw pointers - FFI:
extern "C"
- No direct FFI support - Const generics:
[T; N]
- No compile-time const generics - Higher-ranked trait bounds:
for<'a>
- No higher-ranked types - Inline assembly:
asm!()
- No inline assembly - Global allocators: - No custom allocator support
Important Note on Dynamic Typing: Grapa's dynamic typing is a fundamental design choice, not a limitation. It enables Grapa's core strengths: - Dynamic code execution and meta-programming capabilities - Runtime type introspection with
.type()
method - Flexible data processing without compile-time type constraints - System integration that doesn't require type definitionsGrapa provides type safety through runtime checking and rich type introspection, which is often more flexible than static typing for data processing and system integration tasks.
Nice to Have
These would improve developer experience but aren't essential:
- Traits:
trait MyTrait
- Use object composition and duck typing - Generics:
<T>
- Grapa has dynamic typing - Pattern matching:
match x { Some(y) => y, None => 0 }
- Useif/else
chains - Result types:
Result<T, E>
- Use.iferr()
or explicit error checking - Option types:
Option<T>
- Use explicit null checks - Macros:
macro_rules!
- Use Grapa's built-in code generation - Associated types:
type Output
- Use regular types - Default implementations: - Use regular method definitions
- Trait bounds:
where T: Display
- Use dynamic typing - Impl blocks:
impl MyStruct
- Use object constructors - Derive macros:
#[derive(Debug)]
- Use regular methods - Structs:
struct MyStruct
- Use object constructors - Enums:
enum MyEnum
- Use objects with type fields - Modules:
mod my_module
- Use Grapa's file system - Crates: - Use Grapa's library system
- Cargo: - Use Grapa's build system
- Workspaces: - Use directory organization
- Features:
[features]
- Use conditional compilation - Dependencies: - Use Grapa's dependency management
- Publishing: - Use Grapa's distribution system
- Documentation:
///
- Use regular comments
Rarely Used
These are advanced features that most developers won't miss:
- Unions:
union MyUnion
- Use regular types - Bit fields: - Use bitwise operations
- Inline assembly:
asm!()
- Use Grapa's system calls - Global allocators: - Use Grapa's memory management
- Custom target specifications: - Use Grapa's platform abstraction
- Linker scripts: - Use Grapa's build system
- Platform intrinsics: - Use Grapa's system integration
- SIMD: - Use Grapa's parallel processing
- Atomic operations: - Use Grapa's threading
- Memory ordering: - Use Grapa's memory model
Note: Many "missing" features are actually available in Grapa through different mechanisms. For example, Rust's ownership system is replaced by Grapa's automatic memory management, and Rust's async/await is replaced by Grapa's built-in parallel processing.
See Also
If you have more Rust idioms you want mapped to Grapa, please open an issue or PR!
Customizing Grapa for Familiar Syntax
If you prefer Rust-style macro calls, you can define your own println()
function in Grapa:
// Define a println function similar to Rust
println = op("value"=""){value.echo();};
println("Hello from Grapa!");