BIBLIOGRAPHY
Related-Notes
히스토리
- 로그시크에 작성해 둔 것
동질성 : 함수형 프로그래밍 언어 클로저
https://en.wikipedia.org/wiki/Homoiconicity create-at:: 2022-05-21
영어에서 번역됨-컴퓨터 프로그래밍에서 동질성은 일부 프로그래밍 언어의 속성입니다. 작성된 프로그램이 해당 언어를 사용하여 데이터로 조작 될 수 있다면 언어는 동음 이의어이므로 프로그램 자체를 읽는 것만으로 프로그램의 내부 표현을 유추 할 수 있습니다.
2022 함수형 프로그래밍의 개념을 다룬다.
클로저 기준으로 정리 필요 일단 비공
Pure Function 수학 함수는 모두 순수 함수이다. Side-Effect 이 없다. 프로그램 전체가 순수 함수로 작성되어야 이러한 효과를 누릴 수 있다.
Persistent Data Structure 불변하는 데이터를 유지하기 위해서는 영속 자료구조가 필요하다. 그렇다고 모든 데이터를 생성 할 때마다 복수할 수는 없다. Structural Sharing 구조 공유 기법
Laziness and Recursion
Referential Transparency 참조 투명성을 가지는 함수를 순서를 바꾸거나 지연 시킬 수 있다. 여기에 해당하는 기술이 Memoization Automatic caching 전략이다. 참조 투명성은 Automatic parallelization을 가능하게 한다.
그래서 FP 의 이점은 무엇인가? —
이를 위한 개발 가이드 6 가지 이슈
Fibonacci를 통해서 관련 기술을 익혀보자. 코드를 보자! 단계별로 개선해 나가는 작업.
Simple Recursion — Recursion
;; simple recursion - bad idea
(defn stack-consuming-fibo [n]
(cond
(= n 0) 0
(= n 1) 1
:else (+ (stack-consuming-fibo (- n 1))
(stack-consuming-fibo (- n 2)))))
(stack-consuming-fibo 9)
;(stack-consuming-fibo 1000000)
[BROKEN LINK: Recursion/Tail-Recursion] 끝 재귀 이슈가 있다.
- letfn 사용 관련 [BROKEN LINK: _letfn]: use local function
- 끝 재귀를 사용함에도 JVM 에서 최적화 제대로 지원 안됨
(defn tail-fibo [n] (letfn [(fib [current next n] (if (zero? n) current (fib next (+ current next) (dec n))))] (fib 0N 1N n)))
[BROKEN LINK: Recursion/Self-Recursion] with recur [BROKEN LINK: _recur]
- JVM 이 꼬리 재귀를 지원하지 않으니, 클로저에서 제공하는 recur 을 사용하라. 스택을 소모하지 않음.
- 캐싱 이슈 — 매번 같은 계산을 반복해야 하는가? 중간 값들을 캐싱하는 방법을 제공해야 된다.
clojure ;; better but not great (defn recur-fibo [n] (letfn [(fib [current next n] (if (zero? n) current (recur next (+ current next) (dec n))))] (fib 0N 1N n)))
- [BROKEN LINK: Lazy Sequences] 지연 시퀀스 [BROKEN LINK: voclj/sequences/create/lazy-seq]
-
이전과 다른 접근. 피보나치 몇개를 가정하고 함수를 작성할 필요가 없다. 피보나치 수열은 무한한 것이다. 그 중에서 몇개의 값을 얻을지, 몇번째 값을 얻을지는 호출하는 사람의 선택이다. 굉장히 합리적이다.
-
시퀀스는 무한히 커진다. 여기서 지연 시퀀스를 이용해서 원하는 값을 얻어보자.
-
[BROKEN LINK: voclj/primitives/numbers/arithmetic/rem], [BROKEN LINK: voclj/collections/lists/nth]
;; 4) lazy-seq-fibo (defn lazy-seq-fibo ([] (concat [0 1] (lazy-seq-fibo 0N 1N))) ([a b] (let [n (+ a b)] (lazy-seq (cons n (lazy-seq-fibo b n)))))) ;; 10개만 취하자 (take 10 (lazy-seq-fibo)) ;; rem, nth 함수. 1000000 번째 수열에서 뒤에 3자리만 뽑는 코드 (rem (nth (lazy-seq-fibo) 1000000) 1000)
-
원칙 3 의 무한대 시퀀스를 다룰 때는 지연 시퀀스 사용했으니 이제 원칙 5 시퀀스 API 를 사용하라를 따르자. iterate 를 이용하면 정말 간단하게 구현할 수 있다. — 뭐지?! [BROKEN LINK: voclj/sequences/create/iterate]
(take 5 (iterate (fn [[a b]] [b (+ a b)]) [0 1])) (defn fibo [] (map first (iterate (fn [[a b]] [b (+ a b)]) [0N 1N]))) (take 10 (fibo)) ;; 출력 갯수를 10개로 한정하고 싶다면... (set! *print-length* 10) (take 10000000 (fibo)) (fibo)
-
[BROKEN LINK: voclj/sequences/uses/dorun-doall-doseq-run!] 함수를 묶었다. 이것도 방법이다.
-
-
[BROKEN LINK: Recursion/Mutual-Recursion] trampoline
-
[BROKEN LINK: Coin Tossing] 동전 던지기 예를 통해서 Lazy 프로그래밍 기법을 더 다룬다.
왜 코인 던지기? 더 게으른 방법을 이야기하는데 무슨 이야기 인가? 언어가 제공하는 Lazy 에 다가 프로그램에 특성에 맞는 더 Lazy 한 구현 기법을 말하고자 한다. 근데 이게 다른 언어에서는 불가능한가?
[BROKEN LINK: @Functional Thinking]에서 유사한 주제가 있나? — 훌륭한 교과서이다. 뭘 어떻게 해야하는가를 알아야 한다.
recur 을 사용한 간단한 코드. 뭐가 간단한데? 여기서 사용되는 함수들이 여러개고 recur 을 어떻게 쓰는지 생각을 해봐야 한다.
(defn count-heads-pairs [coll]
(loop [cnt 0 coll coll]
(if (empty? coll)
cnt
(recur (if (= :h (first coll) (second coll))
(inc cnt)
cnt)
(rest coll)))))
(count-heads-pairs [:h :h :h :t :h])
이코드에 대해서 설명해봐.
잠시만, 좋은 문서를 찾았다! 와우!
[BROKEN LINK: voclj/CONCEPT/currying_partial function]
[BROKEN LINK: voclj] [BROKEN LINK: @Clojure Cheatsheet] 개발 관련 모음을 해야 할 것 같은데?! 물론 코드를 모으는 것도 좋긴한데 하다보니 검색하는게 불편하다. 특히, 글을 적는게 아니라 활용성이 떨어진다. 그래서 Sheet 를 기준으로 정리하다보면 관련 코드가 모이지 않을까? 그렇다고 딱 띠어놓고 그 주제만 하기도 어렵다. 서로 연관이 있기 때문이다. 중복 상관 없이 해당 주제로 백링크를 걸면 되니까. 그냥 시작해도 나쁘지 않을듯하다.
왜 클로저인가? 라는 질문에 로직 프로그래밍이야기를 하는데. 궁금하다. [BROKEN LINK: Clojure/core.logic]이 그 역할을 하는데. 로직 프로그래밍이 무엇인가?
Pure Function
Persistent Data Structure
Structural Sharing
Referential Transparency
Memoization
Automatic parallelization
Fibonacci