anonymous fn or partial?

356 views
Skip to first unread message

Ulises

unread,
Sep 30, 2010, 3:48:32 AM9/30/10
to clo...@googlegroups.com
Hi,

Newbie here with a simple question: what is the preferred way of
mapping a function to a seq? Use an anonymous function or use a
partial?

Consider this:

user=> (map (fn [n] (+ 2 n)) [1 2 3 4 5])
(3 4 5 6 7)
user=> (map (partial + 2) [1 2 3 4 5])
(3 4 5 6 7)
user=>

I know that the answer is likely to be "it depends." I am just
interested in whether one is more idiomatic/functional than the other,
performance issues that one approach may have that the other one
doesn't, etc.

Thanks in advance,

PS: I'm even tempted to say that if one could do (map (+ 2) [1 2 3 4
5]) it would look even better :)

U

nickikt

unread,
Sep 30, 2010, 5:34:21 AM9/30/10
to Clojure
I ask myself that from time to time. I tend to use (partial + 2)
because I think its easier to read.

The (+ 2) bit is intressting. That would be automatic currying, you
get that in other languages. It is not possible in Clojure becaus
there is no limit to how many args a clojure function can take.

Think about it for a moment. What should ((+ 2) 1) return? A
function with the next elment add on to it? So it would return a
function that adds 3 to its args or the result? How can you know what
the caller wants?

Thats the reason for partial. I would have liked a shorter word for
partial but its not really importend.

Meikel Brandmeyer

unread,
Sep 30, 2010, 5:52:27 AM9/30/10
to Clojure
Hi,

On 30 Sep., 09:48, Ulises <ulises.cerv...@gmail.com> wrote:

> user=> (map (fn [n] (+ 2 n)) [1 2 3 4 5])
> (3 4 5 6 7)
> user=> (map (partial + 2) [1 2 3 4 5])
> (3 4 5 6 7)
> user=>

You can also consider the following: (map #(+ % 2) [1 2 3 4]), which
is also very clear. I personally almost never use partial. (partial +
2) is not entirely equivalent to #(+ 2 %) - actually it's #(apply + 2
%&) - but for 95% of my use cases the #() form is sufficient, shorter,
easier to read for me. partial is just a special case of #(). So in
the end it's probably personal preference.

Sincerely
Meikel

Ulises

