<br><br><div><span class="gmail_quote">On 9/2/06, <b class="gmail_sendername">Jay Nelson</b> <<a href="mailto:jay@nelson.name">jay@nelson.name</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Bjorn clarified some optimization approaches:<br><br> > We have considered improving the optimization, so that no list would<br><br>> be built in case 2.<br><br>Where case 2 was the line commented <2> below:
<br><br>> foo(X) -><br>> A = [do_something(E) || E <- X], % <1><br>> [do_other(E) || E <- X], % <2><br>> ok.<br><br><br><br>There has been previous debates about use lists:foreach when only side-effects are desired
<br>and a list comprehension when the result list is needed. I used to subscribe to that<br>approach, but the list comprehension is so much clearer that I always use it now unless<br>there is reason to be concerned about generating the large list. To me, <1> and <2> have
<br>clearly marked intent that the first needs the result and the second is only for side<br>effects because there is no left side pattern match.<br><br>I would lobby for the compiler to not generate a list in this case. It allows me to
<br>code in the most consistent and clear style and not have to take a performance penalty<br>for doing so.<br><br>There are two other reasons why this optimization might be desirable:<br><br>1) When (or if) binary comprehensions are added, it would be possible to use a similar
<br>construct to visit all bytes and emit them via message send or io:format or write them<br>to a file, without constructing and consuming new memory. Thus, binaries nearly the<br>size of total available RAM could be received, transformed and re-emitted as below:
<br><br>{ok, BigBinary} = file:read_file("bigfile"), %% or from a receive<br><< AmazonS3 ! convert_to_unicode(ByteChunk) || ByteChunk:1024 <- BigBinary >>.<br><br><br>2) List Comprehensions (and binary) could be used for infinite streams. Sort of the
<br>equivalent of tail recursion not using the stack.<br><br><br>[ send_to_listeners(Publication) || Publication <- get_next_pub(Publisher) ]<br><br>get_next_pub(Publisher) -><br> receive<br> {Publisher, Pub} -> Pub
<br> after<br> 5000 -> end_of_stream %% Hmmm, well some token to tell comprehension to end.<br> %% Don't think [] would work. Worst case it could just exit.<br> end.<br><br><br>Half-baked idea, but if you spawn link the above code, the intent is to sit emitting
<br>published events to all subscribers until the publisher pauses for 5 seconds. I think<br>the coding style makes it concise and clear what is going on.<br><br>Instead of get_next_pub, the generator could be lazy_gen_all_natural_numbers or some other
<br>infinite stream.<br><br><br>jay<br><br></blockquote></div><br><br>Agreed 101%. <br><br>Excellent use cases, too.<br><br>