5

私は何かを探していますdotoが、返す代わりにx、最後の呼び出し値を返したいと思います。

たとえば、次の代わりに:

(.size (doto (java.util.ArrayList.) 
             (.add 2)
             (.add 3)))

私は書きたい:

(mydoto (java.util.ArrayList.) 
             (.add 2)
             (.add 3)
             .size)

この結果を達成する慣用的な方法は何ですか?

4

3 に答える 3

13

doto最初の引数を返します。->最後のフォームを評価した結果を->>返します (最初の式をスレッド化した後、 を参照してください(clojure.repl/doc ->)。マクロdotoはコードを次のように展開します。

(let [r (java.util.ArrayList.)]
  (.add r 2)
  (.add r 3)
  r)

を使用している場合.size、配列リストには影響せず、メソッドの戻り値に関心があるだけです (これとは異なり.add、ブール値を返し、関心のある ArrayList の状態を変更します)。

異なる種類の戻り値と入力値が必要になるため、mydoto のようにこれらのメソッドを混在させることはできません。最終的なサイズに 3 を掛けたい場合、これは慣用的です。

(-> (doto (java.util.ArrayList.) 
          (.add 2)
          (.add 3))
    .size
    (* 3))

あるいは

(-> (java.util.ArrayList.)
    (doto (.add 2) (.add 3))
    .size
    (* 3))

これらのマクロはコードを読みやすくする必要があるため、コンテキストに応じて、最も意味のある方法で記述します。

于 2013-08-04T11:37:46.663 に答える
1

@lgrapenthin で言及されているように、mydotoを使用して書くことができます。doto

(defmacro mydoto 
    "Like doto but returns the result of the last form instead 
     of the first argument"
    [& args]
    `(-> (doto ~@(butlast args))
         ~(last args)))
于 2013-08-05T06:11:49.750 に答える