How to use realized? on a lazy sequence?

2011-10-07 Thread George Kangas
   Here's a REPL session, wherein I try to use realized? on a
   lazy-seq.

Clojure 1.3.0

Define the lazy-seq:

user= (def naturals (iterate inc 0))
#'user/naturals

Force realization of the first 1 + 123456 elements:

user= (time (nth naturals 123456))
Elapsed time: 481.349 msecs
123456

Due to previous realization, the same expression now eval's
quickly:

user= (time (nth naturals 123456))
Elapsed time: 15.571 msecs
123456

   Now I try to use realized? on 123456th element:

user= (realized? (nth naturals 123456))
ClassCastException java.lang.Long cannot be cast to
clojure.lang.IPending  clojure.core/realized? (core.clj:6505)

Ouch! I guess realized? isn't a macro.  Next try:

user= (realized? (drop 123456 naturals))
false

   Hmmm... could I be off by one? Let's leave lots of room for error:

user= (realized? (drop 12345 naturals))
false
user= (realized? (drop 0 naturals))
false

Huh? How do I get realized? to tell me what I want to know?

What I want to know, is wether the element at the nth index
has been computed and cached.  Maybe something like realized-
length, just for lazy-seq's, which would report how far along
the sequence has realization occurred.

Thanks,
George Kangas

-- 
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 use realized? on a lazy sequence?

2011-10-07 Thread George Kangas


On Oct 7, 5:02 pm, Alan Malloy a...@malloys.org wrote:
 Can't you write that function yourself?

 (defn realized-length [xs]
   (loop [n 0 xs xs]
     (if (realized? xs)
       (recur (inc n) (rest xs))
       n)))

Thanks, Alan!


 drop returns a new lazy sequence, with no realized elements,

I didn't realize that!  I expected that drop would call rest
recursively, like your realized-length does.  But apparently, it's
lazier than that:

user= (def c (drop 12345678 naturals))
#'user/c
user= (time (first c))
Exception in thread main java.lang.OutOfMemoryError: Java heap space
(more java.lang.barfing)


 user= (def naturals (rest (iterate inc 0)))
 #'user/naturals

You introduce another subtlety here: realized? won't work on the
result of iterate (as Tassilo Horn found), but it will work on
(rest (iterate ...)).  And this is because:

 Note that this does not work for the base case of an iterated
 sequence, because that is not a lazy-seq but a cons. Seems a bit weird
 to me, but then realized? itself is a bit weird...

realized? doesn't seem so weird, when it deals with  promises,
delays and futures. Those objects have explicit API's for their
creation and realization, and realized? has a natural and
predictable role in that API.

Lazy sequences are more magic, and less explicit about creation and
realization (or so it seems to me).  Implementors of functions such as
iterate, drop, rest, range, etc., have some freedom to decide
times of creation/realization.  Then, when you try to use realized?
on lazy sequences, those decisions (which you may not have expected)
come to the surface.

Maybe realized? doesn't really belong in the lazy sequence API, but
it is fun to play around with it.  Thanks for showing me how!

regards,

George



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


What happened to bignum support? (clojure 1.3.0)

2011-09-25 Thread George Kangas
Greetings, Clojure community.  I've been playing around with
clojure,
and just downloaded 1.3.0. Here's a REPL session, wherein I define
a power-of-two function, and apply it a couple of times.

lecturer-01:clojure-1.3.0 kangas$ java -cp clojure-1.3.0.jar
clojure.main
Clojure 1.3.0
user= (defn pow2 [n]
  (loop [n n, p 1]
 (if (zero? n)
p
(recur (dec n) (+ p p)) )))
#'user/pow2
user= (pow2 62)
4611686018427387904
user= (pow2 63)
ArithmeticException integer overflow
clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374)
user=

Previous versions would silently, automagically convert to bignums
and
give me the answer I wanted.  Is clojure-1.3.0 too serious,
enterprisy, and
Java-like for this sort of thing?  I found no clue in the list of
changes.

thanks,

George

-- 
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: aquamacs, slime and clojure on OS X

2011-09-25 Thread George Kangas
I'm quite happy using emacs's Scheme support.  But then, I've never
experienced the luxury of swank and slime.

The Scheme modes work a bit better (for Clojure) than the Lisp modes,
because: 1) it highlights matching square and curly brackets, not just
parentheses; and 2) after you do C-u M-x run-scheme / java -cp...
to start inferior Scheme mode, you can restart it with just M-x run-
scheme (within the same emacs session).

So, until you man up, and build the great edifice of leiningen + ant +
maven + ..., something I'll probably never get around to, you can make
do with Scheme mode.  Good enough for the '90s!

Some people are happy with mini-IDE called clooj that's under
developement.  You can find that on github.

ciao,

George

-- 
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: What happened to bignum support? (clojure 1.3.0)

2011-09-25 Thread George Kangas
Thanks, Baishampayan and Sam!

