2

定義済みの関数を無名関数に変えたい。それ、どうやったら出来るの?次の関数は、シーケンスから最後の要素を返します。

(defn lastt [l]
    (cond
        (nil? (next l)) l
        :else
            (lastt (next l))))

形にするにはどうすればいいfnですか?

PS: 関数については知っていlastますが、これは単なる演習です。

4

2 に答える 2

7

まず、その関数は、最後の項目を含むリストを返します。最後の項目だけを返すように定義を変更します。

(defn lastt [l]
  (cond
   (nil? (next l)) (first l)
   :else (lastt (next l))))

簡単にするために、 で2 回let呼び出しているため、バインディングを使用します。nextl

(defn lastt [l]
  (let [n (next l)]
    (cond
     (nil? n) (first l)
     :else (lastt n))))

次に行うことは、最終呼び出しを代わりlasttに使用するように置き換えることですrecur

(defn lastt [l]
  (let [n (next l)]
    (cond
     (nil? n) (first l)
     :else (recur n))))

そして、私はそれを

#(let [n (next %)]
   (cond
    (nil? n) (first %)
    :else (recur n)))

そして、破壊を使用してさらに単純化できることに気付きました:)

#(let [[h & t] %]
   (cond
    (nil? t) h
    :else (recur t)))

更新しました

condブランチは 2 つしかないため、 は必要ありません。短縮形fnの代わりにを使用すると、のパラメータで分解を行うことができ、関数全体がもう少し簡潔になります。#fn

(fn [[h & t]]
  (if (empty? t) h
      (recur t)))
于 2012-05-26T06:43:44.163 に答える
6

私はクロージャーというよりはスキーマ/CLer ですが、(defn f [args] body)ほとんどが の構文糖衣のように見えます(def f (fn f ([args] body)))。この場合、 を省略lasttして無名関数として記述できますdef

(fn lastt 
    ([l] (cond
           (nil? (next l))
             l
           :else
             (lastt (next l)))))

再帰なのでlastt、ボディ内でバインドする名前を指定する必要があります。

于 2012-05-26T06:37:14.373 に答える