Skip to content

3. Dipping Your toes in the pool

Joony.L edited this page Nov 3, 2014 · 8 revisions

Truthiness

  • ์‚ฌ์ „์  ์˜๋ฏธ: ์ง„์‹ค์„ฑ ๋ถ€์—ฌ(์‚ฌ์‹ค๊ณผ๋Š” ์ƒ๊ด€์—†์ด ์‚ฌ๋žŒ๋“ค์ด ์ง„์‹ค์ด๊ธฐ๋ฅผ ๋ฐ”๋ผ๋Š” ๋งˆ์Œ์—์„œ ๋ถ€์—ฌํ•˜๋Š” ์ง„์‹ค์„ฑ)

What's truth?

  • Every object is โ€œtrueโ€ all the time, unless itโ€™s nil or false.

    (if true :truthy :falsey)  ;=> :truthy
    (if [] :truthy :falsey)    ;=> :truthy
    (if nil :truthy :falsey)   ;=> :falsey
    (if false :truthy :falsey) ;=> :falsey

Don't create Boolean objects

  • NEVER do this

    (def evil-false (Boolean. "false")) 
    
    evil-false
    ;=> false
    
    (= false evil-false)
    ;=> true
          
    (if evil-false :truthy :falsey)
    ;=> :truthy
  • right way

    (if (Boolean/valueOf "false") :truthy :falsey)
    ;=> :falsey

nil vs false

  • Rarely do you need to differentiate between the two non-truthy values, but if you do, you can use nil? and false?

    (when (nil? nil) "Actually nil, not false")
    ;=> "Actually nil, not false"
  • Keeping in mind the basic rule that everything in Clojure is truthy unless itโ€™s false or nil is an astonishingly powerful concept, allowing for elegant solutions.

Nil pun with care

  • The seq function returns a sequence view of a collection, or nil if the collection is empty.

    (seq [1 2 3])
    ;=> (1 2 3)
     
    (seq [])
    ;=> nil
  • print-seq function

    (defn print-seq [s]
      (when (seq s) B Check for empty
        (prn (first s))
        (recur (rest s))))
    
    (print-seq [])
    ;=> nil
    
    (print-seq [1 2])
    ;1
    ;2
    ;=> nil

Destructuring

(assignment ํ•  ๋•Œ ๋ฐ›์•„๋“ค์ผ ๊ฒƒ๋งŒ ์„ ํƒํ•˜๋ผ.)Your assignment, should you choose to accept it

๋ฒกํ„ฐ๋ฅผ ์“ธ ๋•Œ์˜ ๋””์ŠคํŠธ๋Ÿญ์ฒ˜๋ง

๋งต ์“ธ ๋•Œ์˜ ๋””์ŠคํŠธ๋Ÿญ์ฒ˜๋ง

ํ•จ์ˆ˜ ์ธ์ž์•ˆ์—์„œ์˜ ๋””์ŠคํŠธ๋Ÿญ์ฒ˜๋ง

๋””์ŠคํŠธ๋Ÿญ์ฒ˜๋ง vs accessor๋ฉ”์†Œ๋“œ

๋งŽ์€ ๊ฐ์ฒด ์ง€ํ–ฅ ์–ธ์–ด์—์„œ, ๋„ˆ๋Š” ์•„๋งˆ ๋„ˆ์˜ ์•ฑ ๋ฐ์ดํƒ€ ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด,๊ฐ๊ฐ์˜ ๊ฒŒํ„ฐ์„ธํ„ฐ ๋ฉ”์†Œ๋“œ์˜ ์ง‘ํ•ฉ๊ณผ ํ•จ๊ป˜ ์ƒˆ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์„ ๊ฒƒ์ด๋‹ค. ํด๋กœ์ €๋Š” ๋Œ€์‹ ์— ์ง€์–ด๋†จ๋‹ค ํŽธ๋ฆฌํ•˜๊ฒŒ ๋งต๊ณผ ๋ฒกํ„ฐ๋ฅผ ์‚ฌ์šฉํ• ์ˆ˜ ์žˆ๊ฒŒ ์ถ”์ƒํ™”๋ฅผ ํ•˜๋Š”๋ฐ์—. ์ด๊ฑฐ๋Š” ๋””์ŠคํŠธ๋Ÿญ์ฒ˜๋ง์„ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ง๊ด€์ ์ด๊ฒŒ ํ•œ๋‹ค. ๋„ˆ๊ฐ€

์‹คํ—˜์„ ์œ„ํ•ด REPL ์‚ฌ์šฉํ•˜๊ธฐ

