Значение оператора вопросительного знака '?' перед аргументами в Haxe

В чем разница между этими двумя сигнатурами функций?

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

Кажется, не имеет значения, является ли аргумент префиксом ? Оба компилируют нормально.

Ответ 1

Там действительно нет причин для использования ? в этом примере, но есть разница.

На статически типизированной цели f(null) не будет компилироваться, так как базовые типы Int, Float и Bool там не обнуляются. Однако ? подразумевает обнуляемость, то есть

function f(?i:Int)

на самом деле так же, как

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

Как вы можете видеть, что ? имеет два эффекта:

  • Добавляется null значение по умолчанию, поэтому вы можете опустить i во время вызова: f();
  • Тип обернут в Null<T>. Хотя это не имеет значения для динамических целей, обычно это приводит к снижению производительности во время выполнения для статических целей (опять же: только для аргументов Int/Float/Bool).

Единственная причина, по которой я могу придумать, почему вы хотите, чтобы аргументы с базовыми типами обнулялись, - это включение необязательного пропуска аргументов. При вызове f в этом примере i могу быть пропущен, только если он обнуляем:

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

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

Обратите внимание, что если вы добавите значение по умолчанию к необязательному аргументу, это значение будет использоваться, даже если вы явно передадите null:

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

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

Ответ 2

Это две разные вещи. A? Означает необязательный параметр. Поэтому, если полностью исключить из вызова функции и не будет никакой замены.

(x: Float = 12) является параметром по умолчанию. Значение, если его исключение из функции вызовет, будет использовано значение 12.