함수가 순수한 경우 계산


11

Wikipedia에 따라 :

컴퓨터 프로그래밍에서, 함수에 관한이 두 문장이 모두 유지되면 함수는 순수한 것으로 설명 될 수 있습니다. 함수는 항상 동일한 인수 값이 주어지면 동일한 결과 값을 평가합니다. 기능 결과 값은 프로그램 실행이 진행됨에 따라 또는 프로그램의 다른 실행간에 변경 될 수있는 숨겨진 정보 또는 상태에 의존 할 수 없으며 I / O 장치의 외부 입력에 의존 할 수도 없습니다. 결과의 평가는 변경 가능한 객체의 돌연변이 또는 I / O 장치로의 출력과 같이 의미 적으로 관찰 가능한 부작용 또는 출력을 유발하지 않습니다.

함수가 순수한지 여부를 계산하는 함수를 작성할 수 있는지 궁금합니다. 자바 스크립트의 예제 코드 :

function sum(a,b) {
    return a+b;
}

function say(x){
    console.log(x);
}

isPure(sum) // True
isPure(say) // False

7
이것은 Computer Science Stack Exchange 의 후보 일 수 있습니다 . 이것은 실용적이고 디자인적인 것이 아니라 이론의 영역 ( "가능")에 더 가깝다.

... "가능"하고 "이론"임에도 불구하고 증거와 관련 될 수있는 실제 답변 (Q & A에 적합)이있을 가능성이 매우 높습니다. 다시 컴퓨터 과학 세계로 되돌아갑니다. .

정의에서 호출 된 함수 유형을 보면 함수가 순수한지 여부를 결정할 수 있다고 생각합니다. 함수 구조에 대해 유도함으로써 순도를 정의 할 수 있습니다.
조르지오

7
플랫폼 별 리플렉션 해킹이 없으면 할 수 없습니다. 함수가 블랙 박스 인 경우 실험 이 순수함을 입증 할 수 없습니다 . 예를 if (rand(1000000)<2) return WRONG_ANSWER들어와 같은 것이 있으면 일관된 동작을 위해 함수를 여러 번 조사해도 도움이되지 않습니다. 그러나 함수 정의에 액세스 할 수 있으면 증거는 간단합니다.
SK-logic

1
@ user470365 순수한 함수정의에서 - "결과를 평가해도 변경 가능한 객체의 돌연변이 나 I / O 장치로의 출력과 같이 의미 적으로 관찰 가능한 부작용이나 출력이 발생하지 않습니다." -IO에 쓰는 것은 정의상 불완전합니다. 이 예에서는 불순한 say호출 도 불완전합니다. console.logsay

답변:


17

예, 언어에 따라 가능합니다.