Since so little effort is required to get the BigInt behavior, you'll
all be relieved to hear that I Approve of This Change.  Should I ever
need high performance from Clojure, I'll actually be happy about it.
Notwithstanding the snarking tone of my original post.

George

-- 
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: puzzlement over lazy sequences

2011-09-11 Thread George Kangas
Hi, Stu,

  Loving your book!

  I posted a reply earlier, through a different interface, which went
to moderators.  Sorry for the clumsiness, but I'm not familiar with
the mechanics of newsgroups.

On Sep 11, 7:28 am, Stuart Halloway stuart.hallo...@gmail.com wrote:

 The consing version of ev-stream is self-referential, because you explicitly 
 made it so by consing it back onto itself. So it only has two items in it, 
 though it bounces back and forth between them forever. The cycling version is 
 not self-referential.

Since it's the self reference that gives the nice results (finite
memory consumption, and apparently better speed), I came up with a
little macro to provide it:

(defmacro defcycle [name coll]
`(def ~name (lazy-seq (concat ~coll ~name))) )

This is probably not the most useful way to do it, since the user has
to provide name.

  Now I'll test it with 9876543210, a number which ev? was able to
  handle:

     user= (time (mod3 9876543210))
     Elapsed time: 37759.615 msecs
     1
     user= (mod 987654321 3)
     0

  Whoa! The computation finished in reasonable time, but with the WRONG
  answer! How did that happen?
  Did I find a bug?

 No, there is simply a typo in your input arg.

with the typo fixed, i.e. (mod 9876543210 3), the result is still 0.

regards,

George

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


puzzlement over lazy sequences

2011-09-10 Thread George Kangas
Greetings, Clojurers!

I've been playing with clojure, particularly with lazy sequences.
Some of the
results have left me puzzled, so I saved a REPL session wherein I
illustrate the points
of puzzlement.  REPL lines are indented below; added comments are
unindented.


Clojure 1.2.1

I define a silly version of even? which uses a lazy sequence:

user= (defn ev? [n] (nth (cycle [true false]) n))
#'user/ev?

It works, albeit slowly, for large arguments:

user= (time (ev? 9876543210))
Elapsed time: 337225.287 msecs
true

This won't work, if any reference is retained to that long sequence:

user= (def ev-stream (cycle [true false]))
#'user/ev-stream
user= (defn ev? [n] (nth ev-stream n))
#'user/ev?
user= (time (ev? 9876543210))
Exception in thread main java.lang.OutOfMemoryError: Java heap
space
at java.lang.reflect.Method.copy(Method.java:143)
at java.lang.reflect.ReflectAccess.copyMethod(ReflectAccess.java:118)
at sun.reflect.ReflectionFactory.copyMethod(ReflectionFactory.java:
282)
at java.lang.Class.copyMethods(Class.java:2748)
at java.lang.Class.getMethods(Class.java:1410)
at clojure.lang.Reflector.getMethods(Reflector.java:310)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:27)
at clojure.main$repl_caught.invoke(main.clj:116)
at clojure.main$repl$fn__5637.invoke(main.clj:206)
at clojure.main$repl.doInvoke(main.clj:204)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.main$repl_opt.invoke(main.clj:262)
at clojure.main$main.doInvoke(main.clj:355)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:361)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)

Process scheme exited abnormally with code 1

Okay, that was the expected java.lang.barf.  No puzzlement so far.
Now I restart the REPL.

Clojure 1.2.1

Once again, I make a globally referenced, infinitely long stream.  But
now I use lazy-seq
instead of cycle:

user= (def ev-stream (lazy-seq (cons true (cons false ev-
stream
#'user/ev-stream
user= (defn ev? [n] (nth ev-stream n))
#'user/ev?
user= (time (ev? 9876543210))
Elapsed time: 47244.061 msecs
true

OMG! Not only did it NOT hose the heap and crash, it actually ran much
faster than the version
with the unreferenced (cycle [true false]).

The only reason I can think of, for this to NOT exhaust memory, is
that the lazy-seq macro knows
when to construct a circular list. Is that what happens?  If so, why
DOESN'T it happen with cycle,
where it's obviously the behavior one would want?

Okay, now I'll play the same game again, but with mod 3:

user= (def mod3-stream (lazy-seq (cons 0 (cons 1 (cons 2 mod3-
stream)
#'user/mod3-stream
user= (defn mod3 [n] (nth mod3-stream n))
#'user/mod3

It passes a simple test:

user= (map mod3 (range 20))
(0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1)

It passes a test with a pretty big number:

user= (time (mod3 987654321))
Elapsed time: 28998.966 msecs
0
user= (mod 987654321 3)
0

Now I'll test it with 9876543210, a number which ev? was able to
handle:

user= (time (mod3 9876543210))
Elapsed time: 37759.615 msecs
1
user= (mod 987654321 3)
0

Whoa! The computation finished in reasonable time, but with the WRONG
answer! How did that happen?
Did I find a bug?

Thanks for reading this far, and best regards,

George Kangas

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