13

What is the difference between these two function signatures?

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

It doesn't seem to make any difference whether argument is prefixed with ?, both compile fine.

Gama11
  • 31,714
  • 9
  • 78
  • 100
Dlean Jeans
  • 966
  • 1
  • 8
  • 23

2 Answers2

17

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);
    }
}
Gama11
  • 31,714
  • 9
  • 78
  • 100
1

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.

  • 1
    While you are not wrong, default parameters imply that they are optional. From a caller's perspective, they do not need to be entered. Since most languages that haxe compiles to do not support this, then an optional parameter is pretty much the same as a default parameter: the default value should be in the comments. This is not a critic of your statement, only an opinion on what is missing. – oli_chose123 Apr 30 '18 at 00:12
  • This answer implies that the default value of `12` would be inserted at the call-site if omitted from the call. As the JS Source tab here shows, that is _not_ the case: https://try.haxe.org/#De82a – Gama11 Feb 02 '19 at 11:44