Clojure REPL์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฒ˜์Œ ์‚ฌ์šฉํ•ด๋ณด๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์ฆ๊ฑฐ์šด ๋งˆ์Œ์œผ๋กœ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์‹œํ€€์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์‹คํ—˜ํ•˜๊ธฐ

  • ํ™”๋ฉด์— ํ”ฝ์…€์„ ํ‘œํ˜„ํ•˜๋Š” x, y ์ขŒํ‘œ๋ฅผ ๊ฐ€์ง€๋Š” ์‹œํ€€์Šค์™€ xor ์—ฐ์‚ฐ์„ ํ•ด์„œ ์žฌ๋ฏธ๋‚œ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž

  • ๋จผ์ € range ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์ขŒํ‘œ๋ฅผ ํ‘œํ˜„ํ•ด๋ณด๊ธฐ ์œ„ํ•ด range๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณธ๋‹ค.

     (range 5)
    ;=> (0 1 2 3 4)
  • x, y ์ขŒํ‘œ ์Œ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ for๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š”์ง€ ์‹คํ—˜ํ•ด๋ณด์ž.

    (for [x (range 2) y (range 2)] [x y])
    ;=> ([0 0] [0 1] [1 0] [1 1])
  • xor ์—ฐ์‚ฐ์„ ์œ„ํ•ด์„œ xor ํ•จ์ˆ˜๊ฐ™์€ ๊ฒƒ์ด ์žˆ์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๊ณ  REPL๋กœ ์‹คํ—˜ํ•ด๋ณด์ž.

    (xor 1 2)
    ;=> java.lang.Exception: Unable to resolve symbol: xor in this context
  • xor๋ผ๋Š” ์ด๋ฆ„์˜ ํ•จ์ˆ˜๋Š” ์—†๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜๋‹ค. ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ์—†๋Š”์ง€ find-doc์œผ๋กœ ์ฐพ์•„๋ณธ๋‹ค.

    (find-doc "xor")
    ; -------------------------
    ; clojure.core/bit-xor
    ; ([x y]) ([x y & more])
    ;   Bitwise exclusive or
    ;=> nil
  • bit-xor๋ผ๋Š” ํ•จ์ˆ˜๊ฐ€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•จ์ˆ˜๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ๊ณ  REPL์—์„œ ํ™•์ธํ•ด๋ณด์ž.

    (bit-xor 1 2)
    ;=> 3
  • ์ด์ œ ๋จผ์ € ๋งŒ๋“ค์—ˆ๋˜ x, y ์Œ์„ ์ฃผ๋Š” for๋ฌธ์— xor ๊ฐ’์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž. REPL์—์„œ UPํ‚ค๋ฅผ ๋ˆ„๋ฅด๋ฉด ์ด์ „์— ์‹คํ–‰ํ–ˆ๋˜ ๊ตฌ๋ฌธ์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

    (for [x (range 2) y (range 2)]
      [x y (bit-xor x y)])
    ;=> ([0 0 0] [0 1 1] [1 0 1] [1 1 0])
  • ์ž˜ ๋œ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ์ด์ œ๊นŒ์ง€ ๋งŒ๋“ค์—ˆ๋˜ ๊ฒƒ์„ ๋‚˜์ค‘์— ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์ž.

    (defn xors [max-x max-y]
      (for [x (range max-x) y (range max-y)]
           [x y (bit-xor x y)]))
    
    (xors 2 2)
    ;=> ([0 0 0] [0 1 1] [1 0 1] [1 1 0])
  • ์œ„์˜ ํ•จ์ˆ˜๋ฅผ Clojure ์†Œ์ŠคํŒŒ์ผ ํ™•์žฅ์ž์ธ .clj๋กœ ์ €์žฅํ•ด๋‘๋ฉด ์ข‹์„๊ฒƒ ๊ฐ™๋‹ค. ๋˜๋Š” ClojureScript ํŒŒ์ผ์ธ .cljs๋กœ ์ €์žฅํ•ด๋‘์ž.

