Re: How to write performant functions in clojure (and other functional languages)

2009-07-26 Thread John Harrop
On Sat, Jul 25, 2009 at 4:40 PM, atucker agjf.tuc...@googlemail.com wrote:


 I wonder if any of the Clojurians on here might like to describe how
 one might write the factorial function as a parallel one?  Taking
 advantage of the associativity of multiplication, along the lines of

 16! = (((1*2)*(3*4)) * ((5*6)*(7*8))) * (((9*10)*(11*12)) * ((13*14)*
 (15*16)))


(defn factorial [n]
  (let [cores (.. Runtime (getRuntime) (availableProcessors))]
(if ( n (* 2 cores))
  (reduce * (rest (range (inc n
  (let [parts (pmap #(reduce * %) (partition (quot (inc n) cores) (rest
(range (inc n)]
(reduce * parts)

ought to do it.

--~--~-~--~~~---~--~~
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: Confusion with apply.

2009-07-22 Thread John Harrop
On Wed, Jul 22, 2009 at 5:17 PM, mmwaikar mmwai...@gmail.com wrote:

 So if this is the intended behavior of apply, which function should I
 use in this case? Is there anything in Clojure where I can apply any
 user-defined function to each and every element of a list one-by-one?


Use map:

user= (map #(* 5 %) [1 2 3 4 5])
(5 10 15 20 25)

(Here I also made the multiply-by-five function an anonymous lambda.)

--~--~-~--~~~---~--~~
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: Simple data structure access macro

2009-07-21 Thread John Harrop
On Mon, Jul 20, 2009 at 4:31 PM, Moses mosesam...@gmail.com wrote:


  I come primarily from a perl programming background, but am trying
 to learn Clojure.

  I'm looking for a clojure equivalent to the following.

  Perl:

   my $nestedDS = [ foo, { hi = there, hello = [buddy] }, hi]

   my $foo = $nestedDS-[0];
   my $there = $nestedDS-[1]-{hi};
   my $hello = $nestedDS-[1]-{hello};
   my $hi = $nestedDS-[2];

   print $foo $there $buddy $hi;

   I'm not sure if it exists or not, but hopefully if it doesn't it
 can be created with a macro.

   To clarify, I'm looking for a function/macro that makes use of a
 small DSL for accessing fields within the basic Clojure data
 structures.

   The best I can come up with in Clojure for a DS equivalent to the
 above is:

  (let [nestedDS [foo, {hi there, hello, [buddy]}, hi]
   foo (nth nestedDS 0)
   there (get (nth nestedDS 1) hi)
   buddy (first (get (nth nestedDS 1) hello))
   hi (nth nestedDS 2)]
(print foo there buddy hi)
   )

  Its not that much longer, but if the fields were more deeply nested,
 it would become a bit pretty annoying.

  Does any kind of DS access macro exist? If not, how hard do you
 think it would be to write?

  Something like

buddy (get-it nestedDS [1]-{hello}-[0])

  Or perhaps an even shorter syntax is possible?


Perhaps use nested maps, along with get-in, assoc-in, update-in etc.:

let [nestedDS {:foo foo :greet-map {hi there hello [buddy]} :hi
hi}]

--~--~-~--~~~---~--~~
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: let a variable number of bindings

2009-07-18 Thread John Harrop
On Fri, Jul 17, 2009 at 11:52 PM, Rowdy Rednose rowdy.redn...@gmx.netwrote:


 How can I lexically bind names like let does in a macro, when names
 and values for those bindings are passed in?

 This here works fine when I pass a literal collection:

 (defmacro let-coll
  [coll  body]
  `(let ~(vec coll) ~...@body))

 user= (let-coll [a 11 b 22] (list b a))
 (22 11)

 Doing the same with a var doesn't work though:

 user= (def x ['a 11 'b 22])
 #'user/x
 user= (let-coll x (list b a))
 java.lang.Exception: Unable to convert: class clojure.lang.Symbol to
 Object[] (NO_SOURCE_FILE:0)

 Any ideas?


It'll be evaluating (vec 'x) during macro expansion, which gives that error.
The argument x has to be evaluated for it to work, so you'd need (vec (eval
x)) in there. Then you'll also need to quote when passing in a literal
vector, e.g. (let-coll ['a 11 'b 12] (list b a)).

--~--~-~--~~~---~--~~
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: let a variable number of bindings

2009-07-18 Thread John Harrop
On Sat, Jul 18, 2009 at 1:22 AM, Meikel Brandmeyer m...@kotka.de wrote:

 Using eval is not really a solution.

 (def foo '[a 1 b 2])
 (let-coll foo ...)

 will probably work with eval, but

 (let [foo '[a 1 b 2]]
  (let-coll foo ...))

 will not.


No, for that you need to make the macro run-time, too. This can be done by
turning it into an ordinary function -- change defmacro to defn and wrap
the return value in eval. The argument now doesn't need to be evald, but
the body now needs to be quoted. To fix the latter, you can create a macro
to wrap the function call that quotes the body. The function then builds the
form to be evaluated from the passed-in quoted body and other argument and
calls eval on this.

The downside to this is that the function now has a run-time computation
cost, and won't work in a deployment situation that doesn't support eval.
(Thus far, with Clojure I'm not aware of any, but a stripped-down micro
edition for use on phones might exist in the future where this wouldn't
work.)

On the other hand, run-time access to eval allows a few very powerful
tricks that are otherwise unavailable, including some very interesting ways
of optimizing computations on the fly. In fact, Clojure can grant all the
power of self-modifying code, without (if you avoid eval-ing def forms)
most of the usual pitfalls of same. The JIT-created code even benefits from
the Hotspot JIT in turn, so it's exactly as powerful (and a lot easier! And
more portable) as self-modifying x86 assembly code, which has a history of
being used to run graphics demos on old hardware that many would have
thought incapable of what was done with it. (See
http://www.anioni.com/pauli/site1999/demoscene.html but this sort of thing
long predates hardware 3D acceleration. These days, this sort of capability
will be more of interest for getting maximum performance out of game or
numeric code, or for AI research.)

(Self-modifying assembly also has a history of being misused to write
viruses and make them hard to detect. Clojure is, fortunately, not so useful
for that. :-))

--~--~-~--~~~---~--~~
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: Very minor problem in the REPL

2009-07-17 Thread John Harrop
On Fri, Jul 17, 2009 at 11:31 AM, Stephen C. Gilardi squee...@mac.comwrote:

 It looks like somehow you're seeing a very old REPL or it's not the default
 REPL you get from launching Clojure via clojure.main.


I can confirm the described behavior for the enclojure REPL.

--~--~-~--~~~---~--~~
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: Is there a standard function testing if a sequence starts with a sequence

2009-07-17 Thread John Harrop
On Fri, Jul 17, 2009 at 4:41 PM, Mark Engelberg mark.engelb...@gmail.comwrote:


 On Fri, Jul 17, 2009 at 1:32 PM, samppirbysam...@gmail.com wrote:
 
  Is there a function in clojure.core or clojure.contrib so that:
   (and (mystery-fn '(a b c d) '(a b))
 (not (mystery-fn '(a b c d) '(a b d


 how about something like:
 (defn mystery-fn [l1 l2] (every? identity (map = l1 l2)))


user= (mystery-fn '(a b) '(a b c d))
true

How about something like:
(defn mystery-fn [l1 l2] (and (= (count l2) (count l1)) (every? identity
(map = l1 l2

--~--~-~--~~~---~--~~
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: How to achieve indirection?

2009-07-16 Thread John Harrop
On Thu, Jul 16, 2009 at 11:34 AM, Dragan draga...@gmail.com wrote:

 Thanks for the tip, I meant something else.
 Let's say that I want to write a function do-something. There could be
 2 implementations: do-something-quickly and do-something-elegantly.
 The parameters are the same and there are no differences in their
 interface. I would like to be able to call it by  writing (do-
 something arg) in my code and specify which implementation I want to
 use somewhere else (in the configuration part of the code).


Functions are values you can pass around, so:

(defn do-something-quickly [x y] ... )
(defn do-something-elegantly [x y] ... )

(defn do-various-things [do-something x y z w]
  (let [z (do-something x y)]
... ))

user= (do-various-things do-something-quickly 13 19 3 23)
some-sort-of-output
user= (do-various-things do-something-elegantly 13 19 3 23)
some-sort-of-output

--~--~-~--~~~---~--~~
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: Performance question (newbie)

2009-07-15 Thread John Harrop
On Wed, Jul 15, 2009 at 11:39 AM, B Smith-Mannschott
bsmith.o...@gmail.comwrote:

 An explicit loop with some type hints is faster, though likely not as
 fast as Java:

 (defn sum-of-range-4 [range-limit]
  (loop [i (int 1) s (long 0)]
(if ( i range-limit)
  (recur (inc i) (+ s i))
  s)))

 This took 20.275s for the same scenario.


Use unchecked-add and unchecked-inc in place of + and inc and you should get
equivalent speed.

--~--~-~--~~~---~--~~
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: EY map reduce contest

2009-07-15 Thread John Harrop
On Wed, Jul 15, 2009 at 4:53 AM, hosia...@gmail.com hosia...@gmail.comwrote:



 http://www.engineyard.com/blog/2009/programming-contest-win-iphone-3gs-2k-cloud-credit/

 Has anyone got access to hundreds of thousands of machines that I
 could borrow for 30 hours ? ;)


Don't know any botnet herders; sorry. :)

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

2009-07-15 Thread John Harrop
On Wed, Jul 15, 2009 at 12:58 PM, Mark Engelberg
mark.engelb...@gmail.comwrote:

 It looks like stack-rot is going to be the bottleneck in your app
 since it requires traversing the whole vector to build the new one,
 but I think the list-based implementation would be a bit worse, so I
 think your choice to use vectors here is sound.

 For stack-dropn and stack-rot to both be fast, I think that you really
 want to use a deque.  Unfortunately, Clojure doesn't have a built-in
 deque, and I don't see one in contrib, but you could look at
 clojure.lang.PersistentQueue and read Okasaki's Functional Data
 Structures to draw some inspiration.


What's needed here is a ring buffer. It shouldn't be hard to implement one
atop a pair of a clojure vec, a true-count, and a start-offset. Rotation is
then very cheap: replace v with (assoc v (- (+ start-offset true-count)
(count v)) (get v start-offset)) and start-offset with (let [s-o (inc
start-offset)] (if (= (count v) s-o) 0 s-o)). Dropn is similarly: true-count
becomes (- n true-count) and start-offset (mod (+ start-offset n) (count
v)). Indexing is cheap: (get v (mod (+ start-offset (mod index true-count))
(count v))) and peek is even cheaper: (get v start-offset). (Maybe add code
to handle empty, that is, (= 0 true-count)). The tricky thing is push. If (=
true-count (count v)) the vector needs to be copied to a larger vector. You
might want to double the size, leaving the unused elements nil: v becomes
(vec (concat (drop start-offset v) (take start-offset
v) [new-element] (repeat true-count nil))), true-count is inc'd as normal
for a push, and start-offset reset to zero. Doubling the size whenever the
vector must grow causes the cost of copying the vector to be asymptotically
constant per push, instead of linear in the average size of the vector at
the time of a push.

(Ironically, the vector probably has this behavior under the hood, like
java.util.ArrayList, but we need it again because  (vec (concat (drop
start-offset v) (take start-offset v) [new-element] (repeat true-count
nil))) has linear time-complexity in vector length.)

You'd actually want to use a structmap for the above if you want to have
multiple ring buffers, with struct keys :count, :offset, and :vector or
similarly. Depending on the application, you might want to make the values
for these keys be refs and have the ring buffer operations use dosync,
though you could instead use a single ref per instance of the structmap.

--~--~-~--~~~---~--~~
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: Compilation troubles...

2009-07-13 Thread John Harrop
On Mon, Jul 13, 2009 at 3:11 PM, Morgan Allen alfred.morgan.al...@gmail.com
 wrote:

 It's a shame about the lack of official support for java-side
 invocation- the bulk of my code is still implemented in java (largely
 for efficiency reasons), so it would be handy to be able to initiate
 things largely from that side.


It's definitely not necessary to implement the bulk of your code in Java to
get performance. On the other hand, getting performance out of Clojure can
be tricky.

First, you need to know how to use loop/recur, type hints, primitives, and
such, not just separately but in harmony. With that, you can get inner loops
that will run, on the server VM, at C-code speeds, not unlike a tight loop
in Java that avoids method calls.

Second, if you need significant flexibility and variability and conditioning
in those loops, but not inside any given instance of running a loop for a
while, you need to get comfortable with macros -- backquote, unquote and
unquote-splicing, gensyms, and the works. With those, you can customize the
loop at each site in the program code so that decisions that don't have to
be made every iteration are made entirely outside of the loop, and each loop
instance has a particular, optimized form built in. This will give you
flexibility coupled with blazing speed.

I currently have a project on the go that has performance-critical CPU-bound
work that involves an open-ended, runtime-changeable set of parameters; a
simulation of sorts. I have it running probably faster than C code could
manage, because it actually uses eval and programmatically-constructed code
to compile new functions on the fly to do the bottleneck parts of the
computations. The resulting functions would be nightmares to code and
maintain individually, modify as needed, and so on, but then so would
assembly language. Basically, I went beyond domain-specific language and
wrote a domain-specific optimizing compiler that ultimately punts to
Clojure's.

Of course, eval is evil and this program will not run on hypothetical future
micro-edition deployment environments whose Clojure runtimes lack
eval/compiler support, but it will run on netbook and larger classes of
device at speeds that would make experienced C coders and assembly
hand-tuners turn green. Of course I can't take all the credit. Rich's
Clojure to bytecode compiler sits beneath my compiler, and Sun's Hotspot
Server VM JIT compiler sits beneath that in turn, and with either shoddy or
missing I couldn't get this kind of speed.

But it is proof that any needed speeds can be achieved in Clojure that can
be achieved in Java, or even by hand-hacking directly on the bare metal, or
by anything short of overclocking chips or fabricating new ones.

(Think of the future, too. Clojure macro-like code that compiles directly to
FPGA circuit layouts or programmable spintronic arrays or suchlike. Well,
not directly; it would be the JVM JIT that would be responsible for creating
hardware acceleration or extra cache memory on the fly for code bottlenecks,
and reallocating the finite gate-array real-estate dynamically as the needs
of the app demanded. Still, combining that with the ability to emit new
optimized JVM bytecode on the fly at need and you've got the ultimate in JIT
capabilities.)


  I *was* planning to write up some
 interfaces for more frequent/time-critical communications, but having
 to compile things via ant or the command line is a pain, and Eclipse
 doesn't have particularly good support for mix-and-match of java and
 clojure files in the same project (at least atm.)


NetBeans, which I use, does better at this. You have to restart the REPL
after any change to Java classes, which is a nuisance, but you don't have to
restart the IDE or muck with anything else (project libraries, classpath).
Even if you have separate projects and some are dependencies of others, and
all are undergoing active development, you just have to reboot the REPL
after changing Java code. Changing Clojure code, even in a separate project
that's a dependency of your main project, can typically be handled with a
load-file of the changed file. Only if your refactoring moves a Clojure
function or other object from one namespace to another (same or different
project) do you generally have to restart the REPL, since it won't let you
intern a name in a package that imports the same name from another one, and
uninterned symbols won't go away. It's a good idea to occasionally restart
your REPL anyway to clear out cruft and avoid having a running image that's
become dependent on something that isn't in your code base, and also to find
anywhere where you are missing forward-declarations.

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

Re: Best way to create nonref variable?

2009-07-10 Thread John Harrop
On Thu, Jul 9, 2009 at 10:29 PM, J. McConnell jdo...@gmail.com wrote:

 You can try with-local-vars. I'm not sure of the performance
 characteristics of this versus using an atom, but it certainly feels
 more imperative:


It's slow. I suspect it (and binding) uses Java's ThreadLocal, which is
slow. Loop/recur rebinding is literally thousands of times faster.

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



*math-context*

2009-07-10 Thread John Harrop
It would be useful to have a *math-context* or similar that had a sensible
default and could be set with binding to affect bigdec calculations within
the temporal scope of said binding.

--~--~-~--~~~---~--~~
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: *math-context*

2009-07-10 Thread John Harrop
On Fri, Jul 10, 2009 at 9:22 AM, Rich Hickey richhic...@gmail.com wrote:

 On Jul 10, 9:01 am, Chouser chou...@gmail.com wrote:
  On Fri, Jul 10, 2009 at 7:14 AM, John Harropjharrop...@gmail.com
 wrote:
   It would be useful to have a *math-context* or similar that had a
 sensible
   default and could be set with binding to affect bigdec calculations
 within
   the temporal scope of said binding.
 
  user= (binding [*math-context* (java.math.MathContext. 5)] (+ 2
 1.1M))
  3.M

 See also: with-precision


Eh. Thanks. There's no *math-context* on the api page at the web site. I
just checked again. I'll keep it in mind though.

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



ArithmeticException with doubles

2009-07-10 Thread John Harrop
This is odd:
user= (/ 1.0 0.0)
#CompilerException java.lang.ArithmeticException: Divide by zero
(NO_SOURCE_FILE:0)

Shouldn't it be Double/POSITIVE_INFINITY?

--~--~-~--~~~---~--~~
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 in Clojure?

2009-07-09 Thread John Harrop
On Thu, Jul 9, 2009 at 11:10 AM, tmountain tinymount...@gmail.com wrote:


 I just finished watching the Bay Area Clojure Meetup video, and Rich
 spent a few minutes talking about the possibility of Clojure in
 Clojure. The prospect of having Clojure self-hosted is incredibly
 cool, but it brought a few questions to mind. For one, Rich mentions
 that it would potentially open up additional target platforms for the
 language citing Objective C, Actionscript, and Javascript as potential
 host languages. As awesome as this sounds, wouldn't it first require a
 native implementation to be created for each language prior to Clojure
 in Clojure running on the platform? Perhaps there's some magic
 bootstrapping stuff that can be done to avoid a full port? I'm also
 wondering if Clojure would take a big performance hit as a result of
 being self-hosted? Either way, this seems like a really neat idea.


The difficult thing would be preserving the inability of bad Clojure code to
crash the process, and most especially, providing all of Swing, AWT, JDBC,
JAXP, and all of the rest of the goodies from the Java class library. Being
JVM-hosted has its advantages.

--~--~-~--~~~---~--~~
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: Passing primitives from an inner loop to an outer loop efficiently

2009-07-08 Thread John Harrop
On Wed, Jul 8, 2009 at 3:42 AM, Frantisek Sodomka fsodo...@gmail.comwrote:


 If result is a vector v, then from these 4 cases:
 (let [v [1 2 3]]
  (let [[a b c] v] a b c)
  (let [a (v 0) b (v 1) c (v 2)] a b c)
  (let [a (nth v 0) b (nth v 1) c (nth v 2)] a b c)
  (let [x (first v) r1 (rest v) y (first r1) r2 (rest r1) z (first
 r2)] x y z))

 using 'nth'
 (let [a (nth v 0) b (nth v 1) c (nth v 2)] a b c)
 is the fastest.


Is it faster than using list and manually destructuring the list?

If so, that would mean that (nth v n) is faster than (get v n), which would
be odd since the latter should turn into the former anyway and be inlinable
by the JIT.

--~--~-~--~~~---~--~~
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: Save current namespace like a Smalltalk image

2009-07-08 Thread John Harrop
On Wed, Jul 8, 2009 at 5:14 AM, Robert Campbell rrc...@gmail.com wrote:


 Thanks Daniel, that makes perfect sense, especially about having
 random - and forgotten - code in the image. I have a lot of this
 during my exploration sessions.


Perhaps instead of saving an image, it should be able to save a transcript
of the REPL inputs? Then you could rescue code from this, or find any cruft
your image had become dependent on, or whatever.

--~--~-~--~~~---~--~~
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: Homoiconicity and printing functions

2009-07-08 Thread John Harrop
On Wed, Jul 8, 2009 at 9:11 AM, Mike cki...@gmail.com wrote:

 One of the things that drew me to Clojure was the fact that it's
 homoiconic (and my previous lisp [Scheme] was not necessarily), which
 means code is data, macro writing is easy etc. etc.

 What I'm missing is why I can't print a function.  I understand that
 most of the functions I write use quite a few macros, and after
 expansion into the core forms it looks shredded...but isn't there any
 way for me to see a representation of this source after a function
 has been compiled?


If you want to see macro expansions, macroexpand and macroexpand-1 will do
ya.

If you want to be able to query a function for its source code later on,
that's tougher. You'll need to make a macro that wraps defn and assigns a
copy of the body form to a metadata tag on the function's name.

--~--~-~--~~~---~--~~
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: Passing primitives from an inner loop to an outer loop efficiently

2009-07-08 Thread John Harrop
Interesting. How are these timings affected if you add in the time taken to
pack the list or vector in the first place, though? I have the feeling it
may be slightly cheaper to unpack a vector, but noticeably cheaper to pack a
list...

--~--~-~--~~~---~--~~
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: Help with example from A Field Guide to Genetic Programming

2009-07-08 Thread John Harrop
On Wed, Jul 8, 2009 at 1:57 PM, Robert Campbell rrc...@gmail.com wrote:

 If it's okay, could somebody explain the difference between what's
 happening here:

 user (def my-func (list + 1 2))
 #'user/my-func
 user (my-func)
 ; Evaluation aborted.

 and here:

 user (def my-func (list + 1 2))
 #'user/my-func
 user (eval my-func)
 3

 I don't really understand how:
 user(my-func) is NOT eval on my-func in the REPL. My understanding is
 the first item in the list is treated as a function, with the rest of
 the list passed as arguments. Wouldn't the REPL just be calling eval
 internally on everything you type in?


Not every expression is a function, even if most are function calls.

Any expression can be evaluated with eval. To call something as a function,
though, it has to be something invokable. A list, even a list of a function
and two values, isn't. An actual function is, as produced by defn or fn or
#(). So are sets, maps, and vectors, which will look up the argument key or
index:

user= (#{'x 'y} 'x)
x
user= (#{'x 'y} 'z)
nil
user= ({:key 'val} :key)
val
user= ({:key 'val} 3)
nil
user= (['a 'b 'c] 0)
a
user= (['a 'b 'c] 2)
c
user= (['a 'b 'c] 3)
#CompilerException java.lang.ArrayIndexOutOfBoundsException: 3
(NO_SOURCE_FILE:0)

And keywords can be invoked to do set and map lookups:

user= (:key {:key 'val})
val
user= (:x {:key 'val})
nil
user= (:key #{:key})
:key
user= (:x #{:key})
nil

Last but not least, there's ., .., .methName, Class., Class/staticMeth,
Class/staticField, and other variations on this theme to interact with Java
classes. And maybe one or two things I'm forgetting. :)

--~--~-~--~~~---~--~~
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: Passing primitives from an inner loop to an outer loop efficiently

2009-07-08 Thread John Harrop
On Wed, Jul 8, 2009 at 4:57 PM, Frantisek Sodomka fsodo...@gmail.comwrote:


 So far it seems that vectors win in Clojure:

 (timings 3e5
  (let [v (vector 1 2 3) a (nth v 0) b (nth v 1) c (nth v 2)] (+ a b
 c))
  (let [lst (list 1 2 3) a (nth lst 0) b (nth lst 1) c (nth lst 2)] (+
 a b c)))

 =
  680.63 ms   83.6%   1.2x  (let [v (vector 1 2 3) a (nth v 0) b (nth
 v 1) c (nth v 2)] (+ a b c))
  813.79 ms  100.0%   1.0x  (let [lst (list 1 2 3) a (nth lst 0) b
 (nth lst 1) c (nth lst 2)] (+ a b c))


Does using vec instead of vector make a difference? Using first, rest,
first, rest instead of nth to destructure the list?

--~--~-~--~~~---~--~~
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: Mysterious ClassFormatError after simple code change.

2009-07-07 Thread John Harrop
On Mon, Jul 6, 2009 at 7:50 PM, Richard Newman holyg...@gmail.com wrote:


  Since it's not apparently a simple bug in my function above, but
  something about a combination of that version of that function and
  some other part of my code, I can't think of a way to track the
  cause down short of the very tedious method of commenting out
  functions or replacing them with dummy functions (if they're called
  by the above function) and seeing which one has the property that
  commenting it out or dummy-izing it makes the error go away.
 
  That will probably take all afternoon, unfortunately; there are
  dozens of functions and over 1600 lines of code in that source file.

 Have you tried simpler things like splitting the offending function
 into a separate namespace, or seeing what happens with (or without)
 AOT compilation?


I didn't get around to that because I accidentally fixed the bug somehow. I
moved a few functions that I realized were general purpose over to a
separate utils project and recompiled everything. The source file with the
problem contained some of the functions I moved, and now loads correctly. It
looks like one of those functions conflicted in some way with the newer
version of the function posted to this thread, though I'm baffled as to how
or why. None were directly called by it, or otherwise directly referenced by
it, nor vice versa.

--~--~-~--~~~---~--~~
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: Mysterious ClassFormatError after simple code change.

2009-07-07 Thread John Harrop
On Mon, Jul 6, 2009 at 11:25 PM, John Harrop jharrop...@gmail.com wrote:

 On Mon, Jul 6, 2009 at 7:50 PM, Richard Newman holyg...@gmail.com wrote:

 Have you tried simpler things like splitting the offending function
 into a separate namespace, or seeing what happens with (or without)
 AOT compilation?


 I didn't get around to that because I accidentally fixed the bug somehow. I
 moved a few functions that I realized were general purpose over to a
 separate utils project and recompiled everything. The source file with the
 problem contained some of the functions I moved, and now loads correctly. It
 looks like one of those functions conflicted in some way with the newer
 version of the function posted to this thread, though I'm baffled as to how
 or why. None were directly called by it, or otherwise directly referenced by
 it, nor vice versa.


And now it's mysteriously back after I implemented a few more functions. I
can't find any obvious errors in any of the new code.

Weirdly, if I copy the entire source file, paste it at the REPL, and hit
enter, the error does not occur!

Somehow, code that is treated as valid when compiled a function at a time is
treated as invalid when compiled all at once. That pretty much proves it's
an implementation bug, since the same code can't both be buggy and be fine
at the same time. :(

--~--~-~--~~~---~--~~
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: Mysterious ClassFormatError after simple code change.

2009-07-07 Thread John Harrop
On Tue, Jul 7, 2009 at 9:30 AM, Stephen C. Gilardi squee...@mac.com wrote:


 On Jul 7, 2009, at 5:51 AM, John Harrop wrote:

  Somehow, code that is treated as valid when compiled a function at a time
 is treated as invalid when compiled all at once. That pretty much proves
 it's an implementation bug, since the same code can't both be buggy and be
 fine at the same time. :(


 It sounds a lot like you're running into limits on the size or count of
 something in a class file:


Shouldn't be. I'm not using :gen-class or similar, so the only classes
generated should be ones for the individual functions, and the largest one
of those works, so is not exceeding any kind of limit.

Furthermore, the clojure documentation does not state any limits on function
size or similar, so implies that there are none.

Last but not least, a change to a single function definition's interior
triggered the error. If the error was:
* too large a function, a much larger function elsewhere in the file would
fail;
* too many names or other things in the namespace, changing a single thing's
  interior without adding more top-level things would not fail;
* just about anything else, either something else would have failed earlier
or
  things would have stayed working, one or the other.

That compiling the functions one by one in the REPL, in the same namespace,
exceeds no limits is also worthy of note. It can't be a namespace size limit
then, nor can any of the individual functions be exceeding a limit. In fact,
the only thing different is that a load script of sorts has to be compiled
for a load-file or build, which evaluates the definitions and other
instructions in order. If that's hitting some sort of limit, the ability to
execute exactly the same things in the same sequence at the REPL proves that
that limit can be circumvented under the hood, simply by having load-file
more faithfully emulate pasting everything into a REPL set to the
appropriate namespace and hitting enter than it apparently currently does.
Is it making the load script into a single huge static method perhaps? If
so, having it break such things up under the hood into several smaller ones
with a driver that calls them all in sequence would fix it, or even having
it break up the -init class into -init, -init2, -init3 and so forth if
necessary and making these invoke one another in chains.

There's really no reason I can think of for anything like this to even be
affecting the user.

If that's true, I think Clojure should be detecting the problem and
 reporting it in a way that's helpful rather than generating a bad class
 file.


That much I'd agree with.


 Are you able and willing to make the entire Clojure source file that's
 failing for you available so it's feasible to track down the problem?


It's probably going to end up GPL'd eventually -- if I can get it to
actually work and stay working -- but it's not presently in a releasable
state.

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



Passing primitives from an inner loop to an outer loop efficiently

2009-07-07 Thread John Harrop
Problem: Passing primitives from an inner loop to an outer loop efficiently.
Here is what I've found.

The fastest method of result batching, amazingly, is to pass out a list and:

(let [foo (loop ... )
x (double (first foo))
r1 (rest foo)
y (double (first r1))
r2 (rest r1)
z (double (first r2))] ... )

(here passing out three doubles).

About half as fast is:

(let [[x y z] (loop ... )] ... ) with (double x), (double y), and (double z)
used later in place of x y z and only one occurrence of each (so no more
(double foo) conversions than before). The destructuring bind apparently
exerts a higher run-time overhead compared to manual destructuring.

(with-locals [x (double 0) y (double 0) z (double 0)]
(loop ... )
(do-something-with (double (var-get x)) (double (var-get y)) (double
(var-get z

is two full orders of magnitude slower (here the loop doesn't return a list
but uses var-set).

Using atoms is even worse.

(let [#^doubles xyz (double-array (int 3))]
(loop ... )
(do-something-with (aget xyz (int 0)) (aget xyz (int 1)) (aget xyz (int
2

with the loop using aset-double to pass out values is, surprisingly, no
faster. Using plain aset makes no difference, as does removing the (int ...)
wrappings around the numbers.

Intermediate in speed is using a clojure vector to pass out values, e.g.
[result-x result-y result-z] is the expression that returns a value from the
loop, and

(do-something-with (get results (int 0)) (get results (int 1)) (get
results (int 2)))

It's surprising that this is faster than using a primitive Java array with
type-hints, and interesting that retrieving sequential items from a list is
faster than a like number of in-order indexed retrievals from a vector,
which could theoretically be optimized to a pointer-walk with each retrieval
involving an increment and a dereference and a store, rather than an
increment, three dereferences, and a store. (Dereference linked list entry
item pointer, store, increment pointer, dereference to get next-entry
pointer, dereference again, repeat.)

Whatever, these results may be useful to someone, along with:

(defn- extract-result-list-into [conv hint gensyms result-generator] (let
[rs (take (count gensyms) (repeatedly gensym))] (into [(first rs)
result-generator] (loop [r rs g (if hint (map #(with-meta % {:tag hint})
gensyms) gensyms) output []] (if (empty? r) output (let [fr (first r) rr
(rest r) frr (first rr)] (recur (rest r) (rest g) (into output (concat
[(first g) (if conv `(~conv (first ~fr)) `(first ~fr))] (if frr [frr `(rest
~fr)]))

This helper function can be used in a macro to suck the contents of a list
into variables with conversions, type hints, or both; conv would be a symbol
like `double, hint something like BigInteger, gensyms some gensyms (or other
symbols) for the variable names (in order), and result-generator some code
(e.g. resulting from a backtick expression). The output is a vector
resembling
[G__5877 (loop ... whatever code)
#^hint G__5874 (conv (first G__5877))
G_5878 (rest G__5877)
#^hint G__5875 (conv (first G__5878))
G_5879 (rest G__5878)
#^hint G__5876 (conv (first G__5879))]
which can be used in a let, loop, or other construct that uses bindings with
the usual clojure syntax, and can even have other things added to it by
macro code.

The downside is relative inflexibility. If you pass in a gensyms seq with an
embedded vector of two gensyms you'll get a valid destructuring bind for a
composite item in the results, but it won't work with type hints or
conversions, nor can those be mixed. Making it more sophisticated would be
possible, though.

This arose when I had a performance-critical double-barreled loop to
optimize, and found that the outer loop was spending several thousand
iterations of the inner loop worth of time just to extract the results via
with-locals. I did some experimenting and benchmarking of various ways to
get the output of the inner loop to code in the outer loop, using
System/nanoTime, millions of repetitions, and averaging to determine the
winner.

An efficient labeled recur would be nice for clojure 2.0. :) (Limited
though it would be to when the inner loop was in tail position in the outer
loop.)

--~--~-~--~~~---~--~~
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: Mysterious ClassFormatError after simple code change.

2009-07-06 Thread John Harrop
On Mon, Jul 6, 2009 at 8:53 AM, Chouser chou...@gmail.com wrote:


 On Sun, Jul 5, 2009 at 3:51 PM, John Harropjharrop...@gmail.com wrote:
 
  This is frankly quite baffling. The changes to the function are
  innocent from a large-literal or pretty much any other perspective.

 Both your functions load fine for me without the rest of
 your code.  Are there type hints on the return values of any
 of the functions called in your examples?


Not that I know of. Called macros above are let-print; called functions are
cons, map, factor-term, rest, make-product*, concat, and
subexpressions-of-product. All are called by both versions; cons, map, rest,
and concat are the clojure.core versions and let-print is just

(defmacro let-print [bindings  body]
  `(let ~bindings ~@(map (fn [x#] `(println ~x#))
  (take-nth 2 bindings)) ~...@body))

which I find handy sometimes when debugging, because I can just slap a
-print at the end of a let to add some debugging dumps to the console
output. (I also have eval-print and intend to add loop-print to dump loop
variables every time around the loop.)

I had been debugging the above function, which work led to the change that
triggered the new problem. Interestingly, changing the let-print back to
let alters the error message, specifically, the cryptic number after
unknown constant tag, but has no other effect.

The functions factor-term, make-product*, and subexpressions-of-product have
all been working for ages, and have not changed recently. None type-hints
anything, return value or otherwise.

--~--~-~--~~~---~--~~
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: Is this unquote dangerous?

2009-07-06 Thread John Harrop

 Or if you really do need a list:

  (for [x [1 2 3]] (cons 'some-symbol (list x)))


Why not

(for [x [1 2 3]] (list 'some-symbol x))

?

--~--~-~--~~~---~--~~
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: Mysterious ClassFormatError after simple code change.

2009-07-06 Thread John Harrop
On Mon, Jul 6, 2009 at 3:58 PM, Emeka emekami...@gmail.com wrote:

  (defn- subexpressions-of-sum** [[n p] terms]
  (let-print [sum (cons '+ (map #(factor-term % n p) terms))
prod (rest (make-product* n p))]
(cons sum
  (map #(cons '* (cons sum (rest %)))
(concat prod (subexpressions-of-product prod))

 I look at the above, and something stupid just entered into my thought.
 What happened when this situation occurs (cons sum ())? I hope that's not
 possible with your code.


It shouldn't be. Even if it is, there'd just be some (* sum) in the results,
which is inefficient but not illegitimate.

I don't see any way that this could be the cause of the ClassFormatError, in
particular.

Frankly, I am starting to suspect a bug in clojure. I'm using the stable
1.0, not the bleeding edge stuff. Whether the occurrence of the
ClassFormatError itself is down to a subtle error in my code (so subtle
no-one can spot it) or an error in clojure, its failure to point to a line
in my source file as the erroneous one is in and of itself a bug, I'd argue.

Since it's not apparently a simple bug in my function above, but something
about a combination of that version of that function and some other part of
my code, I can't think of a way to track the cause down short of the very
tedious method of commenting out functions or replacing them with dummy
functions (if they're called by the above function) and seeing which one has
the property that commenting it out or dummy-izing it makes the error go
away.

That will probably take all afternoon, unfortunately; there are dozens of
functions and over 1600 lines of code in that source file.

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



Mysterious ClassFormatError after simple code change.

2009-07-05 Thread John Harrop

I had this:

(defn- subexpressions-of-sum** [[n p] terms]
  (let-print [sum (cons '+ (map #(factor-term % n p) terms))
prod (rest (make-product* n p))]
(concat [sum] (subexpressions-of-product (cons sum prod)

in a source file with other definitions. Load-file worked. I then
changed it to this:

(defn- subexpressions-of-sum** [[n p] terms]
  (let-print [sum (cons '+ (map #(factor-term % n p) terms))
prod (rest (make-product* n p))]
(cons sum
  (map #(cons '* (cons sum (rest %)))
(concat prod (subexpressions-of-product prod))

and got:

#CompilerException java.lang.ClassFormatError: Unknown constant tag
32 in class file com/mycompany/myfile$eval__14598 (NO_SOURCE_FILE:0)

when I tried to do a load-file.

That function definition was the ONLY thing I changed, but I'm at a
loss to find any kind of error in it. Delimiters balance, all of the
referenced functions exist, basically there's nothing wrong.

The full exception trace, which required evaluating (.printStackTrace
(.getCause *e)) at the repl, is:

java.lang.ClassFormatError: Unknown constant tag 32 in class file
com/mycompany/myfile$eval__14598
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
at java.lang.ClassLoader.defineClass(ClassLoader.java:466)
at 
clojure.lang.DynamicClassLoader.defineClass(DynamicClassLoader.java:42)
at clojure.lang.Compiler$FnExpr.getCompiledClass(Compiler.java:3417)
at clojure.lang.Compiler$FnExpr.eval(Compiler.java:3428)
at clojure.lang.Compiler.eval(Compiler.java:4531)
at clojure.core$eval__3990.invoke(core.clj:1728)
at clojure.main$repl__5813$read_eval_print__5825.invoke(main.clj:176)
at clojure.main$repl__5813.doInvoke(main.clj:193)
at clojure.lang.RestFn.invoke(RestFn.java:548)
at 
org.enclojure.repl.main$create_clojure_repl__53$repl_thread_fn__55.invoke(main.clj:96)
at clojure.lang.AFn.run(AFn.java:37)
at java.lang.Thread.run(Thread.java:619)

It does not point to any line of my source file.

Perhaps the rewritten version of the function provokes a compiler bug?
If there is a known bug that would cause this, let me know of the
known workaround. If there is an error in the second version of my
function, let me know. (It has intentionally different semantics from
the first version, so that's not an error in and of itself.)

--~--~-~--~~~---~--~~
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: Mysterious ClassFormatError after simple code change.

2009-07-05 Thread John Harrop

I'm not doing any funny things with load-string. The largest literal
at this time is

[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79
 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163
 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251
 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349
 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443
 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557
 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647
 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757
 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863
 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983
 991 997]

and has been in there a while without causing problems. The function
definition in my original post is the ONLY change between working and
not-working. With the first version, the file loads consistently. With
the second version, it fails consistently. The error is definitely in
that function and not elsewhere, or else it is in the implementation
of load-file, the compiler, or even Java or the JVM.

The JVM is 1.6.0_something, I forget what. It's pretty current.

The literal generated in the post you linked to took a list of four
items and doubled it up 13 times, for a grand total of 2^15 = 32768
items. There's nothing that large in that function, nor anything in
the second version of it that would expand (say, via a macro) into
something that large from a number being changed.

This is frankly quite baffling. The changes to the function are
innocent from a large-literal or pretty much any other perspective.

On 7/5/09, Stephen C. Gilardi squee...@mac.com wrote:
 On Jul 5, 2009, at 2:01 AM, John Harrop wrote:

 and got:

 #CompilerException java.lang.ClassFormatError: Unknown constant tag
 32 in class file com/mycompany/myfile$eval__14598 (NO_SOURCE_FILE:0)

 Are there large literals elsewhere in the same namespace?

 Here's some info from a previous report of this error:

 http://groups.google.com/group/clojure/browse_frm/thread/e556434a382de814/f8183c88db8fa257?lnk=gstq=oct+18+2008#f8183c88db8fa257

 --Steve



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



<    1   2   3   4