2016-10-17 7 views
-1

로버트 C 마틴 (Robert C Martin)의 기능적 프로그래밍에 대한 이야기를 지켜 봤습니다. 왜? 언제? " https://www.youtube.com/watch?v=7Zlp9rKHGD4함수 프로그래밍에서 클로저의 위치

이 대화의 주요 메시지는 함수 프로그래밍에서 상태가 받아 들여지지 않는다는 것입니다. 마틴은 더 나아가, assigments는 '악'이라고 주장합니다.

그래서 ...이 질문을 염두에두고 제 질문은, 함수 프로그래밍의 폐쇄 장소는 어디입니까?

기능 코드에 상태 변수 또는 변수가없는 경우 이러한 폐쇄 (주, 변수를 묶지 않는 클로저)를 만들고 사용하는 주된 이유는 무엇입니까? 클로저 메커니즘이 유용합니까?

상태 또는 변수가 없으면 (어쩌면 immutables ID 만 사용) 현재의 어휘 범위를 참조 할 필요가 없습니다 (변경할 수있는 것이 아무것도 없습니다)?

이 접근법은 현재 어휘 범위에 대한 링크가없는 Java와 유사한 람다 메커니즘을 사용하기에 충분합니다 (변수가 최종적이어야하는 이유입니다).

일부 소스에서 클로저는 기능적 언어 요소가 있어야 함을 의미합니다.

+3

코딩하려는 패러다임에 관계없이 항상 ** 상태를 유지합니다. **항상**. 국가는 악의가 아니며, 전적으로 필요합니다. 악한 것은 변화 할 수있는 세계적인 국가들입니다. 또는 너무 많은 것을 포함하려고 시도하는 국가 (하나님 물건). – Carcigenicate

+0

확인. 이 사람은 폐쇄가 무엇인지 설명합니다. https://www.youtube.com/watch?v=7aYS9PcAITQ#t=18m13s 나는 그의 예에서 very_local_variable이 '악의적 인'상태라고 생각합니다. c1()을 먼저 호출하고, 두 번째를 호출하는 것이 동일하지 않기 때문에. 각 전화는 '세상을 바꿀 것'입니다. 그럼 ... 어쩌면이 두 번째 예제 (클로저 설명 포함)가 정확하지 않을 수도 있습니다. – LancerX

+1

돌연변이 상태가 함수 외부에있는 경우, 예, 악으로 간주 될 수 있습니다. 내 대답은 내 새 편집 봐. 전역 상태에 영향을 미치지 않으면 서 가변성을 가질 수 있으며, 함수 밖에서는 아무 것도 변경하지 않으므로 악의가 아닙니다. 이 기능은 여전히 ​​효율적이고 기능적으로 투명합니다. – Carcigenicate

답변

3

폐쇄 할 수있는 어휘 범위는 유용 할 수 있도록 변경할 필요가 없습니다. 단지 예로서 카레 기능을 고려

add = \a -> \b -> a+b 
add1 = add(1) 
add3 = add(3) 
[add1(0), add1(2), add3(2), add3(5)] // [1, 2, 5, 8] 

여기 내부 람 바어가 a 값 이상 종료 (또는 때문에 불변의 차이가없는 가변 a 위에).

클로저는 궁극적으로 기능 프로그래밍에 필요하지 않지만 로컬 변수도 마찬가지입니다. 그래도 둘 다 좋은 아이디어입니다. 클로저를 사용하면 함수 프로그래밍의 가장 중요한 (?) 중요한 작업을 추상화 된 코드의 특수한 동작으로 동적으로 생성 할 수 있습니다.

2

변경 가능한 변수가있는 언어에서와 같이 클로저를 사용합니다. 차이점은 분명히 (보통) 수정할 수 없다는 것입니다.

(let [a 10 

     f (fn [b] 
      (+ a b))] 

    (println (f 4))) ; Prints "14" 