๊ทธ๋ž˜ํ”ฝ์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์‹คํ—˜ํ•˜๊ธฐ

  • Clojure REPL์€ ์ž๋ฐ” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‹คํ—˜ํ•˜๊ธฐ์— ์ข‹์€ ํ™˜๊ฒฝ์ด๋‹ค. java.awt์˜ Frame์„ ๊ฐ€์ง€๊ณ  ์‹œ์ž‘ํ•ด๋ณด์ž.

    (def frame (java.awt.Frame.))
    ;=> #'user/frame
  • Frame์ด ์ƒ์„ฑ๋˜์—ˆ๋Š”๋ฐ ๋ณผ์ˆ˜๊ฐ€ ์—†๋‹ค. ์™œ ๊ทธ๋Ÿฐ์ง€ frame์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

    frame
    ;=> #<Frame java.awt.Frame[frame0,0,22,0x0,invalid,hidden,...]>
  • ๋ญ”๊ฐ€ hidden์ด๋ผ๋Š” ๊ฒƒ์ด ๋ณด์ด๋Š” ๊ฑธ๋กœ ๋ณด์•„ ์ด๊ฒƒ์„ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. Frame์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ ์ค‘์—์„œ Vis์–ด์ฉŒ๊ณ ๋กœ ์‹œ์ž‘๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์•„๋ณด์ž.

    (for [meth (.getMethods java.awt.Frame)
        :let [name (.getName meth)]
        :when (re-find #"Vis" name)]
    name)
    ;=> ("setVisible" "isVisible")
  • ๊ด€๋ จ๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‘๊ฐœ ๋ณด์ธ๋‹ค. ๋‘๊ฐœ๋‹ค REPL์—์„œ ํ™•์ธํ•ด๋ณด์ž.

    (.isVisible frame)
    ;=> false
    
    (.setVisible frame true)
    ;=> nil
  • setVisible์„ ํ–ˆ๋Š”๋ฐ๋„ ํ™”๋ฉด์— ๋‚˜ํƒ€์ž์ง€ ์•Š๋Š”๋‹ค. ์•„๊นŒ frame์˜ ์†์„ฑ์„ ๋ดค์„ ๋•Œ ํฌ๊ธฐ๋กœ ๋ณด์ด๋Š” ๊ฐ’์ด 0,0 ์ด์˜€๋˜๊ฒƒ์„ ๊ธฐ์–ตํ•ด๋ณด๋ฉด ํฌ๊ธฐ๊ฐ€ ์ง€์ •๋˜์ง€ ์•Š์•„ ํ™”๋ฉด์— ์•ˆ๋ณด์ธ๊ฒƒ ๊ฐ™๋‹ค.

    (.setSize frame (java.awt.Dimension. 200 200))
    ;=> nil
  • ์ด์ œ ํ™”๋ฉด์— ๋‚˜์™”๋‹ค. ํŒ์œผ๋กœ (javadoc frame)์„ ํ•˜๋ฉด ์ž๋ฐ” ๋ฌธ์„œ๊ฐ€ ๋ธŒ๋ผ์šฐ์ € ์ฐฝ์œผ๋กœ ๋‚˜์˜จ๋‹ค.

  • ํ™”๋ฉด์— ๋ญ˜ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•ด์„œ ๊ทธ๋ž˜ํ”ฝ ์ปจํƒ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์™€ ๋ณด์ž.

    (def gfx (.getGraphics frame))
    ;=> #'user/gfx
  • ํ™”๋ฉด์— ๋ญ˜ ๊ทธ๋ ค๋ณด์ž.

    (.fillRect gfx 100 100 50 75)
  • ํ™”๋ฉด์— ๊ฒ€์€ ์‚ฌ๊ฐํ˜•์ด ๋‚˜์™”๋‹ค. ์žฌ๋ฏธ์žˆ์ง€ ์•Š๋Š”๊ฐ€? ์ด์ œ ์˜ค๋žœ์ง€์ƒ‰ ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ ค๋ณด์ž.

    (.setColor gfx (java.awt.Color. 255 128 0))
    (.fillRect gfx 100 150 75 50)
  • ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ๊ฐ€์ง€๋„ REPL์—์„œ ์‹คํ—˜ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ํ•จ๊ป˜์“ฐ๊ธฐ

  • ์•ž์—์„œ ๋งŒ๋“ค์–ด๋‘” ํ•จ์ˆ˜๋ฅผ ์จ์„œ ์žฌ๋ฏธ๋‚œ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž.

    (doseq [[x y xor] (xors 200 200)]
     (.setColor gfx (java.awt.Color. xor xor xor))
     (.fillRect gfx x y 1 1))
  • xors ํ•จ์ˆ˜์—์„œ ๋‚˜์˜ค๋Š” ์‹œํ€€์Šค์˜ ๋ฐฑํ„ฐ ํ•ญ๋ชฉ์„ x, y, xor ๊ฐ’์— ๋””์ŠคํŠธ๋Ÿญ์ฒ˜๋งํ•ด์„œ ์ƒ‰์ƒ์œผ๋กœ ์ง€์ •ํ•˜๊ณ  ์ „์ฒด ํ”ฝ์…€์— ๊ทธ๋ ค์ฃผ๋Š” ์˜ˆ์ œ์ด๋‹ค.

๋ญ”๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์„ ๋•Œ

  • ํŒจํ„ด์ด ์ค‘๊ฐ„์— ์งค๋ฆฌ๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ์œ„ํ•ด์„œ ์ด๋ฏธ์ง€ ๋ฒ”์œ„๋ฅผ ๋” ํฌ๊ฒŒ ์„ค์ •ํ•ด๋ณด์ž.

     (doseq [[x y xor] (xors 500 500)]
     (.setColor gfx (java.awt.Color. xor xor xor))
     (.fillRect gfx x y 1 1))
    ; java.lang.IllegalArgumentException:
    ;    Color parameter outside of expected range: Red Green Blue
  • ๋ญ”๊ฐ€ ์ž˜ ๋ชป๋˜์—ˆ๋‹ค. REPL์—์„œ๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํŠน๋ณ„ํ•œ var์ธ *e์— ์˜ˆ์™ธ๊ฐ€ ์ €์žฅ๋œ๋‹ค. ์˜ˆ์™ธ ์ƒ์„ธ ๋‚ด์šฉ์„ ๋ณด๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ํ•ด๋ณด์ž.

     (.printStackTrace *e)
     ; java.lang.IllegalArgumentException: Color parameter outside of
     ; expected range: Red Green Blue
     ; at clojure.lang.Compiler.eval(Compiler.java:4639)
     ; at clojure.core$eval__5182.invoke(core.clj:1966)
     ; at clojure.main$repl__7283$read_eval_print__7295.invoke(main.clj:180) ; ...skipping a bit here...
     ; Caused by: java.lang.IllegalArgumentException: Color parameter
     ;         outside of expected range: Red Green Blue
     ; at java.awt.Color.testColorValueRange(Color.java:298)
     ; at java.awt.Color.<init>(Color.java:382)
     ; ...skipping a bit more...
     ; ... 11 more
     ;=> nil
  • ๋ญ”๊ฐ€ ๊ธด๊ธ€์ด ๋‚˜์™”๋‹ค๊ณ  ๋‹นํ™ฉํ•˜์ง€ ๋ง๊ณ  ์ฒœ์ฒœํžˆ ์‚ดํŽด๋ณด์ž. ๋ญ”์ € caused๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํฌ๊ฒŒ ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ๊ณ  ๋‘๋ฒˆ์งธ ๋ถ€๋ถ„์ธ Caused ๋‹ค์Œ์— ๋‚˜์˜ค๋Š” ๋ฌธ์žฅ ๋ถ€ํ„ฐ ๋ณด์ž.

    at java.awt.Color.testColorValueRange(Color.java:298)
  • java์˜ stack trace๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์„ฑ๋œ๋‹ค.

     at <class>.<method or constructor>(<filename>:<line>)
  • ์ด ๊ฒฝ์šฐ์—๋Š” testColorValueRange ํ•จ์ˆ˜์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ณ  ๋‹ค์Œ ๋ผ์ธ์„ ๋ณด๋ฉด Color์˜ ์ƒ์„ฑ์ž์—์„œ ์—๋Ÿฌ๊ฐ€ ๋‚œ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ญ”๊ฐ€ ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ ์ž˜ ๋ชป๋œ๊ฒƒ ๊ฐ™๋‹ค. ์ด๊ฒƒ์„ ๊ณ ์ณ๋ณด์ž.

    (defn xors [xs ys]
     (for [x (range xs) y (range ys)]
       [x y (rem (bit-xor x y) 256)]))
  • bit-xor์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  256์˜ ๋‚˜๋จธ์ง€ ๊ฐ’์œผ๋กœ ๋ฐ”๊ฟง๋‹ค.

  • ๋‹ค์‹œ ํ™•์ธํ•ด๋ณด๊ธฐ ์œ„ํ•ด์„œ ๊ธฐ์กด์˜ ์ด๋ฏธ์ง€๋ฅผ ์ง€์šฐ๋Š” ํ•จ์ˆ˜๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์ž.

     (defn clear [g] (.clearRect g 0 0 200 200))

์žฌ๋ฏธ๋กœ

  • bit-xor ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์žฌ๋ฏธ์žˆ๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค์–ด๋ดค๋Š”๋ฐ ๋‹ค๋ฅธ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋ฉด ๋˜ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์—ฐ์‚ฐ์ž๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž.

     (defn f-values [f xs ys]
     (for [x (range xs) y (range ys)]
     		[x y (rem (f x y) 256)]))
    
     (defn draw-values [f xs ys]
     	(clear gfx)
     	(.setSize frame (java.awt.Dimension. xs ys))
     	(doseq [[x y v] (f-values f xs ys)]
     	  (.setColor gfx (java.awt.Color. v v v))
     	  (.fillRect gfx x y 1 1)))
    
     (draw-values bit-and 256 256)
    (draw-values + 256 256)
    (draw-values * 256 256)
     ``
    
  • REPL์„ ๊ฐ€์ง€๊ณ  Clojure๋ฅผ ๊ฐœ๋ฐœํ•˜๋ฉด ์‚ฌ์šฉํ•˜๋ ค๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ์‹คํ—˜ํ•ด๋ด„์œผ๋กœ ๊ฐœ๋ฐœ ์‹œ๊ฐ„์„ ๋” ์ค„ ์ผ ์ˆ˜ ์žˆ๋‹ค.