[javascript] Math.random ()을 호출하는 함수가 순수합니까?

다음은 순수한 기능입니까?

function test(min,max) {
   return  Math.random() * (max - min) + min;
}

내 이해는 순수한 기능이 다음 조건을 따른다는 것입니다.

  1. 매개 변수에서 계산 된 값을 반환합니다.
  2. 반환 값을 계산하는 것 외에는 어떤 작업도하지 않습니다.

이 정의가 맞다면 내 함수가 순수한 함수입니까? 아니면 순수한 함수를 정의하는 것에 대한 나의 이해가 잘못 되었습니까?



답변

아니, 그렇지 않습니다. 동일한 입력이 주어지면이 함수는 다른 값을 반환합니다. 그러면 입력과 출력을 매핑하는 ‘테이블’을 만들 수 없습니다.

Pure 함수에 대한 Wikipedia 기사에서 :

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

또 다른 것은 이 스레드 에서 설명한대로 순수 함수를 입력 및 출력의 매핑을 나타내는 테이블로 대체 할 수 있다는 것입니다 .

이 함수를 다시 작성하고 순수 함수로 변경하려면 임의의 값도 인수로 전달해야합니다.

function test(random, min, max) {
   return random * (max - min) + min;
}

그런 다음 다음과 같이 호출합니다 (예 : 최소 및 최대로 2와 5 사용).

test( Math.random(), 2, 5)


답변

귀하의 질문에 대한 간단한 대답 은 규칙 # 2Math.random()위반하는 것입니다.

여기에있는 다른 많은 답변은 존재 Math.random()가이 기능이 순수하지 않다는 것을 의미한다고 지적했습니다 . 그러나 나는 그것을 사용하는 기능을 오염시키는 이유를 말할 가치가 있다고 생각 Math.random()합니다.

모든 의사 난수 생성기와 마찬가지로 Math.random()“시드”값으로 시작합니다. 그런 다음이 값을 낮은 수준의 비트 조작 체인 또는 예측할 수없는 (실제로 무작위가 아닌 ) 출력 을 초래하는 기타 작업의 시작점으로 사용합니다 .

JavaScript에서 관련된 프로세스는 구현에 따라 다르며 다른 많은 언어와 달리 JavaScript는 시드를 선택할 수있는 방법을 제공 하지 않습니다 .

구현은 난수 생성 알고리즘에 대한 초기 시드를 선택합니다. 사용자가 선택하거나 재설정 할 수 없습니다.

이것이이 함수가 순수하지 않은 이유입니다. JavaScript는 기본적으로 사용자가 제어 할 수없는 암시 적 함수 매개 변수를 사용합니다. 다른 곳에서 계산되고 저장된 데이터에서 해당 매개 변수를 읽고 있으므로 정의의 규칙 # 2를 위반합니다.

이 함수를 순수 함수로 만들고 싶다면 여기에 설명 된 대체 난수 생성기 중 하나를 사용할 수 있습니다 . 그 발전기를 호출하십시오 seedable_random. 하나의 매개 변수 (시드)를 사용하고 “무작위”숫자를 반환합니다. 물론,이 숫자는 전혀 무작위가 아닙니다. 그것은 종자에 의해 유일하게 결정됩니다. 이것이 이것이 순수한 기능인 이유입니다. 의 출력은 seedable_random입력을 기반으로 출력을 예측하는 것이 어렵다는 의미에서 “무작위”일뿐입니다.

이 함수의 순수 버전은 세 가지 매개 변수 를 가져야합니다 .

function test(min, max, seed) {
   return  seedable_random(seed) * (max - min) + min;
}

주어진 세 개의 (min, max, seed)매개 변수에 대해 항상 동일한 결과를 반환합니다.

의 출력 seedable_random진정으로 무작위가되도록하려면 시드를 무작위 화하는 방법을 찾아야합니다! 그리고 어떤 전략을 사용하든, 기능 외부의 소스에서 정보를 수집해야하기 때문에 필연적으로 순수하지 않을 것입니다. 으로 mtraceurjpmc26 나를 생각 나게,이 모든 물리적 접근을 포함한다 : 하드웨어 난수 발생기를 , 렌즈 캡 웹캠 , 대기 소음 수집 – 심지어 용암 램프 . 이 모든 것에는 함수 외부에서 계산되고 저장된 데이터를 사용하는 것이 포함됩니다.


답변

순수 함수는 관찰 가능한 부작용없이 반환 값이 입력 값에 의해서만 결정되는 함수입니다.

Math.random을 사용하면 입력 값이 아닌 다른 값으로 값을 결정합니다. 순수한 기능이 아닙니다.

출처


답변

아니요, 출력이 단지 의존하지 않기 때문에 순수한 함수가 아닙니다. 제공된 입력 (Math.random ()은 모든 값을 출력 할 수 있음) 순수 함수가 항상 동일한 입력에 대해 동일한 값을 출력해야하기 때문에 순수 함수가 아닙니다.

함수가 순수하면 동일한 입력으로 여러 호출을 최적화하고 이전 호출의 결과를 재사용하는 것이 안전합니다.

적어도 저와 다른 많은 사람들에게 PS는 redux라는 용어를 순수 함수 라는 용어로 유명 하게 만들었습니다 . redux 문서에서 바로 :

감속기 안에서 절대하지 말아야 할 것 :

  • 인수를 변경하십시오.

  • API 호출 및 라우팅 전환과 같은 부작용을 수행합니다.

  • 순수하지 않은 함수 (예 : Date.now () 또는 Math.random ())를 호출합니다.


답변

수학적 관점에서 귀하의 서명은

test: <number, number> -> <number>

그러나

test: <environment, number, number> -> <environment, number>

는의 environment결과를 제공 할 수 Math.random()있습니다. 그리고 실제로 무작위 값을 생성하면 환경이 부작용으로 바뀌므로 첫 번째 환경과 같지 않은 새 환경도 반환됩니다!

즉, 초기 인수 ( <number, number>부분) 에서 나오지 않는 입력이 필요한 경우 실행 환경 (이 예에서는에 대한 상태 제공 Math) 이 제공되어야합니다 . I / O 등과 같은 다른 답변에서 언급 된 다른 것들에도 동일하게 적용됩니다.


비유로, 이것이 객체 지향 프로그래밍이 어떻게 표현 될 수 있는지 알 수 있습니다.

SomeClass something
T result = something.foo(x, y)

실제로 우리는

foo: <something: SomeClass, x: Object, y: Object> -> <SomeClass, T>

메서드가 호출 된 개체가 환경의 일부가됩니다. 그리고 왜 SomeClass결과 의 일부입니까? something의 상태도 변경되었을 수 있기 때문입니다 !


답변

순수 함수는 항상 동일한 입력에 대해 동일한 값을 반환합니다. 순수 함수는 예측 가능하고 참조 투명합니다. 즉, 함수 호출을 반환 된 출력으로 대체 할 수 있으며 프로그램의 작동을 변경하지 않습니다.

https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md


답변

이 함수가 결정적이지 않은 방법을 올바르게 지적하는 다른 답변 외에도 부작용이 있습니다. 향후 호출 math.random()이 다른 답변을 반환하도록합니다. 그리고 해당 속성이없는 난수 생성기는 일반적으로 OS에서 제공하는 임의 장치에서 읽는 것과 같은 일종의 I / O를 수행합니다. 둘 중 하나는 순수한 기능을위한 verboten입니다.