이런 경우 폐쇄의 주요 장점은 내가 "부분적으로 적용"할 수있는 :

다음 (아이러니하게도 내가 지금 함께 쓰고 있어요) Clojure에서의 간단한 예입니다 함수를 사용하고, 적용되지 않은 함수를 전달하는 대신에 부분적으로 적용된 함수를 전달하고, 호출해야하는 데이터를 전달합니다 (많은 시나리오에서 매우 유용합니다). 아래 예에서 함수를 즉시 호출하지 않으려면 어떻게해야합니까? f을 호출 할 때 사용할 수 있도록 a을 전달해야합니다.

그러나 당신이 그것을 필요 (@Bergi가 지적 하듯,이 예제는 "악"입니다,하지만)하다고 인정하는 경우, 당신은 또한 혼합으로 약간의 가변성을 추가 할 수 있습니다

(let [a (atom 10) ; Atoms are mutable 

     f (fn [b] 
      (do 
      (swap! a inc) ; Increment a 
      (+ @a b)))] 

    (println (f 4)) ; Prints "15" 
    (println (f 4))); Prints "16" 

이러한 방법으로 정적 에뮬레이션 할 수 있습니다 변수. 이걸 사용하여 memoize과 같은 멋진 작업을 수행 할 수 있습니다. 그것은 "static 변수"를 사용하여 참조 적으로 투명한 함수의 입출력을 캐시합니다. 이렇게하면 메모리 사용이 늘어나지 만 제대로 사용하면 CPU 시간을 절약 할 수 있습니다.

나는 국가가 있다는 생각에 반대한다는 것에 동의해야합니다. 국가는 악하지 않습니다. 그들은 이 필요합니다.입니다. 모든 프로그램에는 국가가 있습니다. 전 지구 적, 가변 국가는 악합니다.

또한 이 가변성을 가지며 기능적으로는 여전히 프로그램입니다. 목록 위에지도가 포함 된 함수가 있다고 가정 해보십시오. 또한 매핑하는 동안 누산기를 유지해야한다고 말합니다.

  • 스위치 foldmap : 정말 ("수동으로 그 일을"무시)이 옵션이 있습니다.
  • 변경 가능한 변수를 만들고 매핑하는 동안 변경합니다.

옵션 1이 바람직하지만, 두 가지 방법 모두 기능 프로그래밍 중에 활용할 수 있습니다. 하나의 버전이 내부적으로 가변 변수를 사용하더라도 "함수 외부"라는 관점에서 볼 때 아무런 차이가 없습니다. 영향을받는 유일한 변경 가능한 상태가 함수에 국한되어 외부에 영향을 미칠 수 없기 때문에이 함수는 명확하게 투명하고 순수 할 수 있습니다. 로컬 변수 돌연변이

예 번호 :

(defn mut-fn [xs] 
    (let [a (atom 0)] 

     (map 
     (fn [x] 
      (swap! a inc) ; Increment a 
      (+ x @a)) ; Set the accumulator to x + a 
     xs))) 

주 변수 함수 외부에서 볼 수없는a, 그래서이있는 효과가 어떠한 방식으로 발생할 수있는 글로벌 변경. 이 함수는 각 입력에 대해 동일한 출력을 생성하므로 실제로는 순수합니다.

+0

함수 f가 더 이상 명확하게 투명하지 않기 때문에 예제 *의 상태가 * 악하다고 주장 할 수도 있습니다. – Bergi

+0

예, 정적 변수를 '모방하는'것은 악합니다. 기능적 언어 내에서 가능한 이점을 위해 사용될 수 있다는 것을 보여 주었지만, 이상적인 사용 사례와는 거리가 멀습니다. 그래서 로컬 변경 가능 상태가 잠재적으로 유용하지만 유해하지 않다는 것을 보여주기 위해 다른 예제를 추가했습니다. – Carcigenicate

+2

Downvoter, 제발 의견. – Carcigenicate