This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Questions about #!key arguments


On 10/25/2011 12:01 PM, Jamison Hope wrote:
On Oct 25, 2011, at 2:31 PM, Taylor Venable wrote:

Hi there, I'm trying to use #!key arguments but encountering some errors.

[...]


#|kawa:30|# (define (foo #!key (code ::int 400) (message ::string
"brrp"))
#|(---:31|# (format #t "code: ~a~%" code)
#|(---:32|# (format #t "message: ~a~%" message))
exception while initializing module atInteractiveLevel$23
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:84)
at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:269)
at gnu.expr.ModuleExp.evalModule(ModuleExp.java:180)
at kawa.Shell.run(Shell.java:280)
at kawa.Shell.run(Shell.java:194)
at kawa.Shell.run(Shell.java:175)
at kawa.repl.main(repl.java:884)
Caused by: java.lang.VerifyError: (class: atInteractiveLevel$23,
method: foo$V signature: ([Ljava/lang/Object;)V) Expecting to find
object/array on stack
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2308)
at java.lang.Class.getDeclaredField(Class.java:1897)
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:74)
... 6 more

The problem here isn't a problem with your syntax, it's with the types you're using. Well, one of them, anyway. I don't know if it's documented anywhere,

No - because I never realized this didn't work.


but keyword arguments only work with arguments that are
Objects, not primitives. So, when you use int, things blow up.

You are indeed correct. I'm working on a fix.


Going back to the first example that works... that's fine when it
stands alone, but if this is inside a define-simple-class I get a
problem when I try to invoke it.

I've never tried to use #!key in class methods, so I can't help you there, sorry. Per?

Getting that to work would be more difficult. The problem is that class methods are supposed to be Java methods, with a calling convention that interoperates well with Java classes. I'm not sure how to do that. It's not a priority - but there should be a decent error message.

We probably also want to re-think keyword arguments a bit.  Given:
  (lambda (a1 a2 #!key k1 k2 #!rest r) ...)
The existing "standard" is that r *includes* the keyword arguments.
I'm not sure is this is what is most useful.  For a typical "builder"
function (HTML builder, Swing builder, etc) you want keyword arguments
for named properties followed by "child" expressions.  You don't want
all the keyword bindings mixed up with the child parameters.

So I think we need a new delimiter - I thought of #!tail.  This is like
#!rest, but it does *not* include any keyword arguments, and if there
are keyword arguments not matched by keyword parameters, then it
is an error.

Does this make sense?  Suggestions for a better name than #!tail?
(Note that adding this may not happen soon.)

It might also make sense to follow Racket in that an unquoted keyword
can *only* be used for a keyword parameter.  E.g. if you want a
list of keywords, you have to quote them:
  (list 'a: 'b: 'c:)
Contrawise, keyword parameters have to be explicit: You cannot
have a keyword be the result of evaluating an expression *unless*
you use a higher-order function like apply.  (A syntax like ,EXP:
could be used for run-time evaluation of keyword names.)
This may avoid some bugs.  More importantly, it makes the semantics
of what the compiler can and can't do less mushy, so various
optimizations become less ad hoc.  (The compiler basically assumes that
keyword arguments are explicit anyway when it performs optimizations.)
--
	--Per Bothner
per@bothner.com   http://per.bothner.com/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]