So the times when I have the most trouble in Clojure is related to
laziness. Using a lot of lazy operations (for, map, etc.) can cause
some grief.  I was refactoring and added a new parameter to a somewhat
common function and didn't catch all the invocations. However, my
exception turned up in an entirely different area (one that triggered
a cascade of lazy evaluations leading to the exception).

Here, I re-instated the bug and get a large, scary exception:

ERROR in (simple-view-and-fragment) (test_is.clj:657)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.RuntimeException: java.lang.RuntimeException:
java.lang.RuntimeException: java.lang.IllegalArgumentException: Wrong
number of args passed to: view-manager$fn
 at clojure.lang.LazySeq.seq (LazySeq.java:46)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    clojure.core/spread (core.clj:383)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764.invoke
(view_manager.clj:52)
    
com.howardlewisship.cascade.view_manager$parse_and_create_view__834$view_equivalent_of_fragment__836.invoke
(view_manager.clj:170)
    com.howardlewisship.cascade.test_views/test_view (test_views.clj:53)
    com.howardlewisship.cascade.test_views/fn (test_views.clj:60)
    clojure.contrib.test_is$test_var__318$fn__320.invoke (test_is.clj:655)
    clojure.contrib.test_is/test_var (test_is.clj:655)
    clojure.contrib.test_is$test_all_vars__325$fn__327$fn__330.invoke
