Arc Forumnew | comments | leaders | submitlogin
Multiple cases in 'case branches
3 points by twilightsentry 5507 days ago | 13 comments
In CL, you can list multiple cases for a 'case branch by enclosing them in a list:

  >(case 5
     ((1 3 5) 'odd)
     ((2 4 6) 'even)
     (t       '?))
  ODD
Unfortunately, this doesn't work in Arc.

  arc>(def f (x)
        (case x
          (1 3 5) 'odd
          (2 4 6) 'even
                  '?)))
  #<procedure: f>
  arc>(f 5)
  ?
  arc>(f '(1 3 5))
  odd
A minor change in caselet fixes this, but before I push that to anarki, I want to make sure no one expects/depends on the current behavior.

  (mac caselet (var expr . args)
    ...
  -   `(if (is ,var ',(car args))
  +   `(if (in ,var ,@(map [list 'quote _]
  +                        (mklist (car args))))
    ...)


2 points by rntz 5506 days ago | link

I very much expect the current behavior. Can't really say why, it just seems natural to me that a list as a case means "pattern-match", not "any one of these". Also it would break compatibility with pg's arc. Adding a new macro, say, 'mcase ("multi-case") or 'orcase, would be totally fine though.

-----

1 point by akkartik 5506 days ago | link

Or add a sym to the case itself.

    (case x (in 1 3 5) 'odd ..)
Harder to implement, though.

-----

1 point by aw 5506 days ago | link

That's a clever idea, I think I probably would use a macro that let me check a value against a series of expressions (perhaps using some form of currying). I don't think I'd call it "case" though :-)

-----

1 point by akkartik 5505 days ago | link

How about allowing cases to be functions?

  (case x
    [in _ '(1 3 5)] 'odd
    ..)

-----

1 point by twilightsentry 5505 days ago | link

I've got a macro like that, which I call 'test. The problem with combining that and 'case is distinguishing functions and constants before the cases are eval'ed.

  (mac testlet (var expr . args)
    (letf ex (args)
           (if cdr.args
               `(if (,car.args ,var) ,cadr.args
                    ,(args cddr.args))
               car.xs)
      `(let ,var ,expr ,(ex args))))
Anyway, I'll probably just define 'casein as aw and rntz suggested.

-----

1 point by aw 5506 days ago | link

'casein occurs to me, reminiscent of 'in

-----

1 point by aw 5507 days ago | link

I sometimes use lists as compound keys, so I need a version of case that lets me compare against literal lists (whether it gets called "case" as it is in Arc now or something else).

However I don't use Anarki, so it doesn't matter to me whether you push it there.

-----

2 points by rocketnia 5506 days ago | link

I think you can still match against literal lists without much trouble.

  (case compound-key
    ((a certain key))   ...
    ((some other key))  ...
                        ...)
It's just that the "option list" parentheses on the outside of the case are optional when it's a single non-cons option.

-----

1 point by rntz 5506 days ago | link

It may not matter to you, but IMO it matters to the community (what little of it there is) that anarki and arc not break compatibility in such a simple case as this.

-----

1 point by lg 5504 days ago | link

I think it'd be cool if a case-clause could be a fn, and if it is, and calling it on the case-arg returns true, then it matches. but maybe there should be a special sort of case for this called fncase or something.

-----

1 point by rocketnia 5504 days ago | link

I like that idea, and it would be just as minor a change.

  - `(if (is ,var ',(car args))
  + `(if ((testify ,(car args)) ,var)
A difference is that in order to test against a literal value, you have to quote it. It's closer to Anarki's 'switch that way.

Oh, and akkartik and twilightsentry had just mentioned this idea elsewhere in this thread. :-p

-----

1 point by akkartik 5506 days ago | link

Is mklist your own function? Does it work with strings?

-----

1 point by twilightsentry 5505 days ago | link

D'oh. Yeah; I have it defined, and I hadn't tried reloading arc before I posted it. _On_Lisp_ has a CL version; in Arc I do:

  (def mklist (xs)
    (check xs alist (list xs)))

-----