2012-09-20 8 views
6
let inline myfunction x y = ... 

let inline mycurried = myfunction x // error, only functions may be marked inline 

명시 적으로 inline 카레 기능이 불가능한 것처럼 보입니다. mycurried이 호출 될 때마다 myfunctioninlined이라도 정확하게 inlined이되지 않습니다. 맞습니까?인라인 할 수있는 포인트없는 기능 이었습니까?

이렇게 카레 기능의 단점 중 하나로 간주 될 수 있습니까?

답변

5

내가 당신의 질문 point-free 함수가 인라인 여부를 할 수 있는지 여부라고 생각합니다.

발견 한 제한은 카레 기능 때문이 아닙니다. 귀하의 예제에서 카레 기능은 오른쪽에, 왼쪽에는 포인트가없는 기능이 있음에 유의하십시오.

F #은 함수가 상수가 아닌 인라인 만 허용합니다.

원칙적으로 타입 유추가 똑똑해서 (포인트없는) 함수임을 알 수 있지만 부작용에 대해서는 Tomas의 노트를 읽으면 버그라고 생각할 수 있습니다.

컴파일러 좌측은이 오류 실패 만 식별자 발견 명백하게 때

let inline myfunction x y = x + y 

let inline mycurried = myfunction 1 

--> Only functions may be marked 'inline' 

브라이언 대안 양측에 명시 적 매개 변수를 추가하는 것을 특징 같이

let inline mycurried x = (myfunction 1) x 

그러나 귀하의 기능은 더 이상 포인트가 없으며 다음과 동일합니다 :

let inline mycurried x = myfunction 1 x 

일반적인 매개 변수는 왼쪽에 명시 적으로 존재하는 경우

let inline mycurried<'a> = myfunction 1 

가 컴파일 : 또 다른 방법은 명시 적 제네릭 매개 변수를 추가 할 수 있습니다. 당신의 대답 (그리고 downvote)에 대한

Since only functions can be 'inline' this value will be compiled as a function. 

UPDATE

감사 토마스 :

나는 그들이 같은 것을 오류 메시지를 제거하고 그것에게 경고를 켜 바랍니다.

내 개인 의견은 경고 여야하므로 코드의 의미가 결국 변경 될 것이라는 것을 알고 있으므로 어떻게 할 것인지 결정해야합니다.

당신은 인라인 "그냥 최적화"입니다하지만 그건 완전히 사실이 아니다라고 :

. 단순히 모든 인라인 함수를 돌리는 것만으로도 최적의 코드가 보장되는 것은 아닙니다.

. 정적 제약 조건을 사용하려는 경우 인라인을 사용해야합니다.

F # 라이브러리가 이미 수행 한 것처럼 (일종의 GenericZero 및 GenericOne) 내 (종류) 일반 상수를 정의 할 수 있기를 바랍니다. 내 코드가 순수하다는 것을 알기 때문에 매번 실행되는지는 신경 쓰지 않습니다.

+0

let 바인딩을 _value_ ('let x = ...')에서 _function_ ('let x arg = ...')로 변경하면 함수의 의미를 변경할 수 있습니다. 함수에는 몇 가지 효과가 있습니다. 첫 번째 경우에는 효과가 한 번 평가되고 두 ​​번째 경우에는 반복적으로 평가됩니다. 효과를 한 번만 평가하려면 '인라인'을 사용할 수 없습니다. 여러 번 실행하려면 추가 매개 변수를 추가하는 것이 적절하다고 생각합니다. –

+0

일반적인 매개 변수를 추가하는 것은 여전히 ​​값처럼 보이지만 실제로는 함수로 작동하므로 (즉, 효과가 반복적으로 평가되므로) 매우 미묘합니다. 따라서 권장하지 않습니다. (실제로 컴파일러의 향후 버전에서는 모든 제네릭 형식 인수에 대해 한 번만 효과를 평가할 수 있습니다.) 즉, 실제로 동작이 실제로 정의되지 않았 음을 확신합니다. –

+0

오류 메시지는 (하스켈과 같은) 순수 언어에서는 의미가 없지만,'inline'을 추가 할 때 우연히 프로그램 동작을 변경하지 못하도록 막는 것이 아주 좋은 결정이라고 생각합니다. –

4

나는 그냥 (나는 시도하지 않은하지만) 양쪽에 명시 적으로 매개 변수를 추가 할 필요가 있다고 생각 :

let inline myfunction x y = ... 

let inline mycurried y = myfunction 42 y // or whatever value (42) 
2

컴파일러는 함수를 정의하는 let 바인딩에 대해서만 inline을 허용합니다. 이것은 본질적으로 with F# value restriction (그리고 also here 참조)의 상황과 같습니다. Brian이 말했듯이, 함수에 매개 변수를 추가하면 쉽게 해결할 수 있습니다.

왜 이러한 제한이 존재합니까? 그것이 없다면, inline을 추가하면 프로그램의 의미가 바뀌고 그것은 나쁠 것입니다! 이제 다음 코드

let createCounter n = 
    let state = ref n 
    (fun() -> incr state; !state) 

:

let counter = createCounter 0 

이 ... 생성을 예를 들어

, 당신은 (카운터 기능을 변경할 상태를 만들고 반환)이 같은 함수가 있다고 가정 해 여러 번 사용할 수있는 단일 전역 함수 ( counter())와 1부터 시작하는 고유 한 정수를 제공합니다. inline :

0123으로 표시 할 수있는 경우

... counter()을 사용할 때마다 컴파일러가이를 createCounter 0()으로 바꾸어야하므로 카운터를 호출 할 때마다 1이됩니다.

+0

네 말이 맞아. 사실 내가 언급 한 트릭을 인라인으로 컴파일 할 수 있습니다. 인라인 카운터를 사용합시다 <'a> = ...... 어쨌든 컴파일 오류보다 경고를 선호하고 해결 방법/트릭에 의존해야합니다. – Gustavo

+0

@ Gustavo 필자는 인라인 (실제로는 단지 최적화)이 코드의 의미를 변경할 때 컴파일러 오류를 얻는 것이 공평하다고 생각합니다. 이 오류는 컴파일러가 인라인 값을 가져 오지 못한다는 것을 알려줍니다 (아주 잘 이해할 수 있습니다). 값을 함수로 바꾸기를 원한다면, 명시 적으로해야한다. 왜냐하면 이것이 당신에게 원하는 의미를 부여하는지 생각해야하기 때문이다. –

+0

@Gustavo 예,'let inline counter <'T> = createCounter 0'이라고 쓰면 코드를 컴파일 할 수 있습니다. 'counter <_>()'을 호출 할 때 항상 '1'을 얻는다는 뜻이며 이것은 의도 한 행동이 아닙니다. –