2011-12-20 2 views
5

TDPL, p. 167 :이 순수 함수가 비공개 상태를 어떻게 수정할 수 있습니까?

한 함수에서 가변 상태 완전히 그대로 일시적인 (즉, 스택에 할당) 및 전용 (즉, 그 더러운 수 함수를 참조하여 함께 전달되지 않음), 그 기능은 순수한 것으로 간주 될 수 있습니다. 이 스택에, 올바른 때문에

import std.stdio : writeln; 

struct M{ 
    int[4] _data; 

    pure ref int opIndex(size_t i){ return _data[i]; } 
} 

pure M foo(ref M m){ 

    m[0] = 1234; 
    return m; 
} 

void main(){ 

    M m1 = M([7, 7, 7, 7]); 

    writeln(m1); 
    foo(m1); 
    writeln(m1); 
} 

// output: 
// M([7, 7, 7, 7]) 
// M([1234, 7, 7, 7]) 

변경이 용이 한 상태가 일시적입니까? 그러나 그것은 사적인 것이 아닙니다. 그렇다면 은 어떻게 수정 가능합니까 m1?

+0

필자는 [태그 : 순수] 태그를 정리하려고 시도했습니다. 때로는 순수 가상 함수, 때로는 [순수] (http://beebole.com/pure/) 및 때때로 [순수] ] (http://en.wikipedia.org/wiki/Pure_(programming_language)) 등이 있습니다. 하지만 [태그 : d]에 대해서는 아무 것도 모릅니다. 내 태그 편집이 적절한 지 확인할 수 있습니까? 이 질문에 대해 [태그 : 순전히 기능을 수행 할 수 있습니까] - [태그 : 순수 함수]를 만들었으므로 [태그 : 순전히 기능]이 작동하면 기존 태그를 사용하는 것이 더 좋을 것이라고 생각합니다. –

+0

@RichardJPLeGuen [기능적 순도] (http://en.wikipedia.org/wiki/Pure_function)에서와 같이 순전히 순수한 함수가이 질문에 대해 작동합니다. 순전히 기능적이지, 순전히. – Arlen

+0

고마워, @ 알렌! –

답변

6

pure은 TDPL 릴리스 이후 조금 확장되었습니다. TDPL이 설명하는대로 pure은 단순한 수학 함수 등을 넘어서는 유용성이 너무 제한적임을 나타냅니다. 당신은 현재의 정의를 the online documentation 볼 수 있지만, 기본적으로이 내려 온다 :

이 이
    pure 기능은 모든 모듈 수준 또는 프로그램의 과정에서 변이 될 수 정적 변수에 액세스 할 수 없습니다

  1. 이 (가 있어야합니다 const 값 유형 또는 pure 함수에서 액세스 할 immutable).

  2. pure 함수는 pure이 아닌 함수를 호출 할 수 없습니다.

  3. pure 함수는 I/O를 수행 할 수 없습니다.

그렇습니다. 다른 제한 사항은 없습니다. 그러나 함수를 최적화 할 경우 명령문에서 여러 번 사용 되더라도 한 번만 호출되도록 추가 제한이 필요하므로 입니다. 즉 :

  • 함수의 매개 변수는 immutable 또는 immutable에 암시 적으로 변환해야합니다.(const 매개 변수와 함수가 immutable 인자가있을 때 최적화 할 수 있도록),하지만 함수의 인수가해야한다는 요구로 확장 될 수있는 이론적으로

immutable 또는 immutable에 암시 적으로 변환이 현재이 아니다 경우.

이러한 pure 기능은 때때로 "강하게"pure이라고 불리는 반면, 최적화 할 수없는 기능은 "약하게"pure이라고합니다. TDPL은 강력하게 pure 기능을 설명합니다. pure을 좀더 일반적으로 사용할 수 있도록 약한 pure 함수가 추가되었습니다.

약하게 pure 기능 자신의 인수를 변경할 수 있지만, 그들은 글로벌 상태를 변경할 수 없습니다, 그래서 그들은 (가 인수를 변경하지 수있는) 강력 pure 함수를 호출 할 때, 강하게 pure 그 보증 함수의 반환 값은 동일한 인수에 대해 항상 동일합니다. 본질적으로 약한 pure 함수는 전역 상태를 변경시킬 수 없으므로 호출자가 호출 한 강력한 pure 함수의 개인 상태 중 일부입니다. 따라서 Andrei가 5.11.1.1 절에서 설명하는 내용과 매우 흡사합니다. purepure입니다. TDPL에서입니까? 단, 전역 상태를 변경하지 않고 개인 상태를 변경할 수있는 함수를 허용하도록 함수의 개인 상태가 확장되었습니다. .

pure과 관련하여 TDPL 이후로 추가 된 또 다른 중요한 메모는 기능 속성 유추입니다. pure, nothrow@safe은 템플릿 기능에 대한 것으로 추측됩니다 (일반적인 기능의 경우 은 아님). 따라서 템플릿 기능 일 수 있고 pure 일 경우, 이제 pure입니다. 순도는 인스턴스화 된 내용에 따라 다릅니다. 따라서 pure을 템플리트 화 된 함수와 함께 사용할 수있게되는 반면, 전에는 보통 수 없습니다. 왜냐하면 여러분이 그것을 pure으로 만들면 불순한 함수와 함께 작동하지 않기 때문입니다. 그러나 이 아니고 pure으로 만들면 pure 함수와 함께 사용할 수 없으므로 pure의 주요 문제였습니다. 다행히도, 속성 유추가 지금은 그것을 수정합니다. 템플리트 된 함수가 인스턴스화 될 때 위에 나열된 규칙을 따르는 한, pure으로 간주됩니다.

+0

필자는이 문제를 해결하기 위해''pure void opIndexAssign (T value, size_t i) {...}'와''pure T opIndex (size_t i) const {... '와 같은 것에 익숙해 져야한다고 생각합니다.}' – Arlen

+0

'pure'는 함수가 변경 가능한 전역 상태에 액세스 할 수 없다고 생각한 다음 가능한 경우 컴파일러에서 최적화 할 수 있도록합니다. 예, '순수한'수정자는 기능적으로 '순수한'것보다 많은 기능을 끝내지 만 기능적으로 '순수한'기능을 가능하게하고 최적화 할 수있는 기능은 여전히 ​​남아 있습니다. –

5

this 참조는 함수의 매개 변수의 일부로 간주되며 약한 순수 함수이므로 매개 변수를 수정할 수 있습니다. this의 상태가 입력의 일부로 간주되면이 기능은 동일한 입력으로 동일한 출력을 갖는 조건을 여전히 충족시킵니다. TDPL가 릴리스 된 후에

import std.stdio : writeln; 

struct S 
{ 
    int foo = 0; 
    pure void set(size_t i){ foo = i; } 
} 


void main() 
{ 
    S s; 
    s.set(2); 
    writeln(s.foo); 
} 

는 지금까지 내가 아는 한, 순수의 정의가 확장되었다 :

2 출력이 완전히 법적 예를 생각해 보자. 이 책은 강력하고 순수한 기능을 설명합니다. 그 후 두 가지 개발이 이루어졌습니다. 약한 순수 함수가 추가되어 매개 변수가 변경되었습니다. 또한 템플릿 함수가 pure으로 꾸며지지 않은 경우에도 순결하다면 템플릿 함수의 인스턴스화를 사용할 수 있도록 pure-inference가 템플릿 함수에 추가되었습니다.