Opinions on -> macro? (was Re: Extensive use of let?)

4 views
Skip to first unread message

John D. Hume

unread,
Feb 27, 2009, 1:39:58 PM2/27/09
to clo...@googlegroups.com
On Wed, Feb 25, 2009 at 4:11 PM, Jason Wolfe <jaw...@berkeley.edu> wrote:
> (you'll get use to reading inside-out quickly).

As a Java/Ruby guy who is not used to reading inside out, I'm curious
as to whether people who ARE accustomed to LISP find the -> macro
distracting since it flops things around. Are there circumstances
where you prefer it?

Meikel Brandmeyer

unread,
Feb 27, 2009, 1:49:44 PM2/27/09
to clo...@googlegroups.com
Hi,

Am 27.02.2009 um 19:39 schrieb John D. Hume:

> As a Java/Ruby guy who is not used to reading inside out, I'm curious
> as to whether people who ARE accustomed to LISP find the -> macro
> distracting since it flops things around. Are there circumstances
> where you prefer it?

I have a Scheme background and I like -> a lot. I would prefer it
always over

(foo (bar (baz (frobnicate a-thing)) bla)).

Eh? To which function belongs the bla argument? I think

(-> a-thing frobnicate baz (bar bla) foo)

is much clearer.

Sincerely
Meikel

James Reeves

unread,
Feb 27, 2009, 1:52:12 PM2/27/09
to Clojure
On Feb 27, 6:39 pm, "John D. Hume" <duelin.mark...@gmail.com> wrote:
> As a Java/Ruby guy who is not used to reading inside out, I'm curious
> as to whether people who ARE accustomed to LISP find the -> macro
> distracting since it flops things around. Are there circumstances
> where you prefer it?

It's pretty useful for nested keywords:

(:name (:profile (:user message)))

(-> message :user :profile :name)

- James

Allen Rohner

unread,
Feb 27, 2009, 2:56:38 PM2/27/09
to Clojure

>
> It's pretty useful for nested keywords:
>
>   (:name (:profile (:user message)))
>
>   (-> message :user :profile :name)
>
> - James

That is really cool. Once again the language and the community impress
me with how elegant the language is.

Allen

e

unread,
Feb 27, 2009, 10:34:46 PM2/27/09
to clo...@googlegroups.com
I think it's simpler just to have a consistent syntax, personally.  Otherwise, why not python or haskell style syntax for the language?  because code is data.  So now there's a special case where the data is backwards.

Jarkko Oranen

unread,
Feb 28, 2009, 5:54:00 AM2/28/09
to Clojure

e wrote:
> I think it's simpler just to have a consistent syntax, personally.
> Otherwise, why not python or haskell style syntax for the language? because
> code is data. So now there's a special case where the data is backwards.

Consistent syntax is nice, but not very useful if it gets in the way
of readability. Fortunately, Clojure has a consistent method for
designing arbitrary new syntax when needed. -> is not a "special
case". It's a well-documented macro intended to make some kinds of
expressions more readable. The non-macro syntax is "simpler", yes, but
not always easier to read, which is the reason why -> exists.

--
Jarkko

Stuart Sierra

unread,
Feb 28, 2009, 12:35:20 PM2/28/09
to Clojure
On Feb 27, 1:39 pm, "John D. Hume" <duelin.mark...@gmail.com> wrote:
> As a Java/Ruby guy who is not used to reading inside out, I'm curious
> as to whether people who ARE accustomed to LISP find the -> macro
> distracting since it flops things around. Are there circumstances
> where you prefer it?

Definitely. When you're applying a bunch of functions to the same
object, it can be clearer to use ->. I don't use it often, but when I
do, my code is much easier to read.

-Stuart Sierra

e

unread,
Feb 28, 2009, 4:25:13 PM2/28/09
to clo...@googlegroups.com
Consistent syntax is nice, but not very useful if it gets in the way
of readability. Fortunately, Clojure has a consistent method for
designing arbitrary new syntax when needed. -> is not a "special
case". It's a well-documented macro intended to make some kinds of
expressions more readable. The non-macro syntax is "simpler", yes, but
not always easier to read, which is the reason why -> exists.


it's yet one more thing to learn how to read, so there's a trade off.  Once you know it, the claim is that easier to read.

 

--
Jarkko


Joshua Fox

unread,
Feb 28, 2009, 4:39:34 PM2/28/09
to clo...@googlegroups.com
->  confuses me: Does it treat functions with multiple parameters different from functions with one parameter? Am I right that it can only be used with the latter?

Joshua

Meikel Brandmeyer

unread,
Feb 28, 2009, 4:55:39 PM2/28/09
to clo...@googlegroups.com
Hi,

(-> a-thing fun-1 (fun-2) (fun-3 b-thing))

is turned into

(fun-3 (fun-2 (fun-1 a-thing)) b-thing)

So, -> takes the first argument and places it as
first argument in the second argument. If the second
argument is not a list, -> creates automatically a list
the given thing as first argument.

So here are the cases.

(-> x foo) => (foo x)
(-> x (foo)) => (foo x)
(-> x (foo a b c)) => (foo x a b c)

This works recursively. So you can easily chain
functions together. One nice example is that of
nested maps as given by James before in this
thread.

(-> the-map :a :b :c)

is turned into

(:c (:b (:a the-map)))

Now consider the-map to be

{:a {:b {:c 5}}}

Then the above evaluates to 5.

A bit contorted, but I hope this helps.

Sincerely
Meikel

eyeris

unread,
Feb 28, 2009, 5:17:43 PM2/28/09
to Clojure
You are wrong. Many writings use ,, as a place-holder for where -> is
placing the argument. Take Meikel's example above:

(foo (bar (baz (frobnicate a-thing)) bla))

Becomes

(-> a-thing frobnicate baz (bar bla) foo)

So bar is a function of more than one argument. Re-written with place-
holders it would be:

(-> a-thing (frobnicate ,,) (baz ,,) (bar ,, bla) (foo ,,))

Does that make it more clear?

-Drew

Laurent PETIT

unread,
Feb 28, 2009, 7:51:28 PM2/28/09
to clo...@googlegroups.com


2009/2/28 Stuart Sierra <the.stua...@gmail.com>

What you really wanted to say is "a bunch of functions to one object".
(If it is to the same object, then it's doto that should be use)
?



-Stuart Sierra
- Afficher le texte des messages précédents -



Belfabius

unread,
Feb 28, 2009, 8:19:01 PM2/28/09
to Clojure
First, I have to say thanks. I'm only a part-time Clojure user, and I
didn't know of the -> macro until today. Second, I think the ->
syntax leads to more readable code for precisely those situations
where you're coding a sequence of actions. Finally, I've got a
comment about what I think might be a useful addition to Clojure.

In my day job, I've been using F#. F# has a |> operator which relies
on automatic currying to do what, at first blush, I though the ->
macro did. In other words, if you've got, for example, a list of
data in F#, you can do something like:

listOfNum |> (map someFn) |> (filter anotherFn) |> max ;; note
the brackets aren't necessary
;;
I added them for readability

which is functionally equivalent to:

max ( filter anotherFn (map someFn listOfNum)))

I quickly learned the -> macro can't be used in the same way for one
simple reason; the value that is threaded through to the forms is
always placed in the first argument position. How about adding a
macro -- it could be called |> just as in F# -- that places the value
in the last argument position? (It's dead simple to write -- I just
copied and modified the -> macro.)

With the new macro it would be possible to write code like:

( |> list-of-num
( map some-fn )
( filter another-fn )
( max ))

instead of:

(max (filter another-fn (map some-fn list-of-num)))

IMHO, the |> macro, just like the -> macro, makes the sequence of the
actions much easier to follow.

Cheers,
--
BF




On Feb 27, 1:39 pm, "John D. Hume" <duelin.mark...@gmail.com> wrote:

Meikel Brandmeyer

unread,
Mar 1, 2009, 4:19:10 AM3/1/09
to clo...@googlegroups.com
Hi,

Am 01.03.2009 um 02:19 schrieb Belfabius:

> I quickly learned the -> macro can't be used in the same way for one
> simple reason; the value that is threaded through to the forms is
> always placed in the first argument position. How about adding a
> macro -- it could be called |> just as in F# -- that places the value
> in the last argument position? (It's dead simple to write -- I just
> copied and modified the -> macro.)

See here for a in-depth discussion of the pipe macro. :)

http://groups.google.com/group/clojure/browse_frm/thread/66ff0b89229be894/c3d4a6dae45d4852

Sincerely
Meikel

Joshua Fox

unread,
Mar 1, 2009, 5:41:51 AM3/1/09
to clo...@googlegroups.com
Meikel and eyeris,

Thanks, that clarifies the usage of -> even multiple parameters.

IMHO, -> simplifies things where unary functions are involved and where the list-parens are absent, so that -> creates the list. 

In the other cases, the standard syntax is easier on the eye.

Joshua
Reply all
Reply to author
Forward
0 new messages