본문 바로가기

Study/ETC

Clojure로 LISP 톺아보기 (3) - 제어문

서론

이번 포스팅에서는 참과 거짓을 이용해 코드의 흐름을 제어하는 일을 해보겠다.

논리로 흐름 제어하기

클로저의 기본 데이터 타입인 boolean은 참과 거짓으로 코드를 평가한다. boolean을 평가하는 함수에 대해 알아보자.

  • true?

해당 요소가 참인지 검사한다.

user=> (true? true) true user=> (true? false) false
  • false?

해당 요소가 거짓인지 검사한다.

user=> (false? true) false user=> (false? false) true
  • nil?

해당 요소가 값이 없는지 검사한다.

user=> (nil? "papico") false user=> (nil? nil) true
  • not

해당 요소를 부정한다.

user=> (not true) false user=> (not false) true user=> (not nil) true

nil 은 거짓으로 평가된다.

  • =

두 요소가 같은지(동등) 검사한다.

user=> (= :hello :hello) true user=> (= :hello "a") false
  • not=

두 요소가 다른지(동등이 아님) 검사한다.

user=> (not= :hello :hello) false user=> (not= :hello "a") true

컬렉션에 사용하는 논리 검사

컬렉션의 상태를 검사하는 여러 함수들이 존재한다.

  • empty?

컬렉션이 비어있는지 검사한다.

user=> (empty? []) true user=> (empty? '(1 2 3)) false
  • seq

컬렉션을 시퀀스로 변환, 시퀀스 추상은 컬렌션을 리스트처럼 순차적으로 사용할 수 있도록 해준다.

user=> (seq []) nil user=> (seq [1 2 3]) (1 2 3)
  • every?

첫번째 인자로 진위함수, 두번째 인자로 컬렌션을 받아 진위함수가 컬렉션의 모든 요소가 참으로 평가되면 true , 그렇지 않으면 false 가 반환된다.

user=> (every? odd? [1 2 3]) false user=> (every? odd? [1 3 5]) true
  • not-any?

진위함수와 컬렉션을 받아 진위함수로 컬렉션의 요소를 평가한 값이 하나라도 참이라면 false , 그렇지 않다면 true 를 반환한다.

user=> (not-any? odd? [1 2 3]) false user=> (not-any? odd? [2 4 6]) true
  • some

진위함수와 컬렉션을 받아 진위함수로 평가했을때 참이되는 평가 값을 리턴한다. 그렇지 않다면 nil 을 반환한다.

user=> (some odd? [1 2 3]) true user=> (some odd? [2 4 6]) nil

코드 흐름 이용하기

클로저에서 코드의 흐름을 제어하는 조건문에 대해 알아보자.

  • if / if-let

if 는 세 개의 인수를 받는다. 논리 검사식, 참일 경우 평가되는 식, 거짓일 경우 평가되는 식을 받는다.

user=> (if true "it is true." "it is false.") "it is true." user=> (if false "it is true." "it is false.") "it is false."

if-let 을 이용하면 조건식을 변수에 저장하여 if 문을 평가할 수 있다.

user=> (def x {:whatever 1}) #'user/x user=> (if-let [value (:whatever x)] value "Not found") 1 user=> (if-let [value (:no-match x)] value "Not found") "Not found"
  • when / when-let

whenif 문과 다르게 참일 때만 처리할 수 있다.

user=> (defn drink [water] (when water "drink water")) #'user/drink user=> (drink true) "drink water" user=> (drink false) nil

when-let 을 이용해서 평가할 수 있다.

(defn drink [water]     (when-let [d (= water "water")]         (str "drink " water)     ) )  (drink "water") ; "drink water" (drink "poison") ;=> nil
  • cond

cond 는 검사식과 그 검사식이 참일때 평가될 식을 쌍으로 받아 평가한다. "default" 를 통해서 else 를 대신할 수 있다.

(let [bottle "drinkme"]   (cond     (= bottle "poison") "DO NOT DRINK"     (= bottle "drinkme") "Drink"     (= bottle "empty") "This bottle is empty"     "default" "unknown")) ;=> "Drink"  (let [bottle "juice"]   (cond     (= bottle "poison") "DO NOT DRINK"     (= bottle "drinkme") "Drink"     (= bottle "empty") "This bottle is empty"     "default" "unknown")) ;=> "unknown"
  • case

case 는 검사할 심볼이 같고 그 값을 = 로 비교할수 있는 경우 cond 의 축약형으로 사용된다.

(let [bottle "poison"]   (case bottle     "poison" "DO NOT DRINK"     "drinkme" "Drink"     "empty" "This bottle is empty"     "unknown")) ;=> "DO NOT DRINK"

마무리

이번 포스팅에서는 간단하게 제어문을 작성하는 방법에 대해 알아보았다.

이번 포스팅을 요약한 내용이다.

  • 논리식을 평가하는 연산은 true?. false?, nil? not, =, not=가 있다.
  • 컬렉션을 평가하는 방법은 empty?, seq, every?, not-any?, some 이 있다.
  • 조건문에는 if, if-let, when, when-let, cond, case 가 있다.