Today ()가 불순한 함수의 예인 이유는 무엇입니까?


38

"순수 함수"에 대한이 Wikipedia 기사 와 같은 내용을 읽을 때 Today()불순한 함수의 예로 나열 되어 있지만 그것은 나에게 순수한 것 같습니다. 공식적인 입력 인수가 없기 때문입니까? 실제 시간이 "함수 입력"으로 처리되지 않는 이유는 무엇입니까? 동일한 입력을 한 경우 (예 : today()동시에 두 번 실행 했거나 다시 실행하기 위해 시간을 거슬러 이동 한 경우) ), 출력은 같은 시간입니다. Today()난수를 절대로주지 않습니다. 그것은 항상 당신에게 시간을 제공합니다.

Wikipedia 기사에 따르면 "다른 시간에 따라 다른 결과가 나올 수 있습니다"라고 말하지만 x sin(x)다른 비율로 다른 말을하는 것과 같습니다 . 그리고 sin(x)순수한 기능의 예입니다.


8
하루 중 시간이 지났다면 기능은 어떻게됩니까?
JB King

1
나는 그것이 당신에게 시간을 줄 것으로 기대합니다. (가장 유용한 기능은 아님). 그러나 그것은 논쟁의 여지가 없다. 나는 대답의 근본이라고 생각한다.
Brad

3
제공 한 입력 매개 변수를 기반으로 출력을 예측할 수 있습니까?
Daniel B

1
@DanielB 없음 / 널 입력 매개 변수에는 예측력이 없습니다. 내가 할 수있는 유일한 일은 내 손목 시계 (jk 휴대 전화)를 보는 것입니다.
Brad

"실제 시간이"기능 입력 "으로 취급되지 않는 이유는 무엇입니까? 이것은 기본적으로 모나드가 해결하려고하는 문제입니다. 순수한 기능은 입력을 기반으로 할 수 있으며 부작용이 없습니다. "나보다 전 세계의 상태"를 입력 값으로, "나보다 뒤의 세계 상태"를 반환 값의 일부로 만들고이 세계 상태를 프로그램을 통해 전달하면 다시 순수해질 수 있습니다.
Sean McSomething

답변:


103

공식적인 입력 인수가 없기 때문입니까?

출력은 입력이 아닌 무언가, 즉 현재 시간에 의존하기 때문입니다.

실제 시간이 "기능 입력"으로 취급되지 않는 이유는 무엇입니까?

매개 변수로 전달하지 않았기 때문입니다. 매개 변수로 전달하면 날짜에 함수가 ID 함수가되어 매우 쓸모가 없습니다. Today()함수 의 전체 요점은 외부적이고 지속적으로 변화하는 값 (시간)에 따라 무언가를 출력하는 것입니다.

순수한 기능의 장점은 그들의 행동이 절대적으로 재현 가능하고 결정 론적이며 공식적인 증거와 확실한 보증을 쉽게 할 수 있다는 것입니다. 그들은 항상 같은 일을합니다. Today()항상 정반대입니다 : 항상 (시간 세분화를 허용) 다른 일을합니다.


2
따라서 현실의 시간은 일종의 입력이지만 입력으로 제공되지 않고 함수의 제어 외부에 있습니다 (함수 내부와 호출하는 사람의 제어 외부 Today()) Today()는 불완전합니다. 이 Today()함수는 약간 어리석은 예일 수 있습니다. 일부 Count()기능 이 더 적합 할 수 있습니다 . 계산할 항목 수가 동일 Count()하면 항상 같은 수를 반환하지만 그 범위를 벗어난 Count()것은 불완전합니다.
브래드

1
@brad 그것은 다소 회색 영역입니다-암시 적 실제 인수가 있습니다-배열 또는 목록. 불변 목록과 매번 같은 인수가 주어지면 항상 같은 값을 반환합니다.
Max

34
"현실의 시간은 일종의 입력입니다"-예; 실제로, 전역 상태는 모든 기능에 암시 적으로 사용 가능합니다 (즉, '입력 정렬'). 그러나 결과에 의존 하면 불완전합니다!
AakashM

