質問

clojureプログラムでJava Scanner クラスのローカルインスタンスを作成したい。なぜこれが機能しないのか:

; gives me:  count not supported on this type: Symbol 
(let s (new Scanner "a b c"))

ただし、次のようなグローバルインスタンスを作成できます。

(def s (new Scanner "a b c"))

私は、唯一の違いはスコープであるという印象を受けましたが、明らかにそうではありませんでした。 let def の違いは何ですか?

役に立ちましたか?

解決

問題は、 let の使用が間違っていることです。

次のように動作します:

(let [identifier (expr)])

したがって、例は次のようになります。

(let [s (Scanner. "a b c")]
  (exprs))

letのスコープ内では、letで作成された字句バインディングのみを使用できます(開き括弧と閉じ括弧)。字句バインディングのセットを作成してみましょう。グローバルバインディングを作成するためにdefを使用し、letのスコープ内でのみ必要なものをバインドできるようにします。両方とも用途があります。

注:(クラス)は(新しいクラス)と同じで、単なる構文上の砂糖です。

他のヒント

LETは「現在のスコープでレキシカルバインディングを作成する」ではなく、「次のバインディングで新しいレキシカルスコープを作成する」です。

(let [s (foo whatever)]
  ;; s is bound here
  )
;; but not here
(def s (foo whatever))
;; s is bound here

正しい構文:

(let [s (Scanner. "a b c")] ...)

簡易: def はグローバル定数用、 let はローカル変数用です。

意味が関連していても、それらの構文は異なります。

letは、バインディングのリスト(名前と値のペア)の後に式が続き、それらのバインディングのコンテキストで評価します。

defはリストではなく1つのバインディングを取得し、グローバルコンテキストに追加します。

let は、 fn で新しいレキシカルスコープを作成し、すぐに適用するための構文上の砂糖と考えることができます。

(let [a 3 b 7] (* a b))  ; 21
; vs.
((fn [a b] (* a b)) 3 7) ; 21

だから、単純なマクロと fn let を実装できます:

(defmacro fnlet [bindings & body]
  ((fn [pairs]
    `((fn [~@(map first pairs)] ~@body) ~@(map last pairs)))
   (partition 2 bindings)))

(fnlet [a 3 b 7] (* a b)) ; 21
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top