JavaScript에서는 다음 기준에 따라 함수가 순수한지 알 수 있습니다.

  • 매개 변수와 로컬 만 읽습니다.

  • 현지인 만 쓴다.

  • 비 로컬에서는 순수한 함수 만 호출합니다.

  • 암시 적으로 호출하는 모든 함수는 순수합니다 (예 : toString; 과

  • 지역이 아닌 지역의 별칭이 아닌 지역의 속성 만 작성합니다.

일반적인 경우에는 JavaScript에서 앨리어싱 을 결정할 수 없습니다 object["property"]. 객체의 속성을 항상 동적으로 조회 할 수 있기 때문입니다 ( ). 당신이 그렇게하지 않고 전체 프로그램의 출처를 가지고 있다면 문제가 다루기 쉽다고 생각합니다. 또한 console.logDOM과 관련하여 또는 대부분의 부작용과 같은 기본 기능에 대한 정보가 필요 합니다.

"순수한"이라는 용어는 약간의 설명을 사용할 수도 있습니다. 모든 함수가 참조 적으로 투명한 강력하고 정적으로 형식이 지정된 순수하게 기능적인 프로그래밍 언어 일지라도 함수가 여전히 종료되지 않을 수 있습니다. 우리가 이야기 할 때 id :: a -> a실제로 말하는 것은 아닙니다.

type 값이 주어지면 a함수 id는 type 값을 생성합니다 a.

그러나 오히려 :

유형의 일부 값이 주어지면 a함수 id는 유형 이 아닌 값을 생성 하지 않습니다 .a

의 올바른 구현은 id입니다 error "Not implemented!". Peteris가 지적한 바와 같이,이 비 합계 성은 일종의 불순으로 보일 수 있습니다. Koka 는 JavaScript로 모델링 된 구문을 가진 기능 프로그래밍 언어로, 분기 (비 종료), 참조 투명성, 예외 발생 및 I / O 작업과 같은 가능한 효과를 유추 할 수 있습니다.


한 - Peteris으로 대답을 감안할 때이 ..... 너무 많은 upvotes있어
mattnz

기준 목록에 "순수 함수 만 호출"을 추가해야한다고 가정합니다.
Greg Hewgill

1
@GregHewgill : 잘 잡았습니다. 이에 따라 답변을 업데이트했습니다. 부작용이없는 한 현지인에서 돌연변이 기능 을 호출 하는 것이 좋습니다. “순수한”용어에 과부하가
걸린다

또한 toString문자열로 사용하는 객체에 순수한 것인지 확인해야 합니다.
Oleg V. Volkov

실제로 이러한 결정을 내릴 수있는 상황의 하위 집합 만 있기 때문에이 답변이 정확하지 않다고 생각합니다. 이 기능이 순수합니까? function a (o) { return o.method(); }- o전달 된 매개 변수에 따라 다르므로 실제로 응답 할 수 없습니다 . 또한, 이전에 인증 된 순수 함수가 순수가 아닌 구현으로 변경된 경우 발생하는 상황을 설명 할 수 없습니다. 이는 항상 자바 스크립트의 잠재적 인 문제입니다.
Jules

11

아니요. Jon Purdy의 답변에 설명 된대로 함수가 "순수 안전"작업 만 수행하는지 쉽게 확인할 수 있지만 IMO가 질문에 대답하기에 충분하지 않습니다.

이 기능을 고려하십시오.

function possiblyPure(x) {
    if (someCheck(x)) {
        return x+1; // pure code path
    }
    else {
        console.log("I'm so unpure..."); // unpure code path
    }
}

분명하지 someCheck않다면, 그렇습니다 possiblyPure. 그러나, 경우는 someCheck순수 반환 true의 모든 가능한 값은 x, possiblyPureunpure 코드 경로에 연결할 수 있기 때문에, 순수!

그리고 여기에 어려운 부분이 있습니다. someCheck가능한 모든 입력에 대해 true를 반환 할지 여부를 결정합니다 . 그 질문에 대답하려고하면, 멈춤 문제와 비슷한 결정 불가능한 문제의 영역으로 이끌게됩니다.

편집 : 불가능하다는 증거

순수한 함수가 가능한 모든 입력에서 종료되어야하는지에 대한 불확실성이 있습니다. 그러나 두 경우 모두 중지 문제를 사용하여 순도 검사가 불가능하다는 것을 알 수 있습니다.

순수한 기능이 가능한 모든 입력에 종료해야하는 경우 케이스 A)는, 당신은 함수가 순수 여부를 결정하기 위해 정지 문제를 해결하기 위해. 이것이 불가능한 것으로 알려져 있기 때문에,이 정의에 따르면, 순도는 계산 될 수 없다.

사례 B) 일부 입력에서 순수 함수가 종료되지 않는 경우 다음과 같이 구성 할 수 있습니다 . 순수 함수를 정의하는 문자열 인지 isPure(f)계산 f합니다.