(test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is$test_all_vars__325$fn__327.invoke (test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is/test_all_vars (test_is.clj:666)
    clojure.contrib.test_is/test_ns (test_is.clj:688)
    clojure.core$map__3815$fn__3817.invoke (core.clj:1503)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.Cons.next (Cons.java:37)
    clojure.lang.RT.next (RT.java:560)
    clojure.core/next (core.clj:50)
    clojure.core$reduce__3319$fn__3322.invoke (core.clj:539)
    clojure.core/reduce (core.clj:537)
    clojure.core/reduce (core.clj:531)
    clojure.core$merge_with__3945.doInvoke (core.clj:1657)
    clojure.lang.RestFn.applyTo (RestFn.java:144)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:443)
    clojure.contrib.test_is$run_tests__339.doInvoke (test_is.clj:701)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    user/eval (all_tests.clj:26)
    clojure.lang.Compiler.eval (Compiler.java:4532)
    clojure.lang.Compiler.load (Compiler.java:4857)
    clojure.lang.Compiler.loadFile (Compiler.java:4824)
    clojure.main/load_script (main.clj:206)
    clojure.main/script_opt (main.clj:258)
    clojure.main$main__5888.doInvoke (main.clj:333)
    clojure.lang.RestFn.invoke (RestFn.java:413)
    clojure.lang.Var.invoke (Var.java:346)
    clojure.lang.AFn.applyToHelper (AFn.java:173)
    clojure.lang.Var.applyTo (Var.java:463)
    clojure.main.main (main.java:39)
Caused by: java.lang.RuntimeException: java.lang.RuntimeException:
java.lang.IllegalArgumentException: Wrong number of args passed to:
view-manager$fn
 at clojure.lang.LazySeq.seq (LazySeq.java:46)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    clojure.core/spread (core.clj:383)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764.invoke
(view_manager.clj:52)
    
com.howardlewisship.cascade.view_manager$create_static_element_renderer__823$static_element_renderer__825.invoke
(view_manager.clj:147)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764$iter__765__767$fn__768.invoke
(view_manager.clj:53)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    clojure.core/spread (core.clj:383)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764.invoke
(view_manager.clj:52)
    
com.howardlewisship.cascade.view_manager$parse_and_create_view__834$view_equivalent_of_fragment__836.invoke
(view_manager.clj:170)
    com.howardlewisship.cascade.test_views/test_view (test_views.clj:53)
    com.howardlewisship.cascade.test_views/fn (test_views.clj:60)
    clojure.contrib.test_is$test_var__318$fn__320.invoke (test_is.clj:655)
    clojure.contrib.test_is/test_var (test_is.clj:655)
    clojure.contrib.test_is$test_all_vars__325$fn__327$fn__330.invoke
(test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is$test_all_vars__325$fn__327.invoke (test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is/test_all_vars (test_is.clj:666)
    clojure.contrib.test_is/test_ns (test_is.clj:688)
    clojure.core$map__3815$fn__3817.invoke (core.clj:1503)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.Cons.next (Cons.java:37)
    clojure.lang.RT.next (RT.java:560)
    clojure.core/next (core.clj:50)
    clojure.core$reduce__3319$fn__3322.invoke (core.clj:539)
    clojure.core/reduce (core.clj:537)
    clojure.core/reduce (core.clj:531)
    clojure.core$merge_with__3945.doInvoke (core.clj:1657)
    clojure.lang.RestFn.applyTo (RestFn.java:144)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:443)
    clojure.contrib.test_is$run_tests__339.doInvoke (test_is.clj:701)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    user/eval (all_tests.clj:26)
    clojure.lang.Compiler.eval (Compiler.java:4532)
    clojure.lang.Compiler.load (Compiler.java:4857)
    clojure.lang.Compiler.loadFile (Compiler.java:4824)
    clojure.main/load_script (main.clj:206)
    clojure.main/script_opt (main.clj:258)
    clojure.main$main__5888.doInvoke (main.clj:333)
    clojure.lang.RestFn.invoke (RestFn.java:413)
    clojure.lang.Var.invoke (Var.java:346)
    clojure.lang.AFn.applyToHelper (AFn.java:173)
    clojure.lang.Var.applyTo (Var.java:463)
    clojure.main.main (main.java:39)
Caused by: java.lang.RuntimeException:
java.lang.IllegalArgumentException: Wrong number of args passed to:
view-manager$fn
 at clojure.lang.LazySeq.seq (LazySeq.java:46)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764$iter__765__767$fn__768.invoke
(view_manager.clj:52)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    clojure.core/spread (core.clj:383)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764.invoke
(view_manager.clj:52)
    
com.howardlewisship.cascade.view_manager$create_static_element_renderer__823$static_element_renderer__825.invoke
(view_manager.clj:147)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764$iter__765__767$fn__768.invoke
(view_manager.clj:53)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    clojure.core/spread (core.clj:383)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764.invoke
(view_manager.clj:52)
    
com.howardlewisship.cascade.view_manager$parse_and_create_view__834$view_equivalent_of_fragment__836.invoke
(view_manager.clj:170)
    com.howardlewisship.cascade.test_views/test_view (test_views.clj:53)
    com.howardlewisship.cascade.test_views/fn (test_views.clj:60)
    clojure.contrib.test_is$test_var__318$fn__320.invoke (test_is.clj:655)
    clojure.contrib.test_is/test_var (test_is.clj:655)
    clojure.contrib.test_is$test_all_vars__325$fn__327$fn__330.invoke
(test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is$test_all_vars__325$fn__327.invoke (test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is/test_all_vars (test_is.clj:666)
    clojure.contrib.test_is/test_ns (test_is.clj:688)
    clojure.core$map__3815$fn__3817.invoke (core.clj:1503)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.Cons.next (Cons.java:37)
    clojure.lang.RT.next (RT.java:560)
    clojure.core/next (core.clj:50)
    clojure.core$reduce__3319$fn__3322.invoke (core.clj:539)
    clojure.core/reduce (core.clj:537)
    clojure.core/reduce (core.clj:531)
    clojure.core$merge_with__3945.doInvoke (core.clj:1657)
    clojure.lang.RestFn.applyTo (RestFn.java:144)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:443)
    clojure.contrib.test_is$run_tests__339.doInvoke (test_is.clj:701)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    user/eval (all_tests.clj:26)
    clojure.lang.Compiler.eval (Compiler.java:4532)
    clojure.lang.Compiler.load (Compiler.java:4857)
    clojure.lang.Compiler.loadFile (Compiler.java:4824)
    clojure.main/load_script (main.clj:206)
    clojure.main/script_opt (main.clj:258)
    clojure.main$main__5888.doInvoke (main.clj:333)
    clojure.lang.RestFn.invoke (RestFn.java:413)
    clojure.lang.Var.invoke (Var.java:346)
    clojure.lang.AFn.applyToHelper (AFn.java:173)
    clojure.lang.Var.applyTo (Var.java:463)
    clojure.main.main (main.java:39)
Caused by: java.lang.IllegalArgumentException: Wrong number of args
passed to: view-manager$fn
 at clojure.lang.AFn.throwArity (AFn.java:449)
    clojure.lang.AFn.invoke (AFn.java:52)
    clojure.lang.MultiFn.invoke (MultiFn.java:157)
    clojure.core$map__3815$fn__3817.invoke (core.clj:1503)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764$iter__765__767$fn__768.invoke
(view_manager.clj:52)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    clojure.core/spread (core.clj:383)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764.invoke
(view_manager.clj:52)
    
com.howardlewisship.cascade.view_manager$create_static_element_renderer__823$static_element_renderer__825.invoke
(view_manager.clj:147)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764$iter__765__767$fn__768.invoke
(view_manager.clj:53)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.RT.seq (RT.java:436)
    clojure.core/seq (core.clj:103)
    clojure.core/spread (core.clj:383)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    
com.howardlewisship.cascade.view_manager$combine_render_funcs__762$combined__764.invoke
(view_manager.clj:52)
    
com.howardlewisship.cascade.view_manager$parse_and_create_view__834$view_equivalent_of_fragment__836.invoke
(view_manager.clj:170)
    com.howardlewisship.cascade.test_views/test_view (test_views.clj:53)
    com.howardlewisship.cascade.test_views/fn (test_views.clj:60)
    clojure.contrib.test_is$test_var__318$fn__320.invoke (test_is.clj:655)
    clojure.contrib.test_is/test_var (test_is.clj:655)
    clojure.contrib.test_is$test_all_vars__325$fn__327$fn__330.invoke
(test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is$test_all_vars__325$fn__327.invoke (test_is.clj:670)
    clojure.contrib.test_is/default_fixture (test_is.clj:628)
    clojure.contrib.test_is/test_all_vars (test_is.clj:666)
    clojure.contrib.test_is/test_ns (test_is.clj:688)
    clojure.core$map__3815$fn__3817.invoke (core.clj:1503)
    clojure.lang.LazySeq.seq (LazySeq.java:41)
    clojure.lang.Cons.next (Cons.java:37)
    clojure.lang.RT.next (RT.java:560)
    clojure.core/next (core.clj:50)
    clojure.core$reduce__3319$fn__3322.invoke (core.clj:539)
    clojure.core/reduce (core.clj:537)
    clojure.core/reduce (core.clj:531)
    clojure.core$merge_with__3945.doInvoke (core.clj:1657)
    clojure.lang.RestFn.applyTo (RestFn.java:144)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:443)
    clojure.contrib.test_is$run_tests__339.doInvoke (test_is.clj:701)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply__3243.doInvoke (core.clj:390)
    clojure.lang.RestFn.invoke (RestFn.java:428)
    user/eval (all_tests.clj:26)
    clojure.lang.Compiler.eval (Compiler.java:4532)
    clojure.lang.Compiler.load (Compiler.java:4857)
    clojure.lang.Compiler.loadFile (Compiler.java:4824)
    clojure.main/load_script (main.clj:206)
    clojure.main/script_opt (main.clj:258)
    clojure.main$main__5888.doInvoke (main.clj:333)
    clojure.lang.RestFn.invoke (RestFn.java:413)
    clojure.lang.Var.invoke (Var.java:346)
    clojure.lang.AFn.applyToHelper (AFn.java:173)
    clojure.lang.Var.applyTo (Var.java:463)
    clojure.main.main (main.java:39)

Can you tell where the error is?  The stack trace is misleading; it is
a problem in (create-static-element-renderer) but on line 133 (not the
147 listed in the stack trace).

(defn- create-static-element-renderer
  [namespace element-node]
  (let [body (element-node :body)
        token (element-node :token)
        element-uri (token :ns-uri)
        element-name (token :tag)
        element-ns-uri-to-prefix (element-node :ns-uri-to-prefix)
        body-as-funcs (map to-fragment-fn body)    ; LINE 133
        body-combined (combine-render-funcs body-as-funcs)
        attributes (construct-attributes (element-node :attributes))]
    (fn static-element-renderer [env params]
                                [(struct-map dom-node
                                  :type :element
                                  :ns-uri element-uri
                                  :ns-uri-to-prefix
(remove-cascade-namespaces element-ns-uri-to-prefix)
                                  :name element-name
                                  ; currently assuming that attributes
are "static" but
                                  ; that will change ... though we
should seperate "static" from "dynamic"
                                  :attributes attributes
                                  ; TODO: there might be a way to
identify that a static element has only static
                                  ; content, in which case the body
can itself be computed statically
                                  :content (body-combined env
params))]))) ; LINE 147


The fix was to replace line 133 with:

        body-as-funcs (map (partial to-fragment-fn namespace) body)

I'm not sure what can be done about this kind of problem. The laziness
is wonderful until it breaks ... here's an area where Haskell would
have been able to identify the incorrect call via static analysis.

Tapestry has some similar problems, based on how user code is so
intermixed with framework code; it does a lot of work to identify why
a given method is being invoked ... you get a stack of components that
are rendering (which leads to what component class methods are being
invoked); there's a similar concept in the IoC container to trace what
objects are being instantiated, which methods or contructors are being
invoked, and parameter values being calculated (this latter case uses
a lot of Thread Locals and is inefficient and ugly).

Again, I'm not sure what the solution is or what the implementation
would look like, but I'd love it if Clojure could relate back to me,
when an exception occurred, what lazy operations were taking place
that caused the bad code to be invoked.

-- 
Howard M. Lewis Ship

Creator of Apache Tapestry
Director of Open Source Technology at Formos

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

Reply via email to