PATCH: AFn.java, RestFN.java (a better throwArity message)

14 views
Skip to first unread message

MarkSwanson

unread,
Oct 25, 2009, 12:57:09 PM10/25/09
to Clojure
Hello,

Someone recently posed the question: (why doesn't this work)
(into {} (map #([% (* % %)]) [1 2 3 4]))

(reference: http://groups.google.com/group/clojure/browse_thread/thread/7d3ee57ee8041353)

The error message was:
Caused by: java.lang.IllegalArgumentException: Wrong number of args
passed to: PersistentVector

How many args were being passed anyway? The code looked fine (to me).
It would have been helpful to me to know the number of args being
passed was zero.

With the patch below the error message would look like this:

... java.lang.IllegalArgumentException: Wrong number of args (0)
passed to: PersistentVector ...

The patch will handle all cases of wrong arity and report the expected
number of args. In some cases (RestFN) the exception will now report
the required arity as well as the given arity.

There is one improvement that could still be made to the patch:
applyTo(ISeq args) -> should report the count of args:
- return throwArity();
+ return throwArity(-1, reqArity); // TODO/BUG: -1 should be count
of args

I'm running out the door and don't have time to code this.

Please consider this patch - or something like it.



diff --git a/src/jvm/clojure/lang/AFn.java b/src/jvm/clojure/lang/
AFn.java
index e2646ad..56afa8f
100644
--- a/src/jvm/clojure/lang/
AFn.java
+++ b/src/jvm/clojure/lang/
AFn.java
@@ -45,110 +45,110 @@ public void run()
{


public Object invoke() throws Exception
{
- return throwArity
();
+ return throwArity
(0);
}

public Object invoke(Object arg1) throws Exception
{
- return throwArity
();
+ return throwArity
(1);
}

public Object invoke(Object arg1, Object arg2) throws Exception
{
- return throwArity
();
+ return throwArity
(2);
}

public Object invoke(Object arg1, Object arg2, Object arg3) throws
Exception{
- return throwArity
();
+ return throwArity
(3);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4) throws Exception
{
- return throwArity
();
+ return throwArity
(4);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5) throws Exception
{
- return throwArity
();
+ return throwArity
(5);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6) throws Exception
{
- return throwArity
();
+ return throwArity
(6);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7)
throws Exception
{
- return throwArity
();
+ return throwArity
(7);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8) throws Exception
{
- return throwArity
();
+ return throwArity
(8);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9) throws Exception
{
- return throwArity
();
+ return throwArity
(9);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10) throws
Exception{
- return throwArity
();
+ return throwArity
(10);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11) throws Exception
{
- return throwArity
();
+ return throwArity
(11);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12) throws Exception
{
- return throwArity
();
+ return throwArity
(12);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object
arg13)
throws Exception
{
- return throwArity
();
+ return throwArity
(13);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object arg13, Object
arg14)
throws Exception
{
- return throwArity
();
+ return throwArity
(14);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object arg13, Object
arg14,
Object arg15) throws Exception
{
- return throwArity
();
+ return throwArity
(15);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object arg13, Object
arg14,
Object arg15, Object arg16) throws Exception
{
- return throwArity
();
+ return throwArity
(16);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object arg13, Object
arg14,
Object arg15, Object arg16, Object arg17) throws
Exception
{
- return throwArity
();
+ return throwArity
(17);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object arg13, Object
arg14,
Object arg15, Object arg16, Object arg17, Object
arg18) throws Exception
{
- return throwArity
();
+ return throwArity
(18);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object arg13, Object
arg14,
Object arg15, Object arg16, Object arg17, Object
arg18, Object arg19) throws Exception
{
- return throwArity
();
+ return throwArity
(19);
}

public Object invoke(Object arg1, Object arg2, Object arg3, Object
arg4, Object arg5, Object arg6, Object
arg7,
Object arg8, Object arg9, Object arg10, Object
arg11, Object arg12, Object arg13, Object
arg14,
Object arg15, Object arg16, Object arg17, Object
arg18, Object arg19, Object
arg20)
throws Exception
{
- return throwArity
();
+ return throwArity
(20);
}


@@ -157,7 +157,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
Object arg15, Object arg16, Object arg17, Object
arg18, Object arg19, Object
arg20,
Object...
args)
throws Exception
{
- return throwArity
();
+ return throwArity
(-1);
}

public Object applyTo(ISeq arglist) throws Exception
{
@@ -443,10 +443,35 @@ static public Object applyToHelper(IFn ifn, ISeq
arglist) throws Exception
{
}
}

-public Object throwArity()
{
+public Object throwArity(int argNum)
{
String name = getClass().getSimpleName
();
int suffix = name.lastIndexOf
("__");
- throw new IllegalArgumentException("Wrong number of args
passed to: "
+ String
number;
+ if (argNum == -1)
{
+ number =
"...";
+ }
+ else
{
+ number = Integer.toString
(argNum);
+ }
+ throw new IllegalArgumentException("Wrong number of args (" +
number +
+
") passed to:
"
+ (suffix == -1 ? name :
name.substring(0, suffix)).replace('_',
'-'));
}
+
+public Object throwArity(int argNum, int reqArity)
{
+ String name = getClass().getSimpleName
();
+ int suffix = name.lastIndexOf
("__");
+ String
number;
+ if (argNum == -1)
{
+ number =
"...";
+ }
+ else
{
+ number = Integer.toString
(argNum);
+ }
+ throw new IllegalArgumentException("Wrong number of args (" +
number +
+
") (required=" + reqArity
+
+
") passed to:
"
+ + (suffix == -1 ? name :
name.substring(0, suffix)).replace('_',
'-'));
+}
+
}
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/
RT.java
index a5da74a..c25c489
100644
--- a/src/jvm/clojure/lang/
RT.java
+++ b/src/jvm/clojure/lang/
RT.java
@@ -476,7 +476,7 @@ static ISeq seqFrom(Object coll)
{
else
{
Class c = coll.getClass
();
Class sc = c.getSuperclass
();
- throw new IllegalArgumentException("Don't know how to
create ISeq from: " + c.getSimpleName
());
+ throw new IllegalArgumentException("Don't know how to
create ISeq from: " + c.getSimpleName() + " / " + c.getName
());
}
}

diff --git a/src/jvm/clojure/lang/RestFn.java b/src/jvm/clojure/lang/
RestFn.java
index 4e15f79..d99afef
100644
--- a/src/jvm/clojure/lang/
RestFn.java
+++ b/src/jvm/clojure/lang/
RestFn.java
@@ -392,7 +392,7 @@ public Object applyTo(ISeq args) throws Exception
{
, args.next
());

}
- return throwArity
();
+ return throwArity(-1, reqArity); // TODO/BUG: -1 should be
count of args
}

public Object invoke() throws Exception
{
@@ -401,7 +401,7 @@ public Object invoke() throws Exception
{
case
0:
return doInvoke
(null);

default:
- return throwArity
();
+ return throwArity(0,
reqArity);
}

}
@@ -414,7 +414,7 @@ public Object invoke(Object arg1) throws Exception
{
case
1:
return doInvoke(arg1,
null);

default:
- return throwArity
();
+ return throwArity(1,
reqArity);
}

}
@@ -429,7 +429,7 @@ public Object invoke(Object arg1, Object arg2)
throws Exception
{
case
2:
return doInvoke(arg1, arg2,
null);

default:
- return throwArity
();
+ return throwArity(2,
reqArity);
}

}
@@ -446,7 +446,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3) throws Exception
{
case
3:
return doInvoke(arg1, arg2, arg3,
null);

default:
- return throwArity
();
+ return throwArity(3,
reqArity);
}

}
@@ -465,7 +465,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4)
throws
case
4:
return doInvoke(arg1, arg2, arg3, arg4,
null);

