2017년 11월 30일 목요일

[clojure][design pattern] 클로저 - 커맨드패턴

clojure design pattern 출처::http://clojure.or.kr/docs/clojure-and-gof-design-patterns.html#command


커맨드패턴(Command Pattern)

보면 알겠지만 커맨드(명령)을 login/logout명령으로 나눠서 따로 구현했다.
구현할 때 Command 인터페이스를 구현하여 execute(실행해라!)모든 명령을 이 인터페이스가 있는 녀석으로 구현하면
뭐든 간에 execute만 실행하면 될 것이다.

(defn login [id pass] (println "id: " id ", pass: " pass))

(defn logout [id] (println "logout: " id))

(defn execute [command]
  (do
    (println "logging")
    (command)))

;; 익명인터페이스와 동급

(execute #(login "name" "123"))  

(execute #(logout "idid"))

(defn execute [command & args]
  (apply command args))

(execute login "id" "password") 
apply를 사용하는 이유는 [command & args]에서 args는 리스트형태(?)로 반환하기 때문에 이 리스트 괄호를 깨부시고 안에 들어가서 적용(apply)해야 한다.

(defn wrong-execute [command & args]
  (command args))
(wrong-execute login "id" "password")

ArityException Wrong number of args (1) passed to: user/login  clojure.lang.AFn.throwArity (AFn.java:429)
보는바와 같이 login에는 잘못된 숫자의 매개변수가 들어간 것이다.
아마
(login ["id" "password"])
요래 들어갔을 것이다. 이렇게 실행해보자.
user=> (login ["id" "password"])
ArityException Wrong number of args (1) passed to: user/login  clojure.lang.AFn.throwArity (AFn.java:429)
똑같다 이제 apply를 해보자
user=> (apply login ["id" "password"])
id:  id , pass:  password
nil
아까 apply를 이용하면 괄호들을 깨부수고 안으로 들어(?)간다고 했다.
(apply login ["id" "password"]) == (login "id" "password")
요래 들어가는 것!!! (apply를 꼭 써야 한다.)
============================

이게 왜 중요하다는 거지?

일단 커맨트패턴이 뭔지보자. (자바의 눈으로)

execute()하나를 함께 쓰기 위해서 Command라는 인터페이스를 각각 구현하는 것이다.
그러면 login/logout을 하기 위해 login,logout클래스를 만들고 Command라는 인터페이스를 구현할 것이다.

자 그렇다면 로그인을 위한 Command 인터페이스를 클래스로 구현했다. 그리고 이제 이 클래스를 사용할 것이다.
아니!
정확히는 이 클래스에 있는 Command 안에 execute을 사용할 것이다.

이 커맨드들을 어딘가에 뒀다가 가져오려면 리턴도 되야하고 매개변수로 넣어지기도 해야 할것이다.
클래스는 그럴 수 없다.(뭔줄알고!!) 메소드를 넣을 수도 없다. 인터페이스를 넣는 것이다.
execute를 사용하기 위해!!

클로저의 눈으로 보자.
일단 클로저에서는 함수를 그냥 넘기기 때문에 개념이 아예 다르다.
그냥... 뭔 만들고 넣고 하는게 아니라...
함수를 보내고 받은걸 쓰면 된다.

뭐가 더 좋다가 아니라 이 두 개념을 마음대로 노닐 수 있는 내가 되었으면 좋겠다.

2017년 11월 16일 목요일

[clojure] loop: doseq,dotimes, while, loop, recur 정리

출처 : Clojure Loop

doseq

foreach 문과 비슷하다. 각각의 요소(element)를 돈다(iterate). 중요한 것은 lazy sequence를 강제(force) 평가(evaluation)한다.

(doseq [n (range 10)]
  (println n))
0
1
~
9

dotimes

일반 for문과 비슷하다. 숫자만큼 포문을 돈다.

(dotimes [i 10]
  (println i))
0
1
~
9

while

단순 while문과 비슷

(def a (atom 0))
(while (< @a 10)
  (do
    (println @a)
    (swap! a inc)))
0
1
~
9

loop/recur

loop를 이용하여 재귀를 돌 범위를 정한다. recur을 이용하여 loop의 값을 바꾼다.

(loop [i 0]
  (if (< i 10)
    (do (println i) 
        (recur (inc i)))
    i))
0
1
~
9

defn/recur

함수를 재귀

함수 이름을 부르지 않고 recur을 사용하는 이유는 tail recursion때문이다.

(defn increase [i]
  (if (< i 10)
    (do (println i)
        (recur (inc i)))
    i))
(increase 0)
0
1
~
9

[java]이클립스 JDK 패스 설정

-vm
 C:\Program Files\Java\jdk1.8.0_152\bin\javaw.exe
이런식의 내용을 eclipse.ini 에 맨 위에 넣는다.