On Thu, Sep 13, 2012 at 12:02 AM, Matthew O.  Smith <m0sm...@gmail.com> wrote:
>
> On Wednesday, September 12, 2012 8:03:58 AM UTC-6, jarppe wrote:
>>
>> I have a function that generatwed unique ID's, something like this:
>>
>>   (def k (atom 0))
>>   (defn generate-id [] (swap! k inc))
>>
>>  and I try to use it like this:
>>
>>    {(generate-id) "foo"
>>     (generate-id) "bar"}
>>
>> How ever, I get
>>
>>    IllegalArgumentException Duplicate key: (generate-id)
>> clojure.lang.PersistentArrayMap.createWithCheck (PersistentArrayMap.java:70)
>>
>>
>> This works as expected.
>>
>>   (let [id1 (generate-id)
>>         id2 (generate-id)]
>>     {id1 "foo" id2 "bar})
>>
>> Should I be able to call generate-id in map literal?
>>
>> --
>> -jarppe
>>
>
> This also fails:
>
>  {  (gensym) "foo"
>     (gensym) "bar" }
>
> From the stack trace I get it looks like the reader macro that handles map
> literals is only looking at the function call, not the result of the
> function call.  This makes sense as it is the reader, not the evaluator.

Figuring out what is and what isn't a compile time constant is tricky,
huh? *headdesk*...

But, what's really going on is that you're running into a consequence
of how Clojure and other lisps work. The first thing they do is
'read', which means
converting the text of the program into data structures. Then it
evaluates those data structures as a program. Then it prints the
result. (REPL)

So, here it's building a map which contains the key "a list containing
the symbol gensym" twice. Clearly, that can't work.

It's only *after* the reader has done its work, and returned the map
that compilation/evaluation take place.

Consider a simpler example with a vector, which doesn't produce an
error since it's allowed to have duplicates:

(def k (atom 0))
(defn generate-id [] (swap! k inc))

Now when the reader reads this:

[(generate-id) (generate-id)]

It returns a vector containing two lists, each of which contains the
symbol generate-id.

It's only when this data structure is evaluated, that the functions
generate-id get called. In some order. I wouldn't rely on getting [1
2] and not [2 1].

// Ben

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to