default:
- return throwArity
();
+ return throwArity(4,
reqArity);
}

}
@@ -486,7 +486,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
5:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
null);

default:
- return throwArity
();
+ return throwArity(5,
reqArity);
}

}
@@ -509,7 +509,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
6:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6,
null);

default:
- return throwArity
();
+ return throwArity(6,
reqArity);
}

}
@@ -535,7 +535,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
7:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7,
null);

default:
- return throwArity
();
+ return throwArity(7,
reqArity);
}

}
@@ -563,7 +563,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
8:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8,
null);

default:
- return throwArity
();
+ return throwArity(8,
reqArity);
}

}
@@ -593,7 +593,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
9:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9,
null);

default:
- return throwArity
();
+ return throwArity(9,
reqArity);
}

}
@@ -625,7 +625,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
10:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10,
null);

default:
- return throwArity
();
+ return throwArity(10,
reqArity);
}

}
@@ -659,7 +659,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
11:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11,
null);

default:
- return throwArity
();
+ return throwArity(11,
reqArity);
}

}
@@ -695,7 +695,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
12:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12,
null);

default:
- return throwArity
();
+ return throwArity(12,
reqArity);
}

}
@@ -747,7 +747,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
case
13:
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13,
null);

default:
- return throwArity
();
+ return throwArity(13,
reqArity);
}

}
@@ -803,7 +803,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13,
arg14,

null);

default:
- return throwArity
();
+ return throwArity(14,
reqArity);
}

}
@@ -862,7 +862,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13,
arg14,
arg15,
null);

