(#({:a %}) :b)

191 views
Skip to first unread message

Steven Obua

unread,
Jun 3, 2012, 9:53:09 PM6/3/12
to clo...@googlegroups.com
The expression

(#({:a %}) :b)

should evaluate to {:a :b}, but raises an exception instead:

Wrong number of args (0) passed to: PersistentArrayMap

This is a pretty irritating bug and makes the #% form essentially unusable for me, because I cannot rely on it but have to always second guess if its use is safe in the current context or not.

Bill Caputo

unread,
Jun 3, 2012, 10:00:32 PM6/3/12
to Clojure
On Jun 3, 2012, at 8:53 PM, Steven Obua wrote:

The expression

(#({:a %}) :b)

either: 

(#(hash-map :a %) :b) 
((fn [x] {:a x}) :b)

will work instead.


Someone with more knowledge than me can probably explain better, but my understanding is that the the reader macro shorthand for anonymous functions and the map literal syntax can't both be used together (i.e. it's not a bug, but a reader limitation).


bill


should evaluate to {:a :b}, but raises an exception instead:

Wrong number of args (0) passed to: PersistentArrayMap

This is a pretty irritating bug and makes the #% form essentially unusable for me, because I cannot rely on it but have to always second guess if its use is safe in the current context or not.

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Michael Gardner

unread,
Jun 3, 2012, 10:30:55 PM6/3/12
to clo...@googlegroups.com
On Jun 3, 2012, at 8:53 PM, Steven Obua wrote:

#(f ...) expands to (fn [...] (f ...)), so #({:a %}) would be (fn [x] ({:a x})).

In order for #({:a %}) to work as you want, the more common usage #(f %) would have to become #((f %)). That seems like a poor trade-off to me.

James Reeves

unread,
Jun 3, 2012, 10:35:56 PM6/3/12
to clo...@googlegroups.com
On 4 June 2012 03:00, Bill Caputo <logo...@gmail.com> wrote:
> Someone with more knowledge than me can probably explain better, but my
> understanding is that the the reader macro shorthand for anonymous functions
> and the map literal syntax can't both be used together (i.e. it's not a bug,
> but a reader limitation).

It's actually because #({:a %}) is equivalent to (fn [x] ({:a x})),
when he wants (fn [x] {:a x}).

So it's not a bug, nor a reader limitation, but rather a
misunderstanding of what #() is short for.

- James

Bill Caputo

unread,
Jun 3, 2012, 10:47:44 PM6/3/12
to Clojure
Ahh, that makes a lot more sense. Another foggy understanding clarified :-)


bill

Steven Obua

unread,
Jun 3, 2012, 11:03:39 PM6/3/12
to clo...@googlegroups.com
Ah, I see. Thanks for the clarifications, at least now I understand why #(...) does what it does.

nick rothwell

unread,
Jun 4, 2012, 4:56:33 AM6/4/12
to clo...@googlegroups.com
This one has caught me once or twice as well: #(xxx) evaluates "(xxx)", not "xxx". My usual mistake is

... #([1 % 3]) ...

My rather verbose workround is

... #(identity [1 % 3]) ...

Meikel Brandmeyer (kotarak)

unread,
Jun 4, 2012, 6:42:52 AM6/4/12
to clo...@googlegroups.com
Or simply: #(vector 1 % 3)

Literals are not the only way to create data structures.

Kind regards
Meikel

Steven Obua

unread,
Jun 4, 2012, 8:29:53 AM6/4/12
to clo...@googlegroups.com
Come to think of it, why not redefine #(...) in the following way:


If (count [...]) is 0 or > 1 , then the old semantics stays 
If (count [...]) is 1, then the new semantics kicks in (i.e., without enclosing brackets).

This would allow (#({:a %}) :b) to behave in a sane way

In case f is actually a function of no arguments, for #(f) you would get 

(fn [] f)

which is also more likely what you actually want compared to the old meaning

(fn [] (f))

which is equivalent to f (and therefore there is no need to write #(f) in the first place).


On Monday, June 4, 2012 2:53:09 AM UTC+1, Steven Obua wrote:

Moritz Ulrich

unread,
Jun 4, 2012, 8:32:01 AM6/4/12
to clo...@googlegroups.com
I don't think redefining the behavior of fundamental syntax is a good
idea. Might break many things.
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en



--
Moritz Ulrich

Steven Obua

unread,
Jun 4, 2012, 8:51:23 AM6/4/12
to clo...@googlegroups.com
I doubt that this change would break anything, as the case that has changed has been pretty useless so far.

Jay Fields

unread,
Jun 4, 2012, 8:59:43 AM6/4/12
to clo...@googlegroups.com
; assume 'recorders' is {:x #(println (System/currentTimeMillis)) ... }
#((recorders %))

the above code has a single form (i.e. count 1), and allows you to get the fn you desire from a map and immediately execute it.

I've done similar things in prod.

Softaddicts

unread,
Jun 4, 2012, 9:13:25 AM6/4/12
to clo...@googlegroups.com
Reader macros are syntactic sugar on top of the syntax.
They identify immediately what they stand for unambigously.

I doubt that it would be a good idea to introduce this kind of logic in the reader.
That's an open door to chaos. The same token could be used for different constructs.

As Meikel said, you can achieve a more readable result using vector and alikes to
avoid confusion.

In the same lineage, Clojure has no user alterable reader tables to avoid messing
with input interpretation.
That's been a clear statement since the beginning and I would be surprised that this
changes.

Don't hold your breath waiting for this to happen :)

Luc
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>
--
Softaddicts<lprefo...@softaddicts.ca> sent by ibisMail from my ipad!

Steven Obua

unread,
Jun 4, 2012, 9:28:01 AM6/4/12
to clo...@googlegroups.com
Jay's example has convinced me that redefinition is not a good idea anyway, because #(f) is not always equivalent to f when (count [f]) is 1.

Gary Verhaegen

unread,
Dec 13, 2012, 1:35:33 PM12/13/12
to clo...@googlegroups.com
I've found this gem in The Joy of Clojure :

#(-> [%])

which would work similarly for any literal, I guess : #(-> {:a %}) in
this case. Much nicer than identity, IMHO.

On 4 June 2012 15:28, Steven Obua <ste...@obua.de> wrote:
> Jay's example has convinced me that redefinition is not a good idea anyway,
> because #(f) is not always equivalent to f when (count [f]) is 1.
>

JvJ

unread,
Dec 13, 2012, 5:48:04 PM12/13/12
to clo...@googlegroups.com
Clever, but I always thought -> had to take more than one parameter.  Maybe that's only for ->>

Michael Fogus

unread,
Dec 14, 2012, 8:07:47 AM12/14/12
to Clojure
The limitation was only on ->> but I think that is due for a fix in
the next version.
--
-- http://blog.fogus.me
-- http://github.com/fogus
--
Reply all
Reply to author
Forward
0 new messages