4
count()대부분의 프로그래밍 언어에서 @Brad 는 순수합니다. 여기에는 명시적인 입력 값이 있습니다. 개수를 원하는 모음입니다. myCollection.count(); 와 같은 구문으로 혼동하지 마십시오 . 그것은 단지 설탕입니다 count(myCollection).
Andres F.

항상 그렇듯이 훌륭한 답변이지만 불변의 자유 변수를 명시 적으로 다루지는 않습니다. 그것들은 함수에 대한 입력이 아니며 매개 변수로 전달되지는 않지만 여전히 참조가 투명하더라도 함수에 의존합니다.

24

sin(x)동일하게 x유지되는 한 항상 동일한 값을 반환합니다 . 제어 범위 밖의 값에 의존Today() 하기 때문에 시간이 지남에 따라 다른 결과를 반환 할 수 있습니다 . 예를 들어, 프로그램이 제어 할 수없는 무언가 가 프로그램이 실행되는 $current_datetime 동안 시스템의 내부 변경 Today()하면 갑자기 다른 결과가 나타납니다.


"항상 다른 값을 반환하는 것은"조금 ...이다 불순한의 표현. Wikipedia에 따르면 "현재 요일을 반환합니다"는 월요일에 얻은 값이 다르지 않음을 의미합니다.
gnat

7
@gnat : 프로그램 외부에서 무언가가 컴퓨터의 내부 캘린더를 변경하여 갑자기 목요일이라고 생각 하지 않는 한, 사실 입니다. 그런 다음 전화 Today()는 월요일에 "목요일"을 반환합니다.
FrustratedWithFormsDesigner

3
@gnat 글쎄, 항상 다른 값을 반환하지는 않습니다 (유용한 기능은 거의 없습니다). 그러나 대부분의 불순 함수와 마찬가지로 반환 값은 단일 프로그램을 실행하는 동안에도 (예 : 밤새 실행하는 경우) 달라질 수 있습니다.

3
@delnan : 그렇습니다. 순진한 데이터베이스 스크립트 작성자의 골칫거리입니다! : P "하지만 어떻게 300 개의 레코드를 놓칠 수 있습니까? 어제 아침에 테스트했을 때 스크립트가 제대로 작동했습니다!"
FrustratedWithFormsDesigner

@delnan 확실합니다. 나는 단지 초기 단어에서 항상 사용하는 것이 (현재 버전의 답변에서 할 수 있음 ) 다소 부정확 하다고 지적했다.
gnat

13

Today ()는 결과가 사용자가 제공하지 않은 것에 의존하기 때문에 불순한 함수입니다. 특히 현재 시스템 시간입니다. 따라서 호출시 제공된 입력만을 기반으로 할 때 결과가 결정적이지 않습니다.

순수한 기능은입니다 int Add(int a, int b) {return a + b;}. 이 함수는 주어진 것만으로 작동하며 다른 외부 상태 데이터를 사용하지 않습니다. 이것의 자연스러운 결과는 Add(2,2)지금부터 끝까지 4를 얻을 수 있다는 것 입니다. 또한 함수가 외부 상태를 변경 하지 않기 때문에 ( "부작용"이 없음) 지금부터 끝까지 2와 2를 추가하는 Add ()는 시스템에서 다른 것을 변경하지 않습니다. 함수의 결과를 변수에 할당하거나 값을 사용하여 상태를 업데이트하십시오 (함수 자체가 수행하는 작업이 아님). 사실상 모든 고전적인 수학적 연산은 순수한 함수이며 그대로 구현 될 수 있습니다.

