Values and Types
This section explains the values and types handled in LuneScript in detail.
Primitive Types
| Type Name | Description | Example |
|---|---|---|
int |
Integer | 1, -10, 0x10 |
real |
Real number (floating point) | 1.0, 3.14 |
bool |
Boolean | true, false |
str |
String (immutable) | "hello", 'world' |
stem |
All types except nil | (Any non-nil value) |
stem is the base type for all types, but it cannot hold nil. To allow
nil, use stem!.
Collections
List<T> (List)
A dynamic array where elements can be added or removed.
let mut list: List<int> = [ 10, 20 ]; // Initialization
list.insert( 30 ); // Add: [ 10, 20, 30 ]
list.remove(); // Remove from end: [ 10, 20 ]
print( list[ 1 ] ); // Access (1-based index): 10
print( #list ); // Get size: 2
Map<K,V> (Associative Array)
Holds key-value pairs. JSON-like literals can be used.
let mut map: Map<str,int> = {
"a": 1,
"b": 2
};
// Access
print( map[ "a" ] ); // 1
print( map.b ); // Can also access via dot notation if the key is a string
// Delete (by assigning nil)
map.a = nil;
nil is returned if
the value corresponding to the key does not exist.
Set<T> (Set)
Manages a collection of unique values. The literal is (@ ... ).
let mut set = (@ 1, 2, 3 );
set.add( 4 ); // Add
set.del( 1 ); // Delete
print( set.has( 2 ) ); // Check existence: true
print( set.len() ); // Number of elements: 3
Set operations or (union), and (intersection), and sub (difference)
are also supported.
Nilable Types (Null Safety)
Appending ! to a type name makes it a type that can hold nil.
let val1: int = 1; // Non-nilable
let val2: int! = nil; // Nilable (int or nil)
Nilable types cannot be used in calculations as is (for safety). They must be Unwrapped (Non-Nilated).
unwrap
Forcibly removes nil. If the value is nil, a runtime error occurs.
let a: int! = 10;
let b: int = unwrap a;
You can specify a default value for safe unwrapping.
let a: int! = nil;
let c: int = unwrap a default 0; // Becomes 0 if nil
if! let / when!
Syntax for executing a block only if a variable is not nil.
fn funcReturnsNilable(): int! { return 1; }
if! let x = funcReturnsNilable() {
// x can be treated as non-nil (int) here
print( x + 1 );
} else {
print( "x was nil" );
}
when! checks if an existing variable is nil.
let val: int! = nil;
when! val {
// Inside this block, val is of type int (immutable)
}
let! .. then ..
A style that describes the "processing when the variable is nil" first (similar to a guard clause).
fn funcReturnsNilable(): int! { return nil; }
let! x = funcReturnsNilable() {
// Executed if x is nil
return;
}
// x is non-nil here
print( x + 1 );
Nil Conditional Operator ($)
Performs member access or function calls on a nilable value only if it is not nil. If the value is nil, it
returns nil. The evaluation result is always a Nilable type.
- Member Access:
obj$.member - Index Access:
obj$[index] - Function Call:
func$(args)
class Test {
pub let val: List<int>;
pub fn func(): int { return 100; }
}
fn sub( test: Test! ) {
// If test is nil, everything becomes nil
print( test$.val$[1], test$.func$() );
}
sub( new Test( [ 1, 2 ] ) ); // 1 100
sub( nil ); // nil nil
Casting
There are two types of type conversion: @@ (forced) and @@@ (safe).
Forced Casting (@@)
let val: stem = 10;
let i = val@@int; // Conversion without checking. Behavior on failure is undefined or an error.
Safe Casting (@@@)
let val: stem = "test";
if! let i = val@@@int {
print( "Integer!" );
} else {
print( "Not an integer" );
}
Returns nil if conversion fails.
Algebraic Data Types
alge is a type of enumeration, but each value (constructor) can have parameters. It is a tagged
union.
alge Shape {
Rect( real, real ),
Circle( real ),
}
let s = Shape.Rect( 10.0, 20.0 );
match s {
case .Rect( w, h ) { print( "Rect:", w * h ); }
case .Circle( r ) { print( "Circle:", r * r * 3.14 ); }
}
Enum
A simple enumeration of values. Integers, real numbers, and strings can be assigned.
enum Color {
Red = 0,
Green, // 1 (Auto-incrementing)
Blue, // 2
}
print( Color.Red ); // 0
print( Color.Red.$_txt ); // "Color.Red" (String representation)
Use _from to convert a raw value to an Enum.
enum Color { Green=1 }
let c = unwrap Color._from( 1 ); // Color.Green (Needs unwrap because it is nilable)
Tuple
Handles multiple values together.
let t: (int, str) = (= 1, "ok" );
Use ... to expand it, for example, when passing arguments to a function.
fn func( i: int, s: str ) { print( i, s ); }
let t: (int, str) = (= 1, "ok" );
func( t... );