Meaning of question mark operator '?' before arguments in Haxe

They are two different things. A ? Means an optional parameter. So if can be completely excluded from the function call and no substitution will take place.

(x:Float = 12) is a default parameter. Meaning if its excluded from the function call the value of 12 will be used.


There is indeed no reason to use ? in this example, but there is a difference.

On a statically typed target, f(null) would not compile since the basic types Int, Float and Bool are not nullable there. However, the ? implies nullability, meaning that

function f(?i:Int)

is actually the same as

function f(i:Null<Int> = null)

As you can see, the ? has two effects:

  • A null default value is added, so you can omit i during the call: f();
  • The type is wrapped in Null<T>. While this makes no difference on dynamic targets, it usually has a runtime performance cost on static targets (again: only for Int / Float / Bool arguments).

The only reason I can think of why you would want arguments with basic types to be nullable is to enable optional argument skipping. When calling f in this example, i can only be skipped if it is nullable:

class Main {
    static function main() {
        f("Test"); // 0, "Test"
    }

    static function f(?i:Int = 0, s:String) {
        trace(i, s);
    }
}

Note that if you add a default value to an optional argument, that value will be used even if you explicitly pass null:

class Main {
    static function main() {
        f(); // 0
        f(null); // 0
    }

    static function f(?i:Int = 0) {
        trace(i);
    }
}

Tags:

Haxe