default:
- return throwArity
();
+ return throwArity(15,
reqArity);
}

}
@@ -924,7 +924,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4,
Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13,
arg14,
arg15, arg16,
null);

default:
- return throwArity
();
+ return throwArity(16,
reqArity);
}

}
@@ -989,7 +989,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4, Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,
arg15, arg16, arg17, null);
default:
- return throwArity();
+ return throwArity(17, reqArity);
}

}
@@ -1058,7 +1058,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4, Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,
arg15, arg16, arg17, arg18,
null);
default:
- return throwArity();
+ return throwArity(18, reqArity);
}

}
@@ -1133,7 +1133,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4, Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,
arg15, arg16, arg17, arg18,
arg19, null);
default:
- return throwArity();
+ return throwArity(19, reqArity);
}

}
@@ -1216,7 +1216,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4, Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,
arg15, arg16, arg17, arg18,
arg19, arg20, null);
default:
- return throwArity();
+ return throwArity(20, reqArity);
}

}
@@ -1307,7 +1307,7 @@ public Object invoke(Object arg1, Object arg2,
Object arg3, Object arg4, Object
return doInvoke(arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,
arg15, arg16, arg17, arg18,
arg19, arg20, ArraySeq.create(args));
default:
- return throwArity();
+ return throwArity(-1, reqArity);
}

}

eyeris

unread,
Oct 25, 2009, 1:12:22 PM10/25/09
to Clojure
+1, This would have helped me a lot when I first came to Clojure (from
a non-lisp background).


