学習Clojureパート4:機能


前の部分では、すでに多くの機能を使用していましたので、関数の呼び出し方についてのアイデアがほとんどあります.
もう一度それをやりましょう.すべての式には同じ構文があります.( , 演算子、オペランド) .
演算子は関数である.
オペランドは任意の値、関数、または式です.
すべての非NILと偽の値ではないと見なされます.
これはおもしろいことをします.
((or + -) 1 2 3 4 5)
;=> 15
もっと複雑な例を挙げましょう.機能を取るmap and inc . inc 1をインクリメントします.map 関数とコレクションを受け取り、新しいリストを作成します.ここで、関数はコレクションに適用されます.
(inc 41)
;=> 42

(map inc [1 2 3 4 5])
;=> (2 3 4 5 6)
私たちが知る必要があるもう一つのことは、clojureは関数に渡す前に再帰的にすべての関数引数を評価することです.
ここでは、clojureがどのように評価されるかのステップの例です.
(+ (inc 1) (* 2 (+ 1 1)))
(+ 2 (* 2 (+ 1 1)))
(+ 2 (* 2 2))
(+ 2 4)
6
この規則の例外は特別な形と呼ばれるものです.関数とは異なり、特殊形式はすべての引数を評価しません.最良の例はif .
(if transaction-approved
 (send-money 5000)
 (send-money 0)
)
上の例では理由がわかります.取引が承認された時のみお金を送りたい.
関数の引数として特殊形式を使用できません.

関数の定義
私たちは既に2つの関数を使用してdefn エクスプレッション.今、私たちは再び全体の過程を進み、深く行きます.
関数定義には5つの部分があります.
  • defn
  • 関数の名前
  • オプションの文字列
  • ブラケットのパラメータ
  • 機能本体
  • 関数定義の例は次のようになります.
    (defn make-it-awesome
     "Returns back a string, that will be awesome"
     [input]
     (str "OMG this is so awesome " input " AWESOME AWESOME AWESOME")
    )
    
    (make-it-awesome "lightsaber")
    ;=> "OMG this is so awesome lightsaber AWESOME AWESOME AWESOME"
    
    ゼロ以上のパラメータがあります.
    [] ;zero
    [input] ; one
    [one two] ; two
    
    関数は、オーバーロードをサポートします.つまり、同じ関数名を複数回定義することができます.これはデフォルト値を提供する主な方法です.
    (defn shoot
     ([shooter target]
     (str shooter " shoots at " target)
     )
     ([target]
     (shoot "Agent Smith" target)
     )
    )
    
    (shoot "Neo" "Agent Smith")
    ;=> "Neo shoots at Agent Smith"
    
    (shoot "Neo")
    ;=> "Agent Smith shoots at Neo"
    
    また、& 文字.
    (defn killing-spree
     [& targets]
     (map shoot targets)
    )
    
    (killing-spree "Morpheus" "Trinity" "Neo")
    ;=> ("Agent Smith shoots at Morpheus" "Agent Smith shoots at Trinity" "Agent Smith shoots at Neo")
    
    もう1つの非常に素晴らしいことは、引数のコレクションを渡し、クロージャがコレクションを破壊し、コレクションの一部のメンバーに意味のある名前を付けさせることです.
    (defn pack
     [[most-important super-needed & others]]
     (println "Packing for a trip.")
     (println (str "Most important thing is " most-important))
     (println (str "You cannot go without " super-needed))
     (println (str "Also: " (clojure.string/join ", " others)))
    )
    
    (pack ["wallet" "phone" "boxers" "deodorant" "socks"])
    ;=>Packing for a trip.
    ;Most important thing is wallet
    ;You cannot go without phone
    ;Also: boxers, deodorant, socks
    
    あなたはマップと同じことができます.
    (defn say-hello
     [{first :first last :last}]
     (str "Hello my friend " first " " last)
    )
    
    (say-hello {:first "Darth" :last "Vader"})
    ;=> "Hello my friend Darth Vader"
    
    しかし、我々がちょうど地図のキーワードを壊したいならば、我々は使うことができます:keys キーワード.
    (defn say-hello
     [{:keys [first last]}]
     (str "Hello my friend " first " " last)
    )
    
    (say-hello {:first "Darth" :last "Vader"})
    ;=> "Hello my friend Darth Vader"
    
    我々も、元のアクセスを保持することができます:as .
    (defn say-hello
     [{:keys [first last] :as person}]
     (println (str "Hello my friend " first " " last))
     (println (str "Original map was " person))
    )
    (say-hello {:first "Darth" :last "Vader"})
    ;Hello my friend Darth Vader
    ;Original map was {:first "Darth", :last "Vader"}
    
    関数本体には複数のフォームを含めることができます.フォームを返します.
    (defn return-last
     []
     1
     (+ 1 2)
     "This is the end."
    )
    
    (return-last)
    ;=> "This is the end."
    

    匿名関数
    Clojureも匿名関数、名前のない関数をサポートします.私たちはfn フォーム.作品は正確にdefn フォーム(名前を除く).
    (fn [param] body)
    
    より具体的な例
    (map (fn [number] (+ 42 number)) [0 1 2 3 4 5 6 7 8 9 10])
    ;=> (42 43 44 45 46 47 48 49 50 51 52)
    
    通常の関数と同じように使用できます.パラメータリスト、破壊などこの関数に名前を割り当てることもできますdef .
    (def adder (fn [number] (+ 42 number)))
    (adder 1)
    ;=> 43
    
    そして、我々が見つけるならばfn あまりにも長い間、ショートカットフォームを使用できます.
    #(+ % 42)
    
    (#(+ % 42) 1)
    ;=> 43
    
    これは奇妙に見えるかもしれないが% 引数を表します.簡単に理解できます.
    (map #(str "Hello dear " %) ["Darth Vader" "Anakin" "Yoda" "Obi-wan"])
    ;=> ("Hello dear Darth Vader" "Hello dear Anakin" "Hello dear Yoda" "Hello dear Obi-wan")
    
    我々の機能が1つ以上の議論をする必要があるならば、我々は使うことができます%1 , %2 , など.
    (#(str %1 " and " %2) "dogs" "cats")
    ;=> "dogs and cats"
    
    残りの引数は%& .

    関数を返す関数
    関数が関数を返すことを既に見ました.返される関数はクロージャと呼ばれます.つまり、関数が作成されたときにスコープ内のすべての変数にアクセスできることを意味します.
    (defn plus-maker
     "Create a custom function that adds to a number"
     [add]
     #(+ % add)
    )
    (def plus42 (plus-maker 42))
    (plus42 1)
    ;=> 43
    
    あなたはこのようなコンテンツを得るために私に従うことができます.