Re: I don't understand this exception

2011-01-16 Thread Ken Wesson
On Mon, Jan 17, 2011 at 1:47 AM, Stefan Rohlfing
 wrote:
> Hi all,
>
> I am trying to implement the function 'group-by' from Clojure.Core
> using my current knowledge of Clojure but cannot get pass a
> java.lang.Exception.
>
> This is the code so far:
>
> (defn key? [key coll]
>  (some #{key} (keys coll)))
>
> (defn my-group-by [f coll]
>  (let [test (fn [m x]
>               (let [res (f x)]
>                 (if (key? res m)
>                   (conj (m res) x)
>                   (assoc m res (vec x)]
>    (reduce test {} coll)))

First of all, your key? is only ever (supposed to be) called on maps,
so you can dispense with it:

(defn my-group-by [f coll]
 (let [test (fn [m x]
              (let [res (f x)]
                (if (contains? res m)
                  (conj (m res) x)
                  (assoc m res (vec x)]
   (reduce test {} coll)))

Second, your already-in-the-map case returns a vector. It doesn't
modify the vector in place; it makes a new one with one more item and
returns that. Not the map it should return.

The next iteration of your reduce, the vector gets passed to key? with
some value. Your key? function calls keys on it, which results in an
exception. I get:

user=> (keys ['x 'y 'z])
java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to
java.util.Map$Entry

You got:

> ;; java.lang.Exception: Unable to convert: class java.lang.Integer to
> Object[] (repl-1:2)

I'm not sure why the difference -- different Clojure versions? -- but
no matter, the fix is the same:

(defn my-group-by [f coll]
 (let [test (fn [m x]
              (let [res (f x)]
                (if (contains? res m)
                  (assoc m res (conj (m res) x))
                  (assoc m res (vec x)]
   (reduce test {} coll)))

This actually returns an updated map and not just an updated vector.
But it can be made nicer in a couple of ways. One uses the optional
not-found option to get to dispense with the contains?:

(defn my-group-by [f coll]
 (let [test (fn [m x]
              (let [res (f x)]
(assoc m res (conj (m res []) x]
   (reduce test {} coll)))

And the other uses update-in. Update-in means the key only needs to be
specified once, which lets you dispense with the inner let:

(defn my-group-by [f coll]
 (let [test (fn [m x]
(update-in m [(f x)] #(if % (conj % x) [x])))]
   (reduce test {} coll)))

This can be formatted a bit more nicely:

(defn my-group-by [f coll]
  (reduce
(fn [m x]
  (update-in m [(f x)]
#(if % (conj % x) [x])))
{} coll))

This gets rid of the outer let as well.

The latter two versions can't distinguish the map having a key with an
associated value of nil and the map lacking that key; however, the map
never associates a key with anything other than a vector, so this ends
up not mattering.

For reference (and I only peeked at this *after* writing all of the
above), the implementation of group-by in clojure.core is:

(defn group-by
  "Returns a map of the elements of coll keyed by the result of
  f on each element. The value at each key will be a vector of the
  corresponding elements, in the order they appeared in coll."
  {:added "1.2"
   :static true}
  [f coll]
  (persistent!
   (reduce
(fn [ret x]
  (let [k (f x)]
(assoc! ret k (conj (get ret k []) x
(transient {}) coll)))

This is basically the same as the version I got adding the optional
not-found argument to get instead of using update-in, except that it
uses transients for the performance benefits (and has docstrings and
metadata) and gets rid of the outer let in the same manner as the
final update-in using version I wrote.

-- 
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


Re: I don't understand this exception

2011-01-16 Thread Meikel Brandmeyer
Hi,

The exceptions stems from the call to vec. vec turns a collections
(read: seqable thing) into a vector. The right function calls is
"vector".

(defn my-group-by
  [f coll]
  (let [test (fn [m x]
   (let [res (f x)]
 (if (key? res m)
   (conj (m res) x)
   (assoc m res (vector x)]
(reduce test {} coll)))

Then your conj call, doesn't work. You have to use update-in to update
the vector in case the key is already known.

(defn my-group-by
  [f coll]
  (let [test (fn [m x]
   (let [res (f x)]
 (if (key? res m)
   (update-in m [res] conj x)
   (assoc m res (vector x)]
(reduce test {} coll)))

"key?" is built-in as "contains?".

(defn my-group-by
  [f coll]
  (let [test (fn [m x]
   (let [res (f x)]
 (if (contains? m res)
   (update-in m [res] conj x)
   (assoc m res (vector x)]
(reduce test {} coll)))

You can use fnil to skip the contains? test completely. fnil takes a
function and a value (in the simple case) and replaces the possible
nil as first argument with the given value. So when the map does not
contain the result we will "call" our conj as ((fnil conj []) nil x)
("(conj nil x)"), but fnil will replace the nil with [], so we
actually get (conj [] x). In the next round the result will be
contained and the non-nil value will be passed through to conj. --
Explained quite badly, but I hope you get the idea. Jay Fields also
blogged about fnil recently[1]. You may find his explanation more
clear.

(defn my-group-by
  [f coll]
  (let [test (fn [m x]
   (let [res (f x)]
 (update-in m [res] (fnil conj []) x)))]
(reduce test {} coll)))

Hope that helps.

Sincerely
Meikel

[1]: http://blog.jayfields.com/2011/01/clojure-fnil.html

-- 
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


I don't understand this exception

2011-01-16 Thread Stefan Rohlfing
Hi all,

I am trying to implement the function 'group-by' from Clojure.Core
using my current knowledge of Clojure but cannot get pass a
java.lang.Exception.

This is the code so far:

(defn key? [key coll]
  (some #{key} (keys coll)))

(defn my-group-by [f coll]
  (let [test (fn [m x]
   (let [res (f x)]
 (if (key? res m)
   (conj (m res) x)
   (assoc m res (vec x)]
(reduce test {} coll)))


Calling 'my-group-by' throws an exception:

(my-group-by (fn [x] (mod x 3)) [0 1 2 3 4 5 6 7 8 9 10])

;; java.lang.Exception: Unable to convert: class java.lang.Integer to
Object[] (repl-1:2)

This is the result that should have been returned if everything was
correct:

{2 (2 5 8), 1 (1 4 7 10), 0 (0 3 6 9)}

So, far I have been unable to find the place in my code where an
Integer  is passed incorrectly. Any suggestions are highly
appreciated!

Best regards,

Stefan

-- 
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


Re: thinking parallel programming

2011-01-16 Thread Tim Daly



Excellent. I am taking notes on Steele's talk and adding them
to the CiSP parallel section. In Clojure it might be possible
to dynamically change the number of processes. With the
bit-partition idea is might even be convenient.




There was some discussion about this topic after David Liebke's talk
at the conj about the prototype fork/join filter/map/etc work that
Rich did.  The talk isn't out on video yet but slides are here:
http://incanter.org/downloads/fjclj.pdf

and I wrote up some of these notes here:
http://tech.puredanger.com/2010/10/25/conj-parallel/

There is a natural question when invoking a sequence operation over a
data set in parallel about what the natural granularity is and Rich's
implementation is currently using 32, which is already embedded in the
underlying data structure.  He mentioned another obvious option would
be 1 as it allows the creator of the sequence to control the chunking
in the sequence directly.  We also talked a little about Guy's talk
and idea of marking a function (in meta) as associative and
appropriate for use in a parallel reduce.



On Jan 16, 1:13 pm, Tim Daly  wrote:

   Steele is advocating binaries trees as an way of
doing parallel computation. I think that this idea
is reasonable but might be more effectively applied
in Clojure.

The idea of "binary" could be expanded in a very
simple way to use log32 instead which is a natural
mapping to the Clojure data structures.

However, this might be too coarse for some computations.
I would propose a middle-course between these two ideas.

I suggest that there is a natural mapping between the
bit-partitioning of data structures in Clojure (see the
section on Bit-Partitioned Hash Tries in CiSP) and the
partitioning of a problem for parallel work.

If the bit-partitioning is variable as a function of
the "size of the work pieces" and "the number of
parallel processors", that is,
(partition chunksize processors)
then we can dynamically decide how to break up a
computation on a data structure.

Tim Daly


--
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


Re: thinking parallel programming

2011-01-16 Thread Alex Miller
There was some discussion about this topic after David Liebke's talk
at the conj about the prototype fork/join filter/map/etc work that
Rich did.  The talk isn't out on video yet but slides are here:
http://incanter.org/downloads/fjclj.pdf

and I wrote up some of these notes here:
http://tech.puredanger.com/2010/10/25/conj-parallel/

There is a natural question when invoking a sequence operation over a
data set in parallel about what the natural granularity is and Rich's
implementation is currently using 32, which is already embedded in the
underlying data structure.  He mentioned another obvious option would
be 1 as it allows the creator of the sequence to control the chunking
in the sequence directly.  We also talked a little about Guy's talk
and idea of marking a function (in meta) as associative and
appropriate for use in a parallel reduce.



On Jan 16, 1:13 pm, Tim Daly  wrote:
>   Steele is advocating binaries trees as an way of
> doing parallel computation. I think that this idea
> is reasonable but might be more effectively applied
> in Clojure.
>
> The idea of "binary" could be expanded in a very
> simple way to use log32 instead which is a natural
> mapping to the Clojure data structures.
>
> However, this might be too coarse for some computations.
> I would propose a middle-course between these two ideas.
>
> I suggest that there is a natural mapping between the
> bit-partitioning of data structures in Clojure (see the
> section on Bit-Partitioned Hash Tries in CiSP) and the
> partitioning of a problem for parallel work.
>
> If the bit-partitioning is variable as a function of
> the "size of the work pieces" and "the number of
> parallel processors", that is,
>    (partition chunksize processors)
> then we can dynamically decide how to break up a
> computation on a data structure.
>
> Tim Daly

-- 
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


Tagless-final Interpretations in Clojure (can it be done better than this?)

2011-01-16 Thread Nathan Sorenson
After reading Oleg's lecture Typed tagless-final interpretations
( http://okmij.org/ftp/tagless-final/course/ ), I decided to see if
this was possible, or made any sense, to follow this style in
Clojure.

The idea is that, instead of representing a DSL syntax as a data
structure that you interpret, you represent syntax directly as
functions, which dispatch (in the Haskell case, using type classes)
depending on how you want to interpret the expressions. This approach
lets you extend the syntax easily, as well as add new interpreters
easily.  Thus, you can avoid the expression problem when creating your
DSLs.

In Clojure, we can't dispatch on return types, so the best I came up
is https://gist.github.com/782454 which dispatches on a dynamic var
(also attached below). I would have liked to use protocols somehow,
but it's not clear how this could be done. Clearly we have, at compile
time, all the information regarding which specialized method to call
-- we shouldn't have to use slow multimethods. Speed isn't important
in this simple example, but it might become critical if we were to
interpret huge expression trees.

;the gist:  https://gist.github.com/782454

(def *interpreter* nil)
(defmulti lit (fn [i] *interpreter*))
(defmulti neg (fn [i] *interpreter*))
(defmulti add (fn [a b] *interpreter*))

;'eval' instance
(defmethod lit :evaluate [x] x)
(defmethod neg :evaluate [x] (- x))
(defmethod add :evaluate [x y] (+ x y))

;'show' instance
(defmethod lit :show [x] (str x))
(defmethod neg :show [x] (str "(-" x ")"))
(defmethod add :show [x y] (str "(" x " + " y ")"))

(defmacro evaluate [expr]
(binding [*interpreter* :evaluate]
(eval expr)))

(defmacro show [expr]
(binding [*interpreter* :show]
(eval expr)))


;(evaluate (add (lit 3) (neg (lit 2
;> 1

;(show (add (lit 3) (neg (lit 2
;> "(3 + (-2))"

-- 
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


Re: Grabbing Rotten Tomatoes movie ratings in clojure

2011-01-16 Thread Stuart Campbell
Hi,

Have you used Enlive[1]? It's a nice tool for HTML scraping and templating -
it might be more robust than your regexp-based solution. It takes a bit of
learning, though.

Regards,
Stuart

[1] https://github.com/cgrand/enlive

On 16 January 2011 05:57, justinhj  wrote:

> Sharing my first useful Clojure program. Feedback welcome.
>
> http://bit.ly/clojure-rotten-tomatoes
>
>
>
>  --
> 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 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

Re: Enhanced Primitive Support Syntax

2011-01-16 Thread chris
Is it insane to suggest that perhaps clojure should work with scala
such that we can write both languages in the same file?

Use scala to do you strongly typed work and things where you are
really concerned that auto-promotion.  Let the language made for
helping a programmer lots of information about his/her code (and
perhaps overspecify the solution a gross amount) be used where that is
necessary.

Look, annotating shit in a clojure file to ensure you don't have a
crapload of boxing and inference going in is a large PITA.  So in
areas where you know you are going to need to do lots of things like
that, why wouldn't you use scala?

Specifying the type of everything going on is obviously, for a lot of
cases, grossly overspecifying the problem.  But what if we could just
write scala code in a clojure file or vice versa?  It seems that you
would bypass a lot of the odder 'improvements' to clojure for expert
users and just be better off.

Obviously one of the answers is 'if you think it is a good idea then
you do it' and I don't have the time.  But I know this:

1.  Meta programming is an insanely powerful tool for compressing
code.
2.  Type inference is insanely powerful for producing programs that do
'exactly' what the programming said they should.
3.  Clojure-in-java is fast and thus clojure-in-scala would be fast,
no language additions required.  And probably 30-50% shorter but
perhaps not more than that.
4.  Type annotations are as bad as C programming in terms of verbosity
and to write fast code you need them.  A little inference would make a
large difference.

Types in a lisp-like language suck.  There isn't a way around it.
Lets use a powerful type-inference tool where appropriate and ditch
them completely where it is inappropriate.

You want a hover-over or tooltip to tell you what type something is
producing or taking (or to guarantee details about what you are
doing)?  Use scala.

You want to write extremely compressed code in a way that is very easy
to change and specifies as little of the answer to the problem as
possible (thus giving a lot of leeway for implementation and
extension)?  Use clojure.

Chris

-- 
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


Re: Clojure Quizzes?

2011-01-16 Thread Stuart Campbell
On 17 January 2011 13:48, John Svazic  wrote:

> Benny already answered, but here's the common block that I'm using for
> my Clojure submissions:
>
> (import '(java.io BufferedReader FileReader))
> (defn process-file [file-name]
>  (let [rdr (BufferedReader. (FileReader. file-name))]
>(line-seq rdr)))
>
> (defn my-func [col]
>  ; Do something interesting
> )
>
> (println (my-func (process-file (first *command-line-args*
>
> Basically I read the lines of the file into a sequence, then process
> that sequence in my function.  Since I'm only dealing with the first
> parameter passed to my script, a (first *command-line-args*) call is
> equivalent to args[0] in other languages like Java.
>

If you include clojure.contrib.io, you could use read-lines:

(defn read-lines
  "Like clojure.core/line-seq but opens f with reader.  Automatically
  closes the reader AFTER YOU CONSUME THE ENTIRE SEQUENCE."
  [f]
  (let [read-line (fn this [^BufferedReader rdr]
(lazy-seq
 (if-let [line (.readLine rdr)]
   (cons line (this rdr))
   (.close rdr]
(read-line (reader f

Regards,
Stuart

-- 
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

Re: Clojure Quizzes?

2011-01-16 Thread John Svazic
Benny already answered, but here's the common block that I'm using for
my Clojure submissions:

(import '(java.io BufferedReader FileReader))
(defn process-file [file-name]
  (let [rdr (BufferedReader. (FileReader. file-name))]
(line-seq rdr)))

(defn my-func [col]
  ; Do something interesting
)

(println (my-func (process-file (first *command-line-args*

Basically I read the lines of the file into a sequence, then process
that sequence in my function.  Since I'm only dealing with the first
parameter passed to my script, a (first *command-line-args*) call is
equivalent to args[0] in other languages like Java.

On Jan 16, 5:03 pm, "Randy J. Ray"  wrote:
> On 01/12/2011 11:50 PM, Robert McIntyre wrote:
>
> > They seem to allow you to include anything in a lib directory that you'd 
> > want.
>
> > I sometimes include apache commons-io and clojure-contrib1.2 without
> > any problems.
> > I also included a sql connection library for one of the problems, so
> > it seems fine :)
>
> For those puzzles that require command-line processing, have you used a 
> library
> to do it? Looking in both "Programming Clojure" and "Practical Clojure", the
> only instruction I can find on handling command-line args involves AOT
> compilation of your class and definition of a -main method. I'm not sure how
> well this would work with the submission model that Coderloop uses.
>
> I'm afraid I'm still *very* new to Clojure, and while it would be easy (for 
> me)
> to solve the problems in other languages, the point of the exercise (for me) 
> is
> to use Coderloop's problems to help myself in learning Clojure...
>
> Randy
>
> --
> """ 
> 
> Randy J. Ray                 Sunnyvale, CA                http://www.rjray.org
> rj...@blackperl.com                                        http://www.svsm.org
> randy.j@gmail.com                                  
> http://twitter.com/rjray

-- 
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


Re: Enhanced Primitive Support Syntax

2011-01-16 Thread Sean Corfield
On Sun, Jan 16, 2011 at 3:50 PM, Jason Wolfe  wrote:
> Moreover, we do not need to redefine the class at run-time.  A simple
> way to do this: when you compile a function with arithmetic
> operations, concatenate bytecode for two versions: essentially, one
> with the unprimed (exception-throwing) ops and one with the primed
> (overflowing) ones.  Now, replace the exceptions in the first path
> with local jumps into the second path.  There are probably ways to get
> around generating two copies of the bytecode in advance, and making
> such a unilateral shift to inefficient semantics, but I don't know
> enough about JVM internals to say for sure.

The problem is that if you have an arbitrary form that can operate
entirely in primitives (some loop/recur perhaps) and you allow
primitives to magically convert to Objects in that code, then the
entire piece of code has to handle both primitives AND Objects and
every single sub-form must be capable of handling primitives as input
AND Objects as input and returning primitives if possible...

You can't have automatic promotion to Object from primitive and expect
any reasonable code to be generated that can maintain primitive
performance across arbitrary expressions. Either everything can work
with Objects - and you lose performance - or everything must be able
to work within primitives (and at most throw exceptions) and remain
performant.
-- 
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

-- 
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


Re: Enhanced Primitive Support Syntax

2011-01-16 Thread Jason Wolfe

> >> (a) unsafe/incorrect value on overflow/fastest/unifiable* vs.
> >> (b) safe/error on overflow/fast/unifiable vs.
> >> (c) safe/promoting on overflow/slow/not-unifiable
>
> > If I understand correctly, the issue with auto-promotion is that we
> > have to box the output of an operation even if it turns out to fit in
> > a long, since the compiler must specify whether the result will be
> > long or Object.
>
> > This is probably a stupid question, but since Clojure is already
> > testing for overflow in (b) to throw an exception, would it be
> > possible to jump into an alternative (c)-type compilation of the
> > function just-in-time to promote on overflow instead?  It seems like
> > this could achieve the performance of (b) while still allowing for
> > auto-promotion (albeit perhaps with a performance hit in that case,
> > code bloat, compromises about how many versions to compile, etc.).
>
> When Clojure compiles your function, it emits JVM bytecode for a new
> class which is then loaded by the classloader.  That JVM bytecode
> defines a function (well, a method as far as the JVM is concerned)
> which returns either a primitive type or Object.  Your suggestion
> would involve redifining the class while it is executing.  That's not
> possible on the JVM.  Even if it were possible -- your function now
> returns Object instead of long.  

If I understand correctly, the return type of your function is not up
for interpretation.  It is Object if undeclared, and primitive only if
declared -- so that is not a problem (if you ask for long, that's what
you'll get).  I am only talking about behavior within a single
function call -- no calling code needs to change.

Moreover, we do not need to redefine the class at run-time.  A simple
way to do this: when you compile a function with arithmetic
operations, concatenate bytecode for two versions: essentially, one
with the unprimed (exception-throwing) ops and one with the primed
(overflowing) ones.  Now, replace the exceptions in the first path
with local jumps into the second path.  There are probably ways to get
around generating two copies of the bytecode in advance, and making
such a unilateral shift to inefficient semantics, but I don't know
enough about JVM internals to say for sure.

-- 
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


Re: Enhanced Primitive Support Syntax

2011-01-16 Thread Armando Blancas
> Then again, how often do you write code that might be
> doing maths with numbers that big and not realise it?  For that
> matter, how often do you write code that might be doing maths with
> numbers that big and not spend time thinking carefully about its
> performance anyway?

This reminds me of a little joke:

Cooper: Honey, will you please - what are the odds of the Russians
attacking on a Thursday night?
--The Man with One Red Shoe (1985)

Having heard from various posters how reasonable it all is, and from
Rich now necessary [1], I still have a feeling that the implications
and consequences of the new semantics aren't well understood, and if
anything, any points of real concerned are downplayed. I'll second
Mark's concerns, above. Like others, I don't like to annotate and
postquote my way to the semantics I want, but that may be the easy
part. But I hope I'm wrong; I guess we'll see.

[1] (in this thread
http://groups.google.com/group/clojure/browse_thread/thread/c8c850595c91cc11/8a4eee5ac4eab3f9?lnk=gst&q=autopromotion#8a4eee5ac4eab3f9)

-- 
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


Re: Clojure Quizzes?

2011-01-16 Thread Benny Tsai
Hi Randy,

You can access a seq of the command line args via the *command-line-
args* var.

On Jan 16, 3:03 pm, "Randy J. Ray"  wrote:
> On 01/12/2011 11:50 PM, Robert McIntyre wrote:
>
> > They seem to allow you to include anything in a lib directory that you'd 
> > want.
>
> > I sometimes include apache commons-io and clojure-contrib1.2 without
> > any problems.
> > I also included a sql connection library for one of the problems, so
> > it seems fine :)
>
> For those puzzles that require command-line processing, have you used a 
> library
> to do it? Looking in both "Programming Clojure" and "Practical Clojure", the
> only instruction I can find on handling command-line args involves AOT
> compilation of your class and definition of a -main method. I'm not sure how
> well this would work with the submission model that Coderloop uses.
>
> I'm afraid I'm still *very* new to Clojure, and while it would be easy (for 
> me)
> to solve the problems in other languages, the point of the exercise (for me) 
> is
> to use Coderloop's problems to help myself in learning Clojure...
>
> Randy
>
> --
> """ 
> 
> Randy J. Ray                 Sunnyvale, CA                http://www.rjray.org
> rj...@blackperl.com                                        http://www.svsm.org
> randy.j@gmail.com                                  
> http://twitter.com/rjray

-- 
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


Re: Clojure Quizzes?

2011-01-16 Thread Randy J. Ray

On 01/12/2011 11:50 PM, Robert McIntyre wrote:

They seem to allow you to include anything in a lib directory that you'd want.

I sometimes include apache commons-io and clojure-contrib1.2 without
any problems.
I also included a sql connection library for one of the problems, so
it seems fine :)


For those puzzles that require command-line processing, have you used a library 
to do it? Looking in both "Programming Clojure" and "Practical Clojure", the 
only instruction I can find on handling command-line args involves AOT 
compilation of your class and definition of a -main method. I'm not sure how 
well this would work with the submission model that Coderloop uses.


I'm afraid I'm still *very* new to Clojure, and while it would be easy (for me) 
to solve the problems in other languages, the point of the exercise (for me) is 
to use Coderloop's problems to help myself in learning Clojure...


Randy

--
"""
Randy J. Ray Sunnyvale, CA http://www.rjray.org
rj...@blackperl.com http://www.svsm.org
randy.j@gmail.com  http://twitter.com/rjray

--
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


Re: Why does (.foo (new Bar)) use a different method invocation mechanism than (def bar (new Bar)) (.foo bar)?

2011-01-16 Thread Robert Campbell
Thank you for the explanation Rasmus. I tried (.foo ^Bar bar) and it
behaved exactly like (.foo (new Bar)) as you suggested.

So method invocation via reflection works, while invokevirtual does
not. As a sanity check I compared the bytecode of an AOT'd (working)
invocation of a method compiled and loaded before the JRebel reload
with a failing invocation after the reload. As expected they both
contain the exact same code:

  71c71
  <10:  invokevirtual   #32; //Method 
foo/core/Bar.sayAhoj:()Ljava/lang/String;
  ---
  >10:  invokevirtual   #32; //Method
foo/core/Bar.sayHello:()Ljava/lang/String;

The only difference I've been able to spot so far between the vanilla
method invocations (pre JRebel reloading) and the freshly added and
reloaded method invocations is in the object expression:

  InstanceMethodExpr for sayAhoj (newly reloaded JRebel, broken):
  method.clazz = class foo.core.Bar$$M$8e38ee87
  method.parameterTypes = java.lang.Class[1], [0] = [class foo.core.Bar]

  InstanceMethodExpr for sayHello (loaded initially, working):
  method.clazz = class foo.core.Bar
  method.parameterTypes = java.lang.Class[0]

This mostly makes sense since I'm assuming JRebel has to load a new
class and perform some behind the scenes magic to write it up to look
like the original. The extra parameter looks like the [this] from the
function. I tried setting these values to match the sayHello versions,
but it didn't help.

Those differences don't seem to actually matter since at the end of
the day the compiled bytecode is twi identical invokevirtuals.

Rob



On Sun, Jan 16, 2011 at 7:22 PM, Rasmus Svensson  wrote:
> 2011/1/16 Robert Campbell :
>> The second form - (.foo bar), expanded to (. bar foo) - eventually
>> calls Reflector.invokeNoArgInstanceMember.
>
> For that form, the clojure compiler cannot infer the type of bar, and
> does not know which exact method (class + type signature) .foo
> represents. Due to this, a runtime lookup that uses the reflector is
> inserted, since a method invocation in java byte code must be
> statically typed (at least currently).
>
>> The first form - (.foo (new Bar)), expanded to (. (new Bar) foo) -
>> doesn't seem to use any Reflector _invocation_ methods. I also added a
>> breakpoint to java.lang.reflect.Method.invoke() and it never hits that
>> breakpoint.
>
> This is because the compiler knows the type of the arg to .foo, and
> can emit bytecode for a plain old (statically typed) method
> invocation.
>
> Since reflective method invocations are pretty slow, you often try to
> add type hints so that it can be avoided: (.foo ^Bar bar) The
> generated bytecode for this method invocation should be very similar
> (if not identical) to the bytecode for (.foo (new Bar))
>
> // raek
>
> --
> 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 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


Re: list* does not make a list?

2011-01-16 Thread Sean Allen
the documentation on that could be improved. the doc string for that
is basically the same as for list. but they return different types.

rather surprising when you first see it.

On Sun, Jan 16, 2011 at 1:55 PM, Alan  wrote:

> list* consumes its last argument lazily, which means it can't count it
> (a requirement to be a real list). Both functions return objects that
> are seqs, though, so you can (seq?) them if you want.
>
> user=> (def x (list* (range)))
> #'user/x
> user=> (def x (apply list (range)))
> java.lang.OutOfMemoryError: Java heap space (NO_SOURCE_FILE:4)
>
>
> On Jan 16, 10:21 am, Brian Marick  wrote:
> > movies.core> (list? (apply list (map identity [1 2 3])))
> > true
> >
> > Makes sense to me!
> >
> > movies.core> (list? (list* (map identity [1 2 3])))
> > false
> >
> > Huh?
> >
> > -
> > Brian Marick, Artisanal Labrador
> > Contract programming in Ruby and Clojure
> > Author of /Ring/ (forthcoming; sample:
> http://bit.ly/hfdf9T)www.exampler.com,www.exampler.com/blog,www.twitter.com/marick
>
> --
> 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 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

Re: list* does not make a list?

2011-01-16 Thread Brian Marick
On Jan 16, 2011, at 12:55 PM, Alan wrote:

> list* consumes its last argument lazily, which means it can't count it


That is indeed what it does. seq* would have been a better name. Too late now, 
I guess.

-
Brian Marick, Artisanal Labrador
Contract programming in Ruby and Clojure
Author of /Ring/ (forthcoming; sample: http://bit.ly/hfdf9T)
www.exampler.com, www.exampler.com/blog, www.twitter.com/marick

-- 
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


Re: thinking parallel programming

2011-01-16 Thread Tim Daly

 Steele is advocating binaries trees as an way of
doing parallel computation. I think that this idea
is reasonable but might be more effectively applied
in Clojure.

The idea of "binary" could be expanded in a very
simple way to use log32 instead which is a natural
mapping to the Clojure data structures.

However, this might be too coarse for some computations.
I would propose a middle-course between these two ideas.

I suggest that there is a natural mapping between the
bit-partitioning of data structures in Clojure (see the
section on Bit-Partitioned Hash Tries in CiSP) and the
partitioning of a problem for parallel work.

If the bit-partitioning is variable as a function of
the "size of the work pieces" and "the number of
parallel processors", that is,
  (partition chunksize processors)
then we can dynamically decide how to break up a
computation on a data structure.

Tim Daly

--
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


Re: list* does not make a list?

2011-01-16 Thread Alan
list* consumes its last argument lazily, which means it can't count it
(a requirement to be a real list). Both functions return objects that
are seqs, though, so you can (seq?) them if you want.

user=> (def x (list* (range)))
#'user/x
user=> (def x (apply list (range)))
java.lang.OutOfMemoryError: Java heap space (NO_SOURCE_FILE:4)


On Jan 16, 10:21 am, Brian Marick  wrote:
>     movies.core> (list? (apply list (map identity [1 2 3])))
>     true
>
> Makes sense to me!
>
>     movies.core> (list? (list* (map identity [1 2 3])))
>     false
>
> Huh?
>
> -
> Brian Marick, Artisanal Labrador
> Contract programming in Ruby and Clojure
> Author of /Ring/ (forthcoming; 
> sample:http://bit.ly/hfdf9T)www.exampler.com,www.exampler.com/blog,www.twitter.com/marick

-- 
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


Re: Why does (.foo (new Bar)) use a different method invocation mechanism than (def bar (new Bar)) (.foo bar)?

2011-01-16 Thread Rasmus Svensson
2011/1/16 Robert Campbell :
> The second form - (.foo bar), expanded to (. bar foo) - eventually
> calls Reflector.invokeNoArgInstanceMember.

For that form, the clojure compiler cannot infer the type of bar, and
does not know which exact method (class + type signature) .foo
represents. Due to this, a runtime lookup that uses the reflector is
inserted, since a method invocation in java byte code must be
statically typed (at least currently).

> The first form - (.foo (new Bar)), expanded to (. (new Bar) foo) -
> doesn't seem to use any Reflector _invocation_ methods. I also added a
> breakpoint to java.lang.reflect.Method.invoke() and it never hits that
> breakpoint.

This is because the compiler knows the type of the arg to .foo, and
can emit bytecode for a plain old (statically typed) method
invocation.

Since reflective method invocations are pretty slow, you often try to
add type hints so that it can be avoided: (.foo ^Bar bar) The
generated bytecode for this method invocation should be very similar
(if not identical) to the bytecode for (.foo (new Bar))

// raek

-- 
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


list* does not make a list?

2011-01-16 Thread Brian Marick
movies.core> (list? (apply list (map identity [1 2 3])))
true

Makes sense to me!

movies.core> (list? (list* (map identity [1 2 3])))
false

Huh?

-
Brian Marick, Artisanal Labrador
Contract programming in Ruby and Clojure
Author of /Ring/ (forthcoming; sample: http://bit.ly/hfdf9T)
www.exampler.com, www.exampler.com/blog, www.twitter.com/marick

-- 
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


Re: Typos in (doc add-watch)

2011-01-16 Thread Stuart Halloway
The 'if' is terse, but correct: call is on agent's thread only when reference 
is an agent, and before pending sends only when reference is an agent or ref.

Cheers,
Stu

> Hi,
> 
> I think there're two typos in
> http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/add-watch
> - I believe 'if' should become 'of':
> 
> The watch fn will be called synchronously, on the agent's thread if an
> agent, before any pending sends if agent or ref.
> 
> should become
> 
> The watch fn will be called synchronously, on the agent's thread of an
> agent, before any pending sends of agent or ref.
> 
> Jacek
> 
> -- 
> Jacek Laskowski
> Java EE, functional languages and IBM WebSphere - http://blog.japila.pl
> 
> -- 
> 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 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


Why does (.foo (new Bar)) use a different method invocation mechanism than (def bar (new Bar)) (.foo bar)?

2011-01-16 Thread Robert Campbell
I've been trying to understand exactly how these two statements are
evaluated by tracing execution through Compiler.java, Reflector.java,
etc of tag 1.2.0.

The second form - (.foo bar), expanded to (. bar foo) - eventually
calls Reflector.invokeNoArgInstanceMember.

The first form - (.foo (new Bar)), expanded to (. (new Bar) foo) -
doesn't seem to use any Reflector _invocation_ methods. I also added a
breakpoint to java.lang.reflect.Method.invoke() and it never hits that
breakpoint.

It seems that Reflector.getMethods is actually used to resolve Methods
for placement in the object expression "ObjExpr fexpr" on line 5421 of
Compiler.java. After that poing I'm unable to trace where the actual
invocation takes place.

I am trying to understand how the first form gets evaluated because I
have a case where JRebel instrumentation causes this to work:

(def bar (new foo.core.Bar))
#'user/bar
(.sayAhoj bar)
"Ahoj!"

but this to fail:

(.sayAhoj (new foo.core.Bar))
java.lang.NoSuchMethodError: foo.core.Bar.sayAhojLjava/lang/String;
(NO_SOURCE_FILE:0)

even though the method appears in the stub and can be invoked fine via
reflection. More information here:

http://blog.robert-campbell.com/post/2760935713/clojures-gen-class-and-jrebel

-- 
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


Typos in (doc add-watch)

2011-01-16 Thread Jacek Laskowski
Hi,

I think there're two typos in
http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/add-watch
- I believe 'if' should become 'of':

The watch fn will be called synchronously, on the agent's thread if an
agent, before any pending sends if agent or ref.

should become

The watch fn will be called synchronously, on the agent's thread of an
agent, before any pending sends of agent or ref.

Jacek

-- 
Jacek Laskowski
Java EE, functional languages and IBM WebSphere - http://blog.japila.pl

-- 
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


Re: Enhanced Primitive Support Syntax

2011-01-16 Thread Sam Roberton
On 16 January 2011 05:35, Jason Wolfe  wrote:
>> (a) unsafe/incorrect value on overflow/fastest/unifiable* vs.
>> (b) safe/error on overflow/fast/unifiable vs.
>> (c) safe/promoting on overflow/slow/not-unifiable
>
> If I understand correctly, the issue with auto-promotion is that we
> have to box the output of an operation even if it turns out to fit in
> a long, since the compiler must specify whether the result will be
> long or Object.
>
> This is probably a stupid question, but since Clojure is already
> testing for overflow in (b) to throw an exception, would it be
> possible to jump into an alternative (c)-type compilation of the
> function just-in-time to promote on overflow instead?  It seems like
> this could achieve the performance of (b) while still allowing for
> auto-promotion (albeit perhaps with a performance hit in that case,
> code bloat, compromises about how many versions to compile, etc.).

When Clojure compiles your function, it emits JVM bytecode for a new
class which is then loaded by the classloader.  That JVM bytecode
defines a function (well, a method as far as the JVM is concerned)
which returns either a primitive type or Object.  Your suggestion
would involve redifining the class while it is executing.  That's not
possible on the JVM.  Even if it were possible -- your function now
returns Object instead of long.  But the variable that the result of
your function is about to be assigned to is a long, because that's
what your function used to be defined to return, and the next bytecode
operation in the calling code is the one that subtracts a primitive
long from a primitive long.  Now what?

Fundamentally, Clojure has to contend with the fact that the JVM as a
platform distinguishes between primitives and Objects.  The bytecode
operations which the Clojure compiler emits have to differ based on
that distinction.  Essentially, the distinction cannot be magicked
away, because JVM bytecode is going to statically enforce that we're
either working with a (long or double) or a (Long or BigInt or
BigDecimal or whatever), and never the twain shall meet.  So if we
ever want to be able to access the speed of the primitive bytecode
operations, then the primitive/Object distinction has to leak into
Clojure.  (Or we have to redefine or move away from the JVM.
Obviously not really an option, but I mention it to point out that the
reason Clojure has to make this decision is that it's a hosted
language.  That has a lot of benefits;  this is one of the trade-offs
we have to contend with in return.)

I think everyone agrees that it's important to make the speed of the
primitive bytecode operations available in Clojure (whether or not
it's the default), so that rules out the option of always doing
auto-promotion.  I think it's probably also agreed that allowing
unchecked overflow is not good (at least, no one seems to be arguing
for it).

So we're left with option (b) and a choice about the default behaviour
of the core library functions.  If we default to boxing and treating
everything as an Object then we get the nice comfy numeric tower that
we never have to worry about, but the default case suffers in
performance.  Otherwise, we default to primitive, and accept that if
we're dealing with numbers which might get bigger than Long.MAX_VALUE,
then we might need to explicitly use a BigInt to get contagion, or use
an operator like +' which will always deal with Objects.

By choosing to make speed the default preference in the core library
functions, I suppose there's more for Clojure programmers to think
about, because whenever you're dealing with numbers, you need to have
in the back of your mind the question of whether this might ever need
to be bigger than Long.MAX_VALUE, and so whether you might need +'
instead of +.  Then again, how often do you write code that might be
doing maths with numbers that big and not realise it?  For that
matter, how often do you write code that might be doing maths with
numbers that big and not spend time thinking carefully about its
performance anyway?

-- 
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


Re: check if something can be coerced to a seq

2011-01-16 Thread Ken Wesson
On Sun, Jan 16, 2011 at 6:22 AM, Jürgen Hötzel  wrote:
> Hi,
> I came across this issue while implementing a lazy, efficient flatten that
> also uses the whole sequence abstraction (flatten java arrays).
> The problem with (seq x) is, that it will throw an Exception if called on
> something, that cannot be coerced to sequence, so I just used sequencial?
> like the current implementation of flatten:
> (defn my-flatten [coll]
>   (mapcat (fn [p] (if (sequential? (first p)) (mapcat my-flatten p) p))
>           (partition-by sequential? coll)))
> But this will obviously fail  to flatten anything that doesn't
> implement clojure.lang.Sequential (like java.arrays).

Unfortunately, right now that's a big gap in the clojure.core
functionality. It's quick to fix, though the fix is a bit of a hack as
it uses the exception-throwing behavior of (seq x). On the plus side
this guarantees that it meets its contract.

(defn seqable? [x]
  (try (seq x) (catch Exception _)))

(def m-seq seqable?)

(defn seqable-ns? [x]
  (if-not (instance? java.lang.String x) (seqable? x)))

(def m-seq-ns seqable-ns?)

Anything seqable is returned unchanged by seqable? and m-seq, which
return nil rather than throw if the thing is not seqable. The two
names for the same function are just to improve code readability:
seqable? for use as a predicate and m-seq for uses like

(if-let [x (m-seq foo)] (do-something-with x))

The -ns versions differ only in that they pretend Strings aren't
seqable, for those fairly common cases where you want to treat strings
as atomic rather than as character sequences; for instance if you're
probing a data structure made of nested colls and wish to regard whole
strings as leaf nodes in the traversal instead of their individual
characters.

-- 
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


check if something can be coerced to a seq

2011-01-16 Thread Jürgen Hötzel
Hi,

I came across this issue while implementing a lazy, efficient flatten that
also uses the whole sequence abstraction (flatten java arrays).
The problem with (seq x) is, that it will throw an Exception if called on
something, that cannot be coerced to sequence, so I just used sequencial?
like the current implementation of flatten:

(defn my-flatten [coll]
  (mapcat (fn [p] (if (sequential? (first p)) (mapcat my-flatten p) p))
  (partition-by sequential? coll)))

But this will obviously fail  to flatten anything that doesn't
implement clojure.lang.Sequential (like java.arrays).

Jürgen

-- 
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

Re: thinking parallel programming

2011-01-16 Thread Ken Wesson
On Sun, Jan 16, 2011 at 2:50 AM, Benny Tsai  wrote:
> In the Hacker News discussion about that talk, someone posted a link
> to another talk by Guy Steele on the same topic:
>
> http://vimeo.com/6624203
>
> ... where he covers the material in somewhat greater depth (the
> downside being that by the 30-minute mark, I was struggling to keep up
> with the flow of ideas).

Aside: this is another problem with these videos -- you must go at the
videographer's pace, whereas with a written text (with possible
multimedia embeds, such as diagrams) you can go at your own.

-- 
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