On Oct 25, 11:57 am, MarkSwanson <mark.swanson...@gmail.com> wrote:
> Hello,
>
> Someone recently posed the question: (why doesn't this work)
> (into {} (map #([% (* % %)]) [1 2 3 4]))
>
> (reference:http://groups.google.com/group/clojure/browse_thread/thread/7d3ee57ee...)

MarkSwanson

unread,
Oct 25, 2009, 3:16:00 PM10/25/09
to Clojure
Ok, I see now I should not post patches here because it messes up the
formatting. I can't seem to find an option to paste <pre> text.

I've placed the patch here:
http://www.scheduleworld.com/sw2/arity.patch.gz

Patrick Steiger

unread,
Oct 25, 2009, 2:59:37 PM10/25/09
to clo...@googlegroups.com
+1. I find Clojure error messages a little bit cryptic, and this is a nice effort to change this.

2009/10/25 MarkSwanson <mark.sw...@gmail.com>

Hello,

Someone recently posed the question: (why doesn't this work)
(into {} (map #([% (* % %)]) [1 2 3 4]))

(reference: http://groups.google.com/group/clojure/browse_thread/thread/7d3ee57ee8041353)

The error message was:
Caused by: java.lang.IllegalArgumentException: Wrong number of args
passed to: PersistentVector

How many args were being passed anyway? The code looked fine (to me).
It would have been helpful to me to know the number of args being
passed was zero.

With the patch below the error message would look like this:

... java.lang.IllegalArgumentException: Wrong number of args (0)
passed to: PersistentVector ...

The patch will handle all cases of wrong arity and report the expected
number of args. In some cases (RestFN) the exception will now report
the required arity as well as the given arity.
...

--
Patrick Steiger.

"Theory is when you know something, but it doesn't work. Practice is
when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't
know why." - Anon

MarkSwanson

unread,
Oct 26, 2009, 1:37:36 PM10/26/09
to Clojure
This seems like an even better place to post it:

http://paste.lisp.org/display/89307

Jason Wolfe

unread,
Oct 26, 2009, 1:55:12 PM10/26/09
to Clojure
Hi Mark,

Thanks for the patch! Have you seen this page?

http://clojure.org/contributing

You should follow the instructions there to get your patch included.
In particular, that page tells you where to post it, and has other
details; for instance, you must send a CA to Rich before any code you
write can be incorporated into Clojure.

Cheers, Jason

John Harrop

unread,
Oct 26, 2009, 4:14:13 PM10/26/09
to clo...@googlegroups.com
On Mon, Oct 26, 2009 at 1:55 PM, Jason Wolfe <jaw...@berkeley.edu> wrote:
Hi Mark,

Thanks for the patch!  Have you seen this page?

http://clojure.org/contributing

You should follow the instructions there to get your patch included.
In particular, that page tells you where to post it, and has other
details; for instance, you must send a CA to Rich before any code you
write can be incorporated into Clojure.

What about code someone explicitly places into the public domain? Uncopyrighted code shouldn't need a CA I'd think. 

MarkSwanson

unread,
Oct 26, 2009, 7:54:12 PM10/26/09
to Clojure
Thanks for the link.

I read somewhere that Rich asked folks to vet stuff on this Google
Group first, so that's why I posted it here.
I previously posted a "patch" to Clojure here and Rich applied it. I
didn't have to do the CA, and if posting my patches into the public
domain works - then please consider my patch as public domain. If this
works I'd prefer to do the same for all future patches.

P.S. All of my legal and banking work over the past few years (which
includes getting VC and forming a startup) was all done with signed
PDFs - no snail mail required. I vote to allow a signed CA PDF in
addition to postal mail.


On Oct 26, 4:14 pm, John Harrop <jharrop...@gmail.com> wrote:

Emeka

unread,
Oct 27, 2009, 1:39:17 PM10/27/09
to clo...@googlegroups.com
On Sun, Oct 25, 2009 at 4:57 PM, MarkSwanson <mark.sw...@gmail.com> wrote:

Hello,

Someone recently posed the question: (why doesn't this work)
(into {} (map #([% (* % %)]) [1 2 3 4]))


Is this actually a Vector problem or the limitation of the anonymous function?

Regards,
Emeka
 

John Harrop

unread,
Oct 27, 2009, 2:10:12 PM10/27/09
to clo...@googlegroups.com
On Tue, Oct 27, 2009 at 1:39 PM, Emeka <emeka...@gmail.com> wrote:
On Sun, Oct 25, 2009 at 4:57 PM, MarkSwanson <mark.sw...@gmail.com> wrote:

Hello,

Someone recently posed the question: (why doesn't this work)
(into {} (map #([% (* % %)]) [1 2 3 4]))


Is this actually a Vector problem or the limitation of the anonymous function?

Neither. It's a limitation of the #() read-macro. (fn [x] [x (* x x)]) works just fine.

P.S. *please* trim quoted text. I've noticed a lot of users of this list leaving large wads of quoted text at the bottoms of their posts after the portions they've replied to. Ordinarily it doesn't bother me much; I delete it if I reply. But in this case there were hundreds of lines of it and the gmail interface doesn't seem to support shift-pgdn, so ...

Emeka

unread,
Oct 27, 2009, 2:17:15 PM10/27/09
to clo...@googlegroups.com
John,

On Tue, Oct 27, 2009 at 6:10 PM, John Harrop <jharr...@gmail.com> wrote:
On Tue, Oct 27, 2009 at 1:39 PM, Emeka <emeka...@gmail.com> wrote:
On Sun, Oct 25, 2009 at 4:57 PM, MarkSwanson <mark.sw...@gmail.com> wrote:

Hello,

Someone recently posed the question: (why doesn't this work)
(into {} (map #([% (* % %)]) [1 2 3 4]))


Is this actually a Vector problem or the limitation of the anonymous function?

Neither. It's a limitation of the #() read-macro. (fn [x] [x (* x x)]) works just fine.
Is #() read-macro not an anonymous function?

Regards,
Emeka

John Harrop

unread,
Oct 27, 2009, 2:28:58 PM10/27/09
to clo...@googlegroups.com
It is, but it's not the only way of writing one, and the other way doesn't have the limitation.

Emeka

unread,
Oct 27, 2009, 2:33:48 PM10/27/09
to clo...@googlegroups.com
John,

That is why I asked that question because I figured out that the problem has nothing to do with Vector but with #() read macro. I wanted to correct the impression that the problem was from Vector.

Regards,
Emeka


John Harrop

unread,
Oct 28, 2009, 2:56:01 AM10/28/09
to clo...@googlegroups.com
On Tue, Oct 27, 2009 at 2:33 PM, Emeka <emeka...@gmail.com> wrote:
John,

That is why I asked that question because I figured out that the problem has nothing to do with Vector but with #() read macro. I wanted to correct the impression that the problem was from Vector.

That was correct. I just wanted to avoid any confusion between the #() read macro and anonymous functions; the read macro is one way of writing an anonymous function but it is not the only way so the two aren't quite interchangeable. 

Meikel Brandmeyer

unread,
Oct 28, 2009, 3:08:55 AM10/28/09
to Clojure
Hi,

On Oct 28, 7:56 am, John Harrop <jharrop...@gmail.com> wrote:

> That was correct. I just wanted to avoid any confusion between the #() read
> macro and anonymous functions; the read macro is one way of writing an
> anonymous function but it is not the only way so the two aren't quite
> interchangeable.

#() is intended only for short anonymous functions like #(instance?
Foo %). It is not a replacement for fn. #() does not nest. Here you
also see why it works the way it works: #((instance? Foo %)) would a)
look weird and b) give a wrong impression, that you "call" the return
value of instance?. So for anything more complicated you should use fn
instead of #().

Sincerely
Meikel
Reply all
Reply to author
Forward
0 new messages