varargs는 어떻게 구현할 수 있습니까? 인수 목록의 끝을 알리는 메커니즘이 필요합니다. 이것은 둘 중 하나 일 수 있습니다
- 특수 종결 자 값 또는
- 추가 매개 변수로 전달 된 vararg 목록의 길이
이러한 메커니즘은 커링의 맥락에서 varargs를 구현하는 데 사용될 수 있지만 올바른 타이핑이 주요 문제가됩니다. sum: ...int -> int
이 함수가 카레를 사용한다는 점을 제외하고 함수를 다루고 있다고 가정 해 봅시다 (따라서 sum: int -> ... -> int -> int
인수의 수를 모르는 것을 제외하고 는 실제로 더 비슷한 유형이 있습니다 ).
사례 : 종결 자 값 : end
특수 종결자가 T
되고 유형입니다 sum
. 우리는 이제 end
함수에 적용하면 다음을 반환 한다는 것을 알고 있습니다 sum: end -> int
. int에 적용된 것은 또 다른 sum-like 함수를 얻습니다 sum: int -> T
. 따라서 T
이러한 유형의 결합은 다음과 같습니다 T = (end -> int) | (int -> T)
.. 대체하여 T
, 우리는 다음과 같은 가능한 다양한 종류의 수 end -> int
, int -> end -> int
, int -> int -> end -> int
, 등 그러나, 대부분의 타입 시스템이 같은 유형을 수용하지 않는합니다.
사례 : 명시 적 길이 : vararg 함수의 첫 번째 인수는 varargs의 수입니다. 그래서 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
있는을 보자 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';
}