Re: Blow up

2009-03-28 Thread William D. Lipe

Your analysis is correct.  Note that adding a doall fixes the problem

user= (def tl (reduce #(doall (concat %1 [%2])) [] (range 4000)))
#'user/tl
user= (last tl)
3999

efficiency notwithstanding.

On Mar 28, 8:59 am, jim jim.d...@gmail.com wrote:
 Hey Rich,

 I found an interesting way to blow up the stack.

 user= (def tl (reduce #(concat %1 [%2]) [] (range 3500)))
 #'user/tl
 user= (last tl)
 java.lang.StackOverflowError (NO_SOURCE_FILE:0)

 The 3500 is probably specific to my environment.  I'm assuming that
 all the concats get deferred until needed and that the nested calls
 blow up the stack.

 Also, this works

 user= (def tl (reduce #(conj %1 %2) [] (range 4000)))
 #'user/tl
 user= (last tl)
 3999

 Jim
--~--~-~--~~~---~--~~
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
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: oo

2009-03-28 Thread David Nolen
On Sat, Mar 28, 2009 at 4:40 PM, mikel mev...@mac.com wrote:


 So, at minimum, to make a solid port, you need to add a function that
 can return a sensible type value for any input


Enjoying the thread. Out of curiosity for which Clojure values is the return
value of the type function undefined?

David

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



Possible Solution for Left-Right Precedence and More when using Multimethods? (was re: oo)

2009-03-28 Thread David Nolen
Having thought a little about multiple inheritance when implementing Spinoza
I also ran into this problem. However at the time I wasn't hindered by
multifn dispatch as much as the fact that parents cannot be ordered (because
calling parents on a tag returns a set) as pointed out by Mark. I understand
Rich's point that hierarchies probably shouldn't be directional, but for the
sake of practicality why not allow the programmer to specify that a tag (or
even the whole hierarchy) should in fact have its relationships be ordered?
In general prefer-method seemed to me (I could be wrong) to be a last
attempt solution- when there is just no other way to resolve an ambiguity,
and this ambiguity is not of the hierarchy, but of multimethod dispatch. As
pointed out by Konrad  Rich, you can work around the limitation of
hierarchies right now with a lot of prefer-methods.  But as Mikel points
out, with current state of prefer-method you have to hunt through code to
find out where these prefers were made and for what reason and they assume
that you've already written your methods (this for me is the deal breaker).

In anycase my general feeling (in agreement with Mark) is that the problem
isn't with multifns but rather with how hierarchies are constructed.

So the achilles heel of hierarchies seems to be that when you call parents
(and related fns) on a tag you get a set - it has no order.  For single
inheritance hierarchies this is fine, but for multiple inheritance I think
this becomes a problem a very fast. Working on Spinoza, I realized I would
have to keep my own ordered list of parents in order to support left-right
precedence, basically keeping an ordered copy of the whole hierarchy. Again
prefer-method is only useful for fixing method-level ambiguities.  There's
no general way to say, type A always precedes type B without writing quite a
bit of explicit code (or hiding the problem away with macros).

Here's something that might kick of a dicussion to a proper solution (I am
sure there are some gaps in my logic), why not allow something like the
following?

;; allow control of how tags get introduced into the hierarchy
(def h (make-hierarchy :parents-fn fn1 :ancestors-fn fn2 :descendants-fn
fn3))

;; add a new parent insertion fn to a hierarchy
(add-parents-fn h fn4) ;; - returns a new hierarchy with the parents fn
set, all parents sets are converted into vectors

;; add a new parent insertion fn to a hierarchy for a specific key, only the
parents of ::my-tag are converted into a vector
(add-parents-fn h fn4 ::my-tag)

;; a hierarchy fn might look something like the following
(defn my-parents-fn [parents new-key]
   (conj parents new-key))

If my thinking is correct this is pretty flexible. This doesn't break the
meaning of hierarchy for any existing code.  It doesn't change the signature
of multimethods.  Yet now a user can provide fns that sorts a hierarchy
anyway they please, and it doesn't even have to be the entire hierarchy.
 This code will probably live in one spot where anyone could look to
understand how the hierarchy is being constructed.  All high-level
precedence ambiguities can now be resolved by looking at the hierarchy.
 prefer-method does only what it was intended to do- resolve method level
ambiguity.

David

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



Request for improved error reporting

2009-03-28 Thread Glen Stampoultzis
Hi, I've been really enjoying getting to know clojure.  It's an awesome
language that has got me very interested in learning more. One thing that
hasn't left me impressed is the error reporting.

I recently got this one that left me scratching my head:

java.lang.NullPointerException (splat.clj:0)
at clojure.lang.Compiler.eval(Compiler.java:4533)
at clojure.lang.Compiler.load(Compiler.java:4846)
at clojure.lang.Compiler.loadFile(Compiler.java:4813)
at clojure.main$load_script__5793.invoke(main.clj:206)
at clojure.main$script_opt__5824.invoke(main.clj:258)
at clojure.main$main__5848$fn__5850.invoke(main.clj:333)
at clojure.main$main__5848.doInvoke(main.clj:328)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at clojure.lang.Var.invoke(Var.java:346)
at clojure.lang.AFn.applyToHelper(AFn.java:173)
at clojure.lang.Var.applyTo(Var.java:463)
at clojure.main.main(main.java:39)
Caused by: java.lang.NullPointerException
at user$render_layer__37.invoke(splat.clj:311)
at user$render_layers__40.invoke(splat.clj:315)
at user$active_update__43.invoke(splat.clj:323)
at user$run__55.invoke(splat.clj:349)
at user$eval__58.invoke(splat.clj:378)
at clojure.lang.Compiler.eval(Compiler.java:4522)
... 11 more

There are a few things wrong here and with clojure error reporting in
general:

1. I'm not getting a line number for some reason.
2. I don't get any indication what the nature of the error is.
3. I get a big (nested) stack trace that has more to do with clojure
compiler internals than my program.

Even when clojure does tell you what went wrong I don't really need to see
the compiler internals.  Just the parts relevant to my program.  Perhaps
some context (such as printing the source line causing the problem) and a
clear message stating the nature of the problem.

Regards,

Glen

--~--~-~--~~~---~--~~
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
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: Request for improved error reporting

2009-03-28 Thread Glen Stampoultzis
Sorry I just realized I was a bit ambiguous with this.  The exception does
show the line number (in the second stack trace).  But it's gone missing in
the top one.

2009/3/29 Glen Stampoultzis gst...@gmail.com

 Hi, I've been really enjoying getting to know clojure.  It's an awesome
 language that has got me very interested in learning more. One thing that
 hasn't left me impressed is the error reporting.

 I recently got this one that left me scratching my head:

 java.lang.NullPointerException (splat.clj:0)
 at clojure.lang.Compiler.eval(Compiler.java:4533)
 at clojure.lang.Compiler.load(Compiler.java:4846)
 at clojure.lang.Compiler.loadFile(Compiler.java:4813)
 at clojure.main$load_script__5793.invoke(main.clj:206)
 at clojure.main$script_opt__5824.invoke(main.clj:258)
 at clojure.main$main__5848$fn__5850.invoke(main.clj:333)
 at clojure.main$main__5848.doInvoke(main.clj:328)
 at clojure.lang.RestFn.invoke(RestFn.java:413)
 at clojure.lang.Var.invoke(Var.java:346)
 at clojure.lang.AFn.applyToHelper(AFn.java:173)
 at clojure.lang.Var.applyTo(Var.java:463)
 at clojure.main.main(main.java:39)
 Caused by: java.lang.NullPointerException
 at user$render_layer__37.invoke(splat.clj:311)
 at user$render_layers__40.invoke(splat.clj:315)
 at user$active_update__43.invoke(splat.clj:323)
 at user$run__55.invoke(splat.clj:349)
 at user$eval__58.invoke(splat.clj:378)
 at clojure.lang.Compiler.eval(Compiler.java:4522)
 ... 11 more

 There are a few things wrong here and with clojure error reporting in
 general:

 1. I'm not getting a line number for some reason.
 2. I don't get any indication what the nature of the error is.
 3. I get a big (nested) stack trace that has more to do with clojure
 compiler internals than my program.

 Even when clojure does tell you what went wrong I don't really need to see
 the compiler internals.  Just the parts relevant to my program.  Perhaps
 some context (such as printing the source line causing the problem) and a
 clear message stating the nature of the problem.

 Regards,

 Glen


--~--~-~--~~~---~--~~
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
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: Request for improved error reporting

2009-03-28 Thread Glen Stampoultzis
It wasn't really this specific problem that I wanted to point out but more
to trigger a rethink of how errors are reported back to the user.
Here's an example that gives an error somewhat similar to the one I posted:

(defn testing [a b] (print a b))
(testing)

java.lang.NoSuchMethodError:
java.lang.Class.getSimpleName()Ljava/lang/String; (testing.clj:0)
at clojure.lang.Compiler.eval(Compiler.java:4533)
at clojure.lang.Compiler.load(Compiler.java:4846)
at clojure.lang.Compiler.loadFile(Compiler.java:4813)
at clojure.main$load_script__5793.invoke(main.clj:206)
at clojure.main$script_opt__5824.invoke(main.clj:258)
at clojure.main$main__5848$fn__5850.invoke(main.clj:333)
at clojure.main$main__5848.doInvoke(main.clj:328)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at clojure.lang.Var.invoke(Var.java:346)
at clojure.lang.AFn.applyToHelper(AFn.java:173)
at clojure.lang.Var.applyTo(Var.java:463)
at clojure.main.main(main.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:582)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Caused by: java.lang.NoSuchMethodError:
java.lang.Class.getSimpleName()Ljava/lang/String;
at clojure.lang.AFn.throwArity(AFn.java:447)
at clojure.lang.AFn.invoke(AFn.java:48)
at user$eval__4.invoke(testing.clj:3)
at clojure.lang.Compiler.eval(Compiler.java:4522)
... 16 more


Using latest released version of clojure.


2009/3/29 Stephen C. Gilardi squee...@mac.com


 On Mar 28, 2009, at 8:01 PM, Glen Stampoultzis wrote:

  Sorry I just realized I was a bit ambiguous with this.  The exception does
 show the line number (in the second stack trace).  But it's gone missing in
 the top one.


 Is this with the current svn or most recent release of Clojure? It would be
 helpful if you could post a (small) reproducible recipe for a test case that
 shows the problem.

 --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
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: new in contrib.test-is: fixtures

2009-03-28 Thread David Nolen

very cool :)

On 3/28/09, Stuart Sierra the.stuart.sie...@gmail.com wrote:

 Hi folks,
 I finally came up with fixtures for clojure.contrib.test-is.  Now you
 can do before/after setup for each test case.  Here's the
 documentation, let me know what you think.
 -Stuart Sierra

   ;; FIXTURES (new)
   ;;
   ;; Fixtures allow you to run code before and after tests, to set up
   ;; the context in which tests should be run.
   ;;
   ;; A fixture is just a function that calls another function passed
 as
   ;; an argument.  It looks like this:
   (defn my-fixture [f]
 ;; Perform setup, establish bindings, whatever.
 (f) ;; Then call the function we were passed.
 ;; Tear-down / clean-up code here.
 )

   ;; Fixtures are attached to namespaces in one of two ways.  each
   ;; fixtures are run repeatedly, once for each test function created
   ;; with deftest or with-test.  each fixtures are useful for
   ;; establishing a consistent before/after state for each test, like
   ;; clearing out database tables.
   ;;
   ;; each fixtures can be attached to the current namespace like
 this:
   (use-fixtures :each fixture1 fixture2 ...)
   ;; The fixture1, fixture2 are just functions like the example above.
   ;; They can also be anonymous functions, like this:
   (use-fixtures :each (fn [f] setup... (f) cleanup...))
   ;;
   ;; The other kind of fixture, a once fixture, is only run once,
   ;; around ALL the tests in the namespace.  once fixtures are
 useful
   ;; for tasks that only need to be performed once, like establishing
   ;; database connections, or for time-consuming tasks.
   ;;
   ;; Attach once fixtures to the current namespace like this:
   (use-fixtures :once fixture1 fixture2 ...)

 


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



new in duck-streams: with-out-writer / with-in-reader

2009-03-28 Thread Stuart Sierra

Following a discussion from a few days ago, I've added two new macros
to clojure.contrib.duck-streams:

(defmacro with-out-writer
  Opens a writer on f, binds it to *out*, and evalutes body.
  [f  body]
  `(with-open [stream# (writer ~f)]
 (binding [*out* stream#]
   ~...@body)))

(defmacro with-in-reader
  Opens a PushbackReader on f, binds it to *in*, and evaluates body.
  [f  body]
  `(with-open [stream# (PushbackReader. (reader ~f))]
 (binding [*in* stream#]
   ~...@body)))


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



new contrib: with-ns macro

2009-03-28 Thread Stuart Sierra

Hi folks,
New lib in contrib: with-ns -- a library to temporarily switch
namespaces at run-time.   People request this occasionally, and I
finally came up with a way to do it.  The code is sneaky, and it
relies on eval, but it works.  Here's the doc:

clojure.contrib.with-ns/with-ns
([ns  body])
Macro
  Evaluates body in another namespace.  ns is either a namespace
  object or a symbol.  This makes it possible to define functions in
  namespaces other than the current one.
-
clojure.contrib.with-ns/with-temp-ns
([ body])
Macro
  Evaluates body in an anonymous namespace, which is then immediately
  removed.  The temporary namespace will 'refer' clojure.core.

-Stuart Sierra
--~--~-~--~~~---~--~~
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
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: Request for improved error reporting

2009-03-28 Thread Glen Stampoultzis
2009/3/29 Stephen C. Gilardi squee...@mac.com


 On Mar 28, 2009, at 10:31 PM, Glen Stampoultzis wrote:

  It wasn't really this specific problem that I wanted to point out but more
 to trigger a rethink of how errors are reported back to the user.


 I understand, but without specifying which Clojure you're using and giving
 an example of how it happened, it's hard to compare our results.


Sorry when I said the latest released version of clojure I thought that
would be enough to go on.  I was using clojure_20090320.zip which matches
your version.




  Here's an example that gives an error somewhat similar to the one I
 posted:

 (defn testing [a b] (print a b))
 (testing)

 java.lang.NoSuchMethodError:
 java.lang.Class.getSimpleName()Ljava/lang/String; (testing.clj:0)
 [ and lots more stack trace ]



 Here's what I get with clojure_20090320 downloaded from:

http://code.google.com/p/clojure/downloads/list

 % java -cp clojure.jar clojure.main
 Clojure
 user= (defn testing [a b] (print a b))
 #'user/testing
 user= (testing)
 java.lang.IllegalArgumentException: Wrong number of args passed to:
 user$testing (NO_SOURCE_FILE:0)
 user=

 That's quite different from your result and I think more in line with what
 you're requesting. Are you able to reproduce this result using the Clojure
 version I referenced?

 --Steve


The difference was that I wasn't running through the REPL.  When I run
through the REPL I get the same result as you. If you run the code from a
file you get:

C:\products\clojurejava -cp clojure.jar clojure.main test.clj
java.lang.IllegalArgumentException: Wrong number of args passed to:
user$testing (test.clj:0)
at clojure.lang.Compiler.eval(Compiler.java:4533)
at clojure.lang.Compiler.load(Compiler.java:4846)
at clojure.lang.Compiler.loadFile(Compiler.java:4813)
at clojure.main$load_script__5793.invoke(main.clj:206)
at clojure.main$script_opt__5824.invoke(main.clj:258)
at clojure.main$main__5848$fn__5850.invoke(main.clj:333)
at clojure.main$main__5848.doInvoke(main.clj:328)
at clojure.lang.RestFn.invoke(RestFn.java:413)
at clojure.lang.Var.invoke(Var.java:346)
at clojure.lang.AFn.applyToHelper(AFn.java:173)
at clojure.lang.Var.applyTo(Var.java:463)
at clojure.main.main(main.java:39)
Caused by: java.lang.IllegalArgumentException: Wrong number of args passed
to: user$testing
at clojure.lang.AFn.throwArity(AFn.java:449)
at clojure.lang.AFn.invoke(AFn.java:48)
at user$eval__4.invoke(test.clj:2)
at clojure.lang.Compiler.eval(Compiler.java:4522)
... 11 more

I think part of my problem is that I'm thinking of it as a compile error
when actually it's a runtime error.  Even so most of the stack is
unnecessary - would it be feasible (or even desirable) to strip the parts
not relevant to the user?

--~--~-~--~~~---~--~~
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
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: new in duck-streams: with-out-writer / with-in-reader

2009-03-28 Thread Parth



On Mar 29, 7:36 am, Stuart Sierra the.stuart.sie...@gmail.com wrote:
 Following a discussion from a few days ago, I've added two new macros
 to clojure.contrib.duck-streams:

 (defmacro with-out-writer
   Opens a writer on f, binds it to *out*, and evalutes body.
   [f  body]
   `(with-open [stream# (writer ~f)]
      (binding [*out* stream#]
       �...@body)))

 (defmacro with-in-reader
   Opens a PushbackReader on f, binds it to *in*, and evaluates body.
   [f  body]
   `(with-open [stream# (PushbackReader. (reader ~f))]
      (binding [*in* stream#]
       �...@body)))

 -Stuart Sierra

This is very useful. Thank you :)

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

2009-03-28 Thread mikel



On Mar 28, 4:28 pm, David Nolen dnolen.li...@gmail.com wrote:
 On Sat, Mar 28, 2009 at 4:40 PM, mikel mev...@mac.com wrote:

  So, at minimum, to make a solid port, you need to add a function that
  can return a sensible type value for any input

 Enjoying the thread. Out of curiosity for which Clojure values is the return
 value of the type function undefined?

Try this:

(type (proxy [clojure.lang.IMeta clojure.lang.IRef][]))

java.lang.UnsupportedOperationException: meta (NO_SOURCE_FILE:0)
  [Thrown class clojure.lang.Compiler$CompilerException]


No doubt someone is going to point out that the proxy object I created
there is useless; that's true, but beside the point. The point is that
it's straightforward to create some value v for which (type v) is
undefined. In order to make a Clojure-friendly version of CLOS, you
need some concept of object type such that you can define a function
that returns a sensible type for any value.

The way that Dylan handled situations similar to Clojure's proxy
objects was with objects called singletons; a singleton is an object
that represents a specific value as a class. For example, (singleton
5) returns an object that is a class, but is also the integer 5. You
can define methods that specialize on such objects.

For example, below is an excerpt from the UI libraries of Apple's long-
ago Bauhaus project. Notice the first line:

  (define-method build-form ((key (singleton label:))

The equivalent syntax in Clojure (if clojure had these mechanisms)
would be:

  (define-method build-form [[key (singleton :label)]


(There was no equivalent of defn in Dylan; there was only define-
method, because all values were instances of Dylan classes, and in
that environment a defn is no different from a define-method without
value constraints. Consequently, all functions were polymorphic; all
unsealed functions could be extended by adding new method
definitions.)



(define-method build-form ((key (singleton label:))
   remaining-spec
   form
   current-x
   current-y
   layout-vector)
  (ignore key)
  (bind ((label-string (car remaining-spec))
 (next (rest remaining-spec)))
  (add-feature-to-form
   (make label-text
 string: label-string
 top: current-y
 left: current-x
 style-array: $espy-10-bold-pointer)
   next form current-x current-y layout-vector)))


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