unread,
Sep 30, 2010, 6:10:00 AM9/30/10
to clo...@googlegroups.com
> You can also consider the following: (map #(+ % 2) [1 2 3 4]), which

I did consider #(...) but didn't include it in the example as I tend
to prefer (fn [..] ...). For some reason my brain parses (fn...) much
better than #() (it looks more explicit).

If partial is a special case of #(..) could there be then a
performance penalty of using apply instead of a direct call?

My question stemmed from the fact that sometimes I find myself mapping
functions which are just partial applications of the same function and
perhaps having a bunch of partials lying around would make my code
read better.

Cheers for all the replies,

U

Ulises

unread,
Sep 30, 2010, 6:12:47 AM9/30/10
to clo...@googlegroups.com
> Think about it for a moment. What should  ((+ 2) 1)  return? A
> function with the next elment add on to it? So it would return a
> function that adds 3 to its args or the result? How can you know what
> the caller wants?

That's a very good point which I hadn't considered.

Perhaps the evaluation result could depend on the context?

E.g.
(def add-2 (partial + 2))
(def add-3 (add-2 1))

Then, hopefully:
(add-3 3) ; 6
(add-3); 3

U

Meikel Brandmeyer

unread,
Sep 30, 2010, 6:13:51 AM9/30/10
to Clojure
Hi,

On 30 Sep., 12:10, Ulises <ulises.cerv...@gmail.com> wrote:

> My question stemmed from the fact that sometimes I find myself mapping
> functions which are just partial applications of the same function and
> perhaps having a bunch of partials lying around would make my code
> read better.

Well. In case it scratches your itch, I don't see a reason why not to
use partial. (Performance implications of the apply should be a
concern when the prove to be a problem)

Sincerely
Meikel

Nicolas Oury

unread,
Sep 30, 2010, 6:44:00 AM9/30/10
to clo...@googlegroups.com
The two styles are ok.
Matter of taste.
(partial ...) have probably a slight cost I wouldn't worry about
except if profiler tells me to worry.


The (partial...) style is called point-less, because you directly
manipulate the arrows and not the points.
It is the same kind of question as : should you use composition or
call (f (g x))?
Should I use the do-monad notation or a clever combination of m-bind,
map, and composition?

No good answer. Do what you like best in each situation.

If you want to have something looking like (+ 2) with multiple args
possible, I would advocate the best way might be to
add a reader macro to clojure expanding to partial. #p(+ 2) for example.
It is a better idea than using having evaluation depending of the context, IMHO.

Ulises

unread,
Sep 30, 2010, 6:53:44 AM9/30/10
to clo...@googlegroups.com
> The two styles are ok.
> Matter of taste.
> (partial ...) have probably a slight cost I wouldn't worry about
> except if profiler tells me to worry.

Excellent.

> If you want to have something looking like (+ 2) with multiple args
> possible, I would advocate the best way might be to
> add a reader macro to clojure expanding to partial.  #p(+ 2) for example.
> It is a better idea than using having evaluation depending of the context, IMHO.

I guess that this has just led me into learning yet another bit which
I wasn't even aware of! Thanks!

U

nickikt

unread,
Sep 30, 2010, 7:08:23 AM9/30/10
to Clojure
> > If you want to have something looking like (+ 2) with multiple args
> > possible, I would advocate the best way might be to
> > add a reader macro to clojure expanding to partial.  #p(+ 2) for example.
> > It is a better idea than using having evaluation depending of the context, IMHO.
>
> I guess that this has just led me into learning yet another bit which
> I wasn't even aware of! Thanks!

Note that you can't make readermacros yet. It's a supported in CL not
in Clojure but maybe in future versions how knows.

I think the have random nummer of args vs currying its a good traidoff.

Nicolas Oury

unread,
Sep 30, 2010, 7:46:22 AM9/30/10
to clo...@googlegroups.com
> Note that you can't make readermacros yet. It's a supported in CL not
> in Clojure but maybe in future versions how knows.

I meant, if you want to modify Clojure to allow a shorter notation for
partial application,
it is better to add a reader macro (directly in Clojure) than to
change evaluation semantic....

I am not sure it is a good idea anyway...

André Thieme

unread,
Sep 30, 2010, 5:51:23 PM9/30/10
to clo...@googlegroups.com

I brought this issue up in late 2008 and Rich decided against a reader
macro for that, as there already is the #() notation, which also has
advantages over partial, namely allowing you to call macros.

(map #(and true %) [1 2 3 nil 5]) ==> (1 2 3 nil 5)
but
(map (partial and true) [1 2 3 nil 5])
==> Can't take value of a macro: #'clojure.core/and

And this would also be the case for a currying reader macro.

Simon Belak

unread,
Oct 1, 2010, 6:44:18 AM10/1/10
to Clojure
There is a subtle difference in how fixed arguments are handled.
partial evaluates the arguments only once while fn evaluates them on
each call. For side-effects free code the former can yield better
performance. To recap:

(partial foo (baz 1 2))

==

(let [b (baz 1 2)]
(fn [& x] (apply foo b x))

As for syntax sugar, I would like to see the #() macro to be extended
so that it curries when no implicit arguments are given:

#(foo bar baz) => #(foo bar baz &%)

whilst keeping (and emphasising) partial for cases where evaluate-once
semantics are required.

Ulises

unread,
Oct 1, 2010, 8:42:04 AM10/1/10
to clo...@googlegroups.com
> There is a subtle difference in how fixed arguments are handled.
> partial evaluates the arguments only once while fn evaluates them on
> each call. For side-effects free code the former can yield better
> performance. To recap:

Ah! What a nice caveat! (also applies to taking macros as arguments).

Thanks for your insights,

U

Reply all
Reply to author
Forward
0 new messages