Hi, Cecil.

The difference is that doseq is used to produce side-effects, which is 
idiomatic, which is exactly what you did. When using doseq you can be sure 
that it's body will evaluate, whereas with map, for, reduce you can't - 
they expect pure functions, and produce lazy sequences, and there in no way 
for them to know that you want these sequences evaluated. At least, this is 
my understanding at the moment.

Because you said you liked clean code, I'd like to point out that your 
solution, although works, relies on mutating state of external vars, i.e. 
producing side effects, which is not necessary, and looks spaghetti-like, 
somewhat.

Instead, you could modify return value of foo function to return a vector 
of [result, time], or, because you seem to not care about the result, time 
the function took to complete.

It would look similar to what you already did:

- first define a higher order function, that records executions time of a 
supplied function:

(defn timed [f]
  (fn [& args]
    (let [start (.getTimeInMillis (now))
          result (apply f args)
          end (.getTimeInMillis (now))]
      [result (- end start)])))

- define a timed version of foo:

(defn foo' (timed foo))

- use it with doseq, because you are doing side-effects:

(doseq [time (map second (map foo' numbers))]
;; alternatively, you can use threading macro: (doseq [time (->> numbers 
(map foo') (map second))]
  (println "it took" time "ms"))

And it works! Without mutating global state, with pure functions - what a 
marvel. However, one piece is missing: number of threads the foo function 
was using - the whole point of this typing, eh, programming, I mean.
You have 2 options here. First, the most obvious, is to return that number 
in foo. Second is applicable if you're doing what I think you're doing - 
applying the same computational algorithm using different number of 
threads. If second is true, you know number of threads you are going to use 
beforehand and foo could use them as input... ah, well, this is exactly 
what you were doing, I know realize, numbers being number of threads to 
use. Anyways, in light of this knowledge we can now rewrite doseq part as:

(doseq [[time nthreads] (map (fn [n] [(second (foo' n)) n]) numbers)]
  (println nthreads "threads took" time "ms to compute things"))

Yay!
Note, that timed should work regardless of what function you supply to it.

On Saturday, April 12, 2014 10:33:02 PM UTC+5:45, Cecil Westerhof wrote:
>
> 2014-04-12 18:19 GMT+02:00 Fergal Byrne <fergalby...@gmail.com<javascript:>
> >:
>
>>
>> On Sat, Apr 12, 2014 at 4:55 PM, Cecil Westerhof 
>> <cldwes...@gmail.com<javascript:>
>> > wrote:
>>
>>> (->> numbers
>>>      (reduce timed-foo [])
>>>      (map format-time)
>>>      println)
>>>
>>
>> (->> numbers
>>      (reduce timed-foo [])
>>      (map format-time)
>>      (map println))
>>
>
> That was my first thought also, but that displays nothing.
>
> But the following works:
> (doseq [i (->> numbers
>      (reduce timed-foo [])
>      (map format-time))]
>      (println i))
>
> -- 
> Cecil Westerhof 
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to