반면에 today () 는 연속으로 두 번 호출 될 때 동일한 값을 생성 할 수 있지만 며칠 동안 반복해서 호출되는 경우에는 그렇지 않습니다. 이는 함수에 매개 변수로 제공하지 않은 외부 상태 데이터에 의존하기 때문입니다. 결과적으로 프로그램 경계 내에서 Today () 함수의 결과를 제어하는 ​​것은 불가능합니다. 특정 날짜에 지정된 값을 생성하며, 실행되는 컴퓨터의 시스템 시계를 변경하지 않는 한 (일반적으로 프로그램 경계 밖에서 발생하는 변경) 다른 날에는 해당 값을 생성하지 않습니다.

불완전한 기능이 반드시 나쁜 것은 아닙니다. 데이터 저장소, 통신 파이프 라인, UI 디스플레이, 주변 장치 등과 같이 프로그램 경계 외부의 모든 항목과 상호 작용하려면 기능적 언어에서도 불순한 기능이 필요합니다. 이러한 작업을 수행하지 않는 프로그램은 프로그램입니다. 그것은 그 유용성에 급격히 제한되어있다. 나는 심지어 그러한 프로그램을 사소한 것으로 부르기까지했다. 입력을 받아 들일 수단이나 출력을 알려주는 수단이 없다면 아무것도하지 않을 수도 있기 때문이다. 기능 언어로 작성된 프로그램은 런타임에서 제공 한 입력 만 가질 수 있으며 명시 적으로 정의 된 불완전한 메소드없이 런타임에보고 된 출력을 생성 할 수 있습니다. 그러나 런타임은 불완전한 컴퓨터 시스템 내에서 작업하는 모든 불완전한 세부 사항을 추상화하기 때문입니다.

사용하는 기능이 순수하고 어떤 기능이 아닌지 아는 것은 매우 좋은 일이므로 사용 방법에 대한 올바른 결정을 내릴 수 있습니다. 불완전한 기능은 기능을 수행하거나 용도에서 명확하지 않은 기능에 의존하기 때문에 사용법에 대한 지식만으로는 예측할 수없는 동작을 수행 할 수 있습니다. 기능을 사용하는 시스템을 일관된 상태로 배치하여 결정적인 결과를 기대하려면 기능의 목적과 외부 상태에 필요한 기능 및 외부 상태에 대한 추가 지식이 필요합니다.


8

이 기능이 해당 페이지의 맨 처음에 주어진 첫 번째 순도 테스트에 실패한다는 것은 상당히 명백한 것 같습니다.

  1. 함수는 항상 동일한 인수 값이 주어지면 동일한 결과 값을 평가합니다. 기능 결과 값은 프로그램 실행이 진행됨에 따라 또는 프로그램의 다른 실행간에 변경 될 수있는 숨겨진 정보 또는 상태에 의존 할 수 없으며 I / O 장치의 외부 입력에 의존 할 수도 없습니다.

인수를 취하지 않기 때문에 하나의 가능한 인수 값 세트 (빈 세트) 만 있습니다. 그리고이 함수는 동일한 '인수 값'에 대해 다른 결과를 반환 할 수 있습니다 .

또한, 상기 함수 결과 값은 않는 "프로그램 실행이 진행됨에 따라 변경 될 수 ... 숨겨진 상태"에 의존한다. 또 다른 실패.


@ JörgWMittag 인수가없는 함수가 값을 반환 할 수 없다고 주장하는 위치를 잘 모르겠습니다.
AakashM

뇌 방귀. "하나의 가능한 반환 값 집합 만 있습니다"를 읽었습니다 .
Jörg W Mittag

8

() => 1항상 1을 반환하므로 순수한 함수가됩니다. Today()"월요일"또는 "화요일"또는 거의 모든 다른 값을 반환 할 수 있습니다.

그것을 생각하는 또 다른 방법은 순수한 기능은 상태에 의존하지 않는 것입니다. 세계는 일반적으로 국가로 간주됩니다. 오늘의 요일을 알기 위해서는 현실의 상태를 알아야합니다.

그러나 세상의 상태에 대해 특별한 것을 알 필요는 없습니다 sin(x). 그리고 sin(x)주어진 x것을 요구하면 같은 값을 반환합니다.


