Як можна реалізувати varargs? Нам потрібен якийсь механізм, щоб сигналізувати про закінчення списку аргументів. Це може бути або
- спеціальне значення термінатора, або
- довжина списку vararg, передана як додатковий параметр.
Обидва ці механізми можуть бути використані в контексті currying для реалізації varargs, але правильне введення тексту стає головною проблемою. Припустимо, що ми маємо справу з функцією sum: ...int -> int
, за винятком того, що ця функція використовує currying (тому ми насправді маємо тип більше подібний sum: int -> ... -> int -> int
, за винятком того, що ми не знаємо кількості аргументів).
Випадок: значення термінатора: Дозвольте end
бути спеціальним термінатором і T
бути типом sum
. Тепер ми знаємо , що стосовно end
функції повертає: sum: end -> int
і, що застосовуються до міжнар ми отримуємо іншу суму-як функція: sum: int -> T
. Тому T
є об'єднання цих типів: T = (end -> int) | (int -> T)
. Підстановкою T
, ми отримуємо різні можливі типи , такі як end -> int
, int -> end -> int
, int -> int -> end -> int
і т.д. Тим НЕ менше, більшість систем типу не враховують таких типів.
Випадок: явна довжина: Перший аргумент функції vararg - це кількість vararg. Так sum 0 : int
, sum 1 : int -> int
і sum 3 : int -> int -> int -> int
т. Д. Це підтримується в деяких типах систем і є прикладом залежного введення тексту . На насправді, кількість аргументів буде параметр типу , а не звичайний параметр - це не мало б сенс для арності функції залежить від значення у час виконання, s = ((sum (floor (rand 3))) 1) 2
очевидно , погано надрукували: це має значення або s = ((sum 0) 1) 2 = (0 1) 2
, s = ((sum 1) 1) 2 = 1 2
або s = ((sum 2) 1) 2 = 3
.
На практиці жодна з цих методик не повинна використовуватися, оскільки вони схильні до помилок і не мають (значущого) типу в системах загального типу. Замість цього, просто передати список значень в якості одного параметра Я : sum: [int] -> int
.
Так, можливо, об'єкт може відображатися і як функція, і як значення, наприклад, у системі типів з примусами. Нехай sum
буде a SumObj
, який має два примуси:
coerce: SumObj -> int -> SumObj
дозволяє sum
використовувати як функцію, і
coerce: SumObj -> int
дозволяє нам отримати результат.
Технічно це зміна випадку значення значення термінатора, описаного вище, з T = SumObj
і coerce
не розгортаючий тип. У багатьох об'єктно-орієнтованих мовах це тривіально реалізується при перевантаженні оператора, наприклад, C ++:
#include <iostream>
using namespace std;
class sum {
int value;
public:
explicit sum() : sum(0) {}
explicit sum(int x) : value(x) {}
sum operator()(int x) const { return sum(value + x); } // function call overload
operator int() const { return value; } // integer cast overload
};
int main() {
int zero = sum();
cout << "zero sum as int: " << zero << '\n';
int someSum = sum(1)(2)(4);
cout << "some sum as int: " << someSum << '\n';
}