public inbox for kawa@sourceware.org
 help / color / mirror / Atom feed
* enums and case
@ 2014-03-06  6:13 Jamison Hope
  0 siblings, 0 replies; only message in thread
From: Jamison Hope @ 2014-03-06  6:13 UTC (permalink / raw)
  To: kawa@sourceware.org list

It occurs to me that it would be very handy if we could use Java enums
in Scheme case expressions the way that they can be used in Java switch
statements:

> public enum Day {
>     SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
>     THURSDAY, FRIDAY, SATURDAY 
> }
> 
> Day day = ...;
> 
> switch (day) {
>   case MONDAY: ...
>   case FRIDAY: ...
>   ...
> }

becomes something like

> (define-enum Day (SUNDAY MONDAY TUESDAY ...))
> 
> (define d ::Day ...)
> 
> (case d ((MONDAY) ...) ((TUESDAY) ...) ...)

There are several issues which must be addressed:

1. How to recognize in (case d ((MONDAY) ...) ...) that we intend
   to compare against the enum constant Day:MONDAY and not the
   symbol named "MONDAY".  Should this depend upon the type
   declaration for d?  In Java, this is a compile-time error:
>    Object day = Day.MONDAY; switch (day) { /* ... */ }

   Is it acceptable for the presence or absence of a type
   declaration to alter the semantics like this in Kawa?

   If so, can a macro defined in Scheme get to a variable's
   gnu.expr.Declaration, or would case need to be rewritten as
   a Java class extending Syntax?

2. Would it be preferable to require qualified constants, as in
   (case d ((Day:MONDAY) ...) ((Day:TUESDAY) ...) ...)?  In that
   case we wouldn't need to chase the declaration for d, but on
   the downside it's more verbose.

3. The current implementation of case checks for matches with each
   datum via (eqv? key (quote datum)).  That means that here we
   would get an expansion of (eqv? d (quote Day:MONDAY)), assuming
   that we require qualified constants.

   But (quote Day:MONDAY) evaluates to the symbol with the name
   "Day:MONDAY", not to the constant named "MONDAY" of the enum
   class Day.

   Should quote recognize that there's a colon in there and check
   for an enum constant before constructing a symbol?  After all,
   '3 evaluates to an integer, not the symbol named "3".

   But what if we actually do want to have the symbol?

4. Should this be a separate macro, "enum-case"?  But standard
   case already handles booleans and numbers and symbols, so why
   should enums require a separate facility?

We would want to do the checking at compile time to catch spelling
errors or other mistakes such as (case d ((JANUARY) ...) ...), so
while altering %case-match like this works (kind of), it isn't
the Right Thing:

> (define-syntax %case-match
>   (syntax-rules ()
>     ((%case-match key datum)
>      (if (*:isEnum key:class)
>          (eq? key (key:class:valueOf (quote datum)))
>          (eqv? key (quote datum))))
>     ((%case-match key datum more ...)
>      (or (if (*:isEnum key:class)
>              (eq? key (key:class:valueOf (quote datum)))
>              (eqv? key (quote datum)))
>          (%case-match key more ...)))))

(Besides, it's horribly inefficient, calling Class#isEnum over and
over again.)


Thoughts?  Once we decide upon the right semantics, this should be
a fairly small task to complete.  Any potential GSoC students want
to give it a try?

--
Jamison Hope
The PTR Group
www.theptrgroup.com



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-03-06  6:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-06  6:13 enums and case Jamison Hope

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).