function halts(f) {
   var fescaped = f.replace(/\"/g, '\\"');
   var upf = 'function() { '+f+'("'+fescaped+'\); console.log("unpure"); }';
   return isPure(upf);
}

이제 자체 소스를 입력으로 중지 isPure할지 여부를 결정해야합니다 f. 그것이 멈 upf추면 불공평하다. 종료되지 않으면 순수합니다. upfiff f는 순수합니다.

경우 isPure예상 (모든 입력에 반환 정확한 결과 및 종료)로 일했다, 우리는 중단 문제 (*)를 해결 한 것입니다! 이것은 불가능한 것으로 알려져 있기 때문에 isPure존재할 수 없습니다.

(*) 순수 JavaScript 함수의 경우 튜링 머신에서도 해결할 수 있습니다.


3
진실. 보수적 인 분석 을 수행하는 것이 항상 가능 합니다. 함수가 확실히 순수한지 확인하지만 그것이 확실하지 않은지를 확인하는 것은 불가능합니다.
SK-logic

Jon Purdy가 묘사 한 순수한 기능이나 무조건 더러운 것을 행하는 불순한 기능; 그러나 일반적으로 결정 불가능한 사례를 구성 할 수 있습니다.
user281377

1

이 stackoverflow 질문 에는 여기에 관련된 yfeldblum의 답변이 있습니다. (그리고 어떤 이유로 든 내가 추론 할 수없는 공감대가있다. 3 살짜리 물건을 공표하는 것은 나쁜 예절 일까?)

실용적인 관점에서 함수가 yes, no 또는 어쩌면 반환하도록하면 일부 언어에서는 그렇게 어렵지 않을 것이라고 생각합니다. 저는 며칠 전에 Clojure에 관한 비디오를보고 있었는데, 화자는 약 4 개의 다른 문자열 (예 : "ref")을 검색하여 코드베이스에서 수많은 불순한 인스턴스를 수행했습니다. Clojure의 불순한 물건의 순도 및 분리에 중점을두기 때문에 사소한 것이었지만 원하는 것이 아닙니다.

따라서 이론적으로 불가능하고 실제로 질문을 약간 조정하면 실제로 가능하며 언어에 따라 얼마나 어려운지 생각합니다. 불변성과 좋은 반성에 중점을 둔 단순하고 깨끗한 언어는 더 쉬울 것입니다.


나는 그것이 잘못 되었기 때문에 downvoted되었다고 생각합니다. bottom유효한 일류 가치이며, 이런 식으로 차별받을 가치가 없습니다.
SK-logic

0

좋은 질문입니다.

가능한 한 여러 번 함수를 호출하기 위해 i / o 조치를 듣지 못하는 경우를 가정하여 실제로 수행 할 수있는 최선의 방법입니다. 그런 다음 반환 값이 일치하는지 확인하십시오.

그러나 당신은 일반적으로 이것을 할 수 없습니다. 비 정지 프로그램은 순수하지 않으며, 정지 문제를 결정할 수 없습니다.


1
-1 :이 테스트를 통과하고 순수한 기능을 작성하는 것은 사소한 일이 아닙니다.
mattnz

3
이 논리에 따르면 모든 void기능은 "순수"하며 이는 명백히 거짓입니다.
Greg Hewgill

1
@Greg : 확장하면 void foo (void)도 순수해야합니다.
mattnz

0

일반적인 경우에는 불가능합니다. 정지 문제를 참조하십시오 . 간단히 말해서, 임의의 기능과 입력이 주어지면 프로그램이 언제 중단 될지 또는 영원히 실행될지를 결정하는 프로그램을 작성할 수 없습니다. 그것이 영원히 실행된다면, 그것은 당신이 준 정의에 맞는 순수한 기능 이 아닙니다 .


5
영원히 실행한다고해서 함수가 순수 함수에 대한 기준을 맞추는 것보다 할인되는 것은 아닙니다.
whatsisname

+1 : 함수가 "함수는 항상 같은 결과 값을
주는데

2
상태를 수정하지 않고 지속적으로 계속 실행하는 것은 완벽하게 "순수"합니다. 그러나 여기서는 용어 문제입니다.
SK-logic

@ mattnz, 이러한 함수는 항상 bottom값으로 평가됩니다 .
SK-logic

1
용어 문제가 어디에서 나오는지 알 수 있습니다. 일부 해석에서 "순수한"기능은 결정적이며 실행 중에 외부와 어떤 상태 나 값도 전달하지 않는 기능입니다. 다른 해석에서는 정지가 요구 사항에 추가됩니다. 첫 번째 해석에서는 함수가 순수한지 쉽게 판단 할 수 있습니다. 특정 언어를 실행하는 기계는 해당 언어의 프로그램이 외부와 통신하는지 판별 할 수 있어야합니다.
rwong
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.