Wikipedia에 따르면 "현재 요일을 반환합니다."는 월요일, 화요일 등을 반환하지만 "1/23/2013"이나 "1/24/2013"을 반환 할 수 없음을 의미합니다.
gnat

7
@ gnat : 업데이트되었지만 차이점은 실제로 중요하지 않았습니다.
Guvante

2

Date(timestamp)순수한 기능이 될 것입니다. dem 등 전성 때문에. 그리고 부작용이 없기 때문입니다.

Today()전화를 거는 시점 에 따라 결과가 달라질 수 있습니다 . 그것이 불순한 이유입니다. dem 등성이 아닙니다. 그러나 부작용은 없지만 순수한 것은 아닙니다.


2

순수한 함수를 논의 할 때 생각하는 약간의 의사 코드가 있습니다.

newValue = Function();
while(true)
{
   oldValue = newValue;
   newValue = Function();
   assert( newValue == oldValue );
}

그것이 무기한으로 실행되고 어설 션을 트리거 할 수 없다면 순수한 기능입니다. 더욱이, args를 사용하는 함수가 있다면 약간의 수정이 있습니다 ....

oldValue = Function( importantVariableToYourApp );
newValue = Function( importantVariableToYourApp );
assert( newValue == oldValue );

앱의 모든 변수 할당 후에 이것을 사용할 수 있고 앱의 결과가 변경되지 않고 어설 션이 절대 실패하지 않으면 순수한 함수입니다.


2

첫째, 인수가없는 함수 (또는 인덱스가없는 배열이나 키가없는 맵)는 없습니다. 하나 이상의 인수 값을 다른 값에 맵핑하는 것은 함수의 정의 특성입니다.

따라서 today전혀 기능이 아니므로 순수한 기능이 없습니다. 또는 구문을 해석 할 수 있습니다

today()

조금 의미하는

today   ()      -- today, applied to the value ()

예를 들어, Haskell에서 이것은 유효합니다 :

data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving Show
today :: () -> Day
today () = ....?
main = print (today())

단일 값 ()을 가진 유형 ()이 있기 때문입니다.

문제는 단지 today요일 () 만 있다면 요일을 어떻게 계산할 수 있습니까? 직접 또는 도우미 불완전한 기능을 통해 시스템 타이머를 읽지 않고서는 불가능합니다.

시스템 타이머는 전역 상태에 대한 훌륭한 예입니다.


1

문제 today()는 함수에서 두 번 이상 호출되면 다른 결과를 얻을 수 있다는 것입니다.

다음은 버그를 일으킬 수있는 코드 예제입니다.

function doSomething(when)
{
     if(today() == when)
     {
           // open a resource or create a temp file.....
     }

     // do some other work

     if(today() == when)
     {
           // close the resource or delete temp file.....
     }
}

위의 예에서 가능합니다. 두 번째 if문장은 실행되지 않습니다. 첫 번째 경우에도 마찬가지입니다. 자원을 나쁜 상태로 두는 것.


1

순수한 기능이 되려면 동일한 매개 변수를 제공 할 때마다 동일한 결과를 제공해야합니다.

호출 할 때마다 Today()동일한 매개 변수 (없음)를 제공하지만 반드시 동일한 결과 (월요일, 화요일 등)를 얻지는 않습니다.


4
이것은 단지 약 2 년 전에 게시 된 최고의 답변 에서 만들어지고 설명 된 반복되는 것 같습니다 . 그런 내용으로 2 살짜리 질문에 부딪 힐만한 가치가없는
gnat

1
나는 stackexchange가 어떻게 작동하는지에 익숙하지 않지만, 이것이 이미 부딪 혔다는 가장 큰 의문이 있었기 때문에 알았습니다. 반복 지점을 만드는 한, 비슷한 답변을 여러 개 얻는 것이 도움이 될 수 있다는 것을 메타에서 읽는 것을 기억합니다. 나는 간결하고 잠재적으로 도움이되는 것처럼 느낍니다.
잔 티에
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.