F # 컴파일러는 다른 유형이 이후에 호출되는 함수를 통해 다른 경로를 암시하는 함수를 호출하여 코드 경로를 구분할 수 있습니까?F # 컴파일러는 currying을 사용하여 유형에 따라 코드 경로를 구분할 수 있습니까?
다음과 같은 구분 된 합집합을 고려하십시오. 이론적으로 서로 다른 종류 2 가지 가능성이있다 :
type Choice =
| Halve
| Double
우리는 이러한 경우 중 일부에 대한 몇 가지 특정 기능이 있다고 가정 : 2 개 별도의 코드 경로를 제공
let halve value = value/2.0
let divide value = value * 2.0
그리고이 기능 유형에 따라 하
let inner param value =
match param with
| Choice.Halve -> halve value
| Choice.Double -> divide value
let outer param value =
let internalVariable =
match param with
| Choice.Halve -> "halving"
| Choice.Double -> "doubling"
inner param value
[<EntryPoint>]
let main argv =
printf "%g\n" (outer Choice.Halve 4.0)
let doubler = outer Choice.Double
printf "%g\n" (doubler 6.0)
이등분 더블 따라서 별도의 코드 경로이며, 우리는 수 : 일부 param
의 (잔부 FS 파일을 완료) 그들을 두 개의 분리 된 기능으로 작성했습니다.
이론적으로 말하자면, 두 가지 다른 기능이 있다고 말합니다. Choice.Halve 또는 Choice.Double 유형 (예 : doubler
) 중 첫 번째 매개 변수를 카레하면 해당 유형에 맞는 함수가 있고 컴파일러는 나중의 분기를 최적화 할 수 있어야합니다.
그런 경우입니까?
일리노이를 살펴보면 이러한 최적화는 볼 수 없지만 JITted 일 가능성이 있습니다. 동료는 분기 예측이 그러한 최적화를 필요로하지 않는다고 제안합니다.
불필요한 가지를 피하여 구조를 뒤집고 divide
/halve
함수를 전달하는 유일한 방법은?
- 편집 -
존 팔머는 inline
를 추가 할 것을 제안했다, 그래서 나는 그것을 시도하고 outer
에 대해 다음과 최적화 된 IL을 가지고 :
IL_0001: ldarg.0
IL_0002: call instance int32 Program/Choice::get_Tag()
IL_0007: ldc.i4.1
IL_0008: bne.un.s IL_0016
IL_000a: ldarg.1
IL_000b: ldc.r8 2
IL_0014: mul
IL_0015: ret
IL_0016: ldarg.1
IL_0017: ldc.r8 2
IL_0020: div
IL_0021: ret
그러나, doubler
카레의 명백한 최적화가 없다 함수는 main
에 있습니다 - 따라서 uncurried 함수는 최적화되었지만 카레 함수는 최적화되지 않았습니다. ,
let inner param =
match param with
| Choice.Halve -> (fun value -> halve value)
| Choice.Double -> (fun value -> divide value)
이 기능
원래 기능과 같은 방식으로 사용할 수 있습니다
어떤 함수에 대해서도'inline'을 사용해 보셨습니까? –