日本語

Troubleshooting & Common Mistakes

We have summarized errors that are easy to encounter while learning LuneScript and their solutions.
This focuses on points where experienced users of other languages (especially Lua, Go, Rust, etc.) are likely to get stuck.

Character Literal Syntax

Mistake: Using single quotes

// Error
let c = 'a';
let c = ?'a';
                

Correct: Write the character immediately after ?

// Becomes character code (int)
let c = ?a;
let sp = ? ;    // Same for space
let zero = ?0;  // Character code for the digit
                

In LuneScript, character literals are treated as integer values (character codes).

Mutable Method Definition

Mistake: Prefixing with mut

class MyClass {
    let mut val: int;
    // Error: illegal field or method declaration
    pub mut fn inc() {
        self.val = self.val + 1;
    }
}
                

Correct: Place mut after the argument list

class MyClass {
    let mut val: int;
    // Indicates that the method modifies itself (self)
    pub fn inc() mut {
        self.val = self.val + 1;
    }
}
                

In method definitions, mut functions as a declaration of the side effect 'this method modifies self', so it is written as part of the signature (on the trailing side).
Note that if there is a return value, it comes before the return type, like pub fn func() mut : int.

Pattern Matching of ADTs

Mistake: Trying to use if let (Rust style)

// Error: illegal exp
if let .Val( v ) = val {
    print( v );
}
                

Correct: Use the match statement

match val {
    case .Val( v ) {
        print( v );
    }
    default {
        // Handling when no match is found
    }
}
                

In the current version of LuneScript, using the match statement is the standard way to decompose Algebraic Data Types (ADTs).

Manipulation of Nilable Types and unwrap

Mistake: Treating Nilable types as Non-nilable directly

let val: int! = 10;
// Error: type mismatch int! (nilable) to int
let num: int = val; 
                

Correct: Use unwrap to extract values safely

let val: int! = 10;
// Specify a default value if it is nil
let num: int = unwrap val default 0;

// Or narrow it down with if let
if let v = val {
    print( v ); // Here v is of type int
}
                

unwrap is used to either 'guarantee that the value is not nil' or 'provide an alternative value if it is nil'.

Macro Syntax Errors

Mistake: Forgetting the expansion operator ,,

macro _dprint( val: __exp ) {
    print( val ); // Error: val is of type __exp and cannot be used as is.
}
                

Correct: Use ,, to expand the expression

macro _dprint( val: __exp ) {
    print( ,,val ); // OK: Expression is expanded
}
                

To use macro arguments (__exp, sym, __block, etc.) within the code, they must always be expanded with ,,.

Mistake: Using Lua keywords as symbol names

macro _measure( block: __block ) {
    {}
    {
        let start = os.clock();
        ,,block
        let end = os.clock(); // Error: 'end' is a Lua keyword
        print( end - start );
    }
}
                

Correct: Use names that avoid keywords

Because LuneScript is converted to Lua, an error will occur if variable names in code expanded by macros collide with Lua keywords (e.g., end, function, repeat). Please change them to different names like endTime.

Mistake: Writing statements directly in a __block argument

_measure( print("hello") ); // Error: A block {} is required, not an expression
                

Correct: Pass it enclosed in {}

_measure( { print("hello"); } );
                

Also, in the latest LuneScript syntax, using the argument omission feature with ## instead of __block may be recommended. Please adjust according to compiler warnings.

Mistake: Attempting to define or call normal functions within a macro-statement

macro _Test() {
  {
    fn createFunc( name: str ): stat { // Error
       return `{ fn ,,,name() {} };
    }
  }
  ,,createFunc("hoge");
}
                

Correct: Understand that macro-statement is a restricted environment

Within a macro-statement block, the type system and user-defined functions are not fully available. Basically, it's safer to stick to calculations using built-in types and built-in functions, and code generation with `{}.

Mistake: Range of the ,,, operator is unclear

stats.insert( `{
    let ,,, "v_%s"(name) = ,,i; // Error: Unclear where the name generation expression ends
} );
                

Correct: Explicitly indicate the termination with ~~

stats.insert( `{
    let ,,, "v_%s"(name) ~~ = ,,i; // OK: Tell the end of the expression with ~~
} );
                

The ,,, operator, which generates symbols dynamically, often requires a ~~ delimiter to prevent it from being interpreted as combined with subsequent elements.