Eager map?

1,173 views
Skip to first unread message

Robert Ewald

unread,
Nov 17, 2008, 6:26:42 PM11/17/08
to clo...@googlegroups.com
Hello,

Doing some small experiments I stumbled over map returning a lazy seq instead
of performing the function. I had to convert that to a doseq. Is there any
rationale for not having an eager map. Or was I just not reading the docs
properly?

--
Robert Ewald

Jarkko Oranen

unread,
Nov 17, 2008, 6:50:38 PM11/17/08
to Clojure
you can use either doall or dorun depending on whether
you need the results or just want to force side-effects:

For example, compare:
(dorun (map println ["This" "is" "an" "example"]))
(doall (map (memfn toUpperCase) ["This" "is" "an" "example"]))

Hope this helps
--
Jarkko

Adam Jones

unread,
Nov 17, 2008, 6:50:44 PM11/17/08
to Clojure
Many of Clojure's functions that operate on seqs have this property.
The idea is to capture the space efficiency of lazy list processing by
default. If you really need strict evaluation, wrap the map with
doall. I'm guessing that strict equivalents aren't provided to
encourage the use of the lazy functions unless they absolutely aren't
needed.

-Adam

>
> --
> Robert Ewald

Allen Rohner

unread,
Nov 17, 2008, 7:24:30 PM11/17/08
to Clojure
>. If you really need strict evaluation, wrap the map with
> doall.

Another way to do that would be to use doseq.

Allen

Bradbev

unread,
Nov 17, 2008, 7:25:44 PM11/17/08
to Clojure
What is the preferred idiom for converting from a Lazy seq to a proper
seq?
I've been using (into [] (map .....)).
doall and dorun don't really appeal to me in this usage, because to me
they say "This code is lazy and I'm executing it for side effects, not
results". (into []...) says to me "This code is lazy, and I really
want a concrete vector here.

Thoughts?

Cheers,
Brad

Adam Jones

unread,
Nov 17, 2008, 9:01:41 PM11/17/08
to Clojure
This is true for dorun, but not exactly for doall. (For instance,
there's no difference in the result between (into '() ...) and
(doall ...)) I'm not really confident enough to speculate on the
relative efficiency of either. As far as I have seen, there is no
preferred idiom for forcing the thunks in a seq.

I'm in the middle of writing some code to extract sql results, which
means I'm doing a *lot* of forcing right now. It's almost enough for
me to wish there was a convention (and provided definitions) for
denoting lazy/strict versions of functions. (e.g. (map f ...) is a
lazy seq, (map! f ...) is strict)

-Adam

>
> Cheers,
> Brad

Chouser

unread,
Nov 17, 2008, 9:58:09 PM11/17/08
to clo...@googlegroups.com
On Mon, Nov 17, 2008 at 9:01 PM, Adam Jones <ajo...@gmail.com> wrote:
>
> I'm in the middle of writing some code to extract sql results, which
> means I'm doing a *lot* of forcing right now. It's almost enough for
> me to wish there was a convention (and provided definitions) for
> denoting lazy/strict versions of functions. (e.g. (map f ...) is a
> lazy seq, (map! f ...) is strict)

(vec x) will force a lazy seq x and store it in a vector. (apply list
x) will force and store in a list.

--Chouser

mb

unread,
Nov 18, 2008, 2:20:15 AM11/18/08
to Clojure
Hi,

On 18 Nov., 03:01, Adam Jones <ajon...@gmail.com> wrote:
> I'm in the middle of writing some code to extract sql results, which
> means I'm doing a *lot* of forcing right now. It's almost enough for
> me to wish there was a convention (and provided definitions) for
> denoting lazy/strict versions of functions. (e.g. (map f ...) is a
> lazy seq, (map! f ...) is strict)

For what it's worth: I use the following convention.

- For code which is purely done for side-effects, I use doseq. eg.
(doseq [x some-seq] (println x))

- In case I want to have the seq in memory, or there are side-effects
and I need the actual results, I use doall.
(doall (map some-f some-seq))

On the other hand: you can simply create your own map!.
(def map! (comp doall map))

Just my 0.02€.

Sincerely
Meikel

Robert Ewald

unread,
Nov 18, 2008, 2:18:28 PM11/18/08
to clo...@googlegroups.com

Right, but this is precisely the reason for my asking. I was aware you could
create a macro, but if I do that a lot nobody could read my code any longer.
Everyone creating his own set of misguided utilities has been an argument
against lisp, and I think this is a function of communication inside the
community.

Using a ! to signify forcing is interesting, even though I am reserved because
scheme is using it to signify side effects and clojure is not free from side
effects.

Anyway, I suppose that doseq is the right idiom for communicating that you
want throw away the results.

--
Robert Ewald

Adam Jones

unread,
Nov 18, 2008, 4:33:45 PM11/18/08
to Clojure
I used it as a shorthand for a similar bit of syntax in Haskell. There
$! is defined such that f $! x forces the evaluation of x before
handing it to f. map$! would be ugly, but I see your point about !.
(in fact, Clojure already uses this for set! on threadlocal vars)
Maybe map$ would be a good choice; it even sort of conveys the idea
that needlessly forcing a computation can be (spatially) expensive! =)

Ultimately the choice of a character to signify "this function is not
lazy" isn't a big issue, so long as it is 1. not confusing and 2.
vaguely memorable. Maybe Rich can step in with an opinion and settle
this.

-Adam
Reply all
Reply to author
Forward
0 new messages