Question

I want to make a local instance of a Java Scanner class in a clojure program. Why does this not work:

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

but it will let me create a global instance like this:

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

I was under the impression that the only difference was scope, but apparently not. What is the difference between let and def?

Was it helpful?

Solution

The problem is that your use of let is wrong.

Let works like this:

(let [identifier (expr)])

So your example should be something like this:

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

You can only use the lexical bindings made with let within the scope of let (the opening and closing parens). Let just creates a set of lexical bindings. I use def for making a global binding and lets for binding something I want only in the scope of the let as it keeps things clean. They both have their uses.

NOTE: (Class.) is the same as (new Class), it's just syntactic sugar.

OTHER TIPS

LET is not "make a lexical binding in the current scope", but "make a new lexical scope with the following bindings".

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

Correct syntax:

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

Simplified: def is for global constants, let is for local variables.

The syntax for them is different, even if the meanings are related.

let takes a list of bindings (name value pairs) followed by expressions to evaluate in the context of those binding.

def just takes one binding, not a list, and adds it to the global context.

You could think of let as syntactic sugar for creating a new lexical scope with fn then applying it immediately:

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

So you could implement let with a simple macro and fn:

(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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top