Semantics of "case"



I think the semantics for case can be taken from the lisp case definition.

I think the answers are those interspersed below.


Stavros Macrakis wrote:

>There has been a lot of discussion about the syntax of a Maxima case
>statement.  Let's think about the semantics for a second.  There are
>several issues.
>
>==Kind of comparison==
>
>One is what kind of comparison to use.  Is it syntactic equality (=)
>or semantic equality (equal)?
>

syntactic.

>  In the case of operators (the use case
>that has been discussed the most), they come to the same thing.  But
>how about:
>
>         assume(equal(x,1))$
>         case  x of
>             0 => und,
>             1 => und,
>             1/(x*(x-1))
>          endcase
>
>==Evaluation of cases==
>
>Are the alternatives evaluated, or (implicitly) quoted? 
>
implicitly quoted.

> Probably
>implicitly quoted -- though as a general rule I think implicit quoting
>gets you into trouble, it seems to make sense here. Any arguments the
>other way?
>
>==Result if not handled==
>
>
>What if none of the clauses are true, and there is no otherwise
>clause?  In "carefree" languages (to invent a term) like Lisp, the
>result is usually to do nothing, or return nil.  In "cautious"
>languages (like Ada or I think ML), this is an error. (Let's not even
>talk about case/switch semantics in "careless" languages like C.)
>
the implementation I provided returns false.  Requiring an "otherwise" 
clause could be done as a suggestion to the programmer.
(What a cautious programmer would do).

>
>I perfer the cautious approach because it makes it easy to write
>first-draft code that instead of failing silently on cases that it
>doesn't handle, lets you know there's a problem, e.g.
>
>inopx(ex):=block([inflag:true],if atom(expr) then false else op(ex))$
>
>       case opx(ex) of
>              false => ex
>              "+" => ...
>              "*" => ...
>              "^" => ...
>        endcase
>
>This will work fine for algebraic expressions, but will just return
>false for sin(x) or a[2], which is almost never the right result.
>
>But given the disagreements in other cases about silent failure vs.
>error signalling, I am not sure we will agree on this....
>
>==Multiple matches==
>
>What about the (common) case where many alteratives are wanted in a branch, e.g.
>
>          case op(x) of
>             ["+", "-"] => ...
>
>or
>
>           case sign(x) of
>              [pos, pz, zero] => f(x),
>              [neg, nz, zero] => -f(-x),
>              [pnz, pn] => analyze(x)
>           end case
>
>This sort of syntax is fine, unless you also want to allow compound
>objects (like lists and sets) in the selectors, e.g.
>
>            case (list) of
>               [] => ...          /* handle empty list */
>               [0] => ...       /* special case */
>               ...
>

The solution here is to use this:
             case ()  of
                  [[]] =>    ..... matches the empty list only
                  [[0]] =>  .....  matches the list [0] only

>
>==Order of testing==
>
>What if more than one branch can match?  Do we evaluate them in order? 
>


>Consider
>
>         assume(equal(x,a),equal(x,b))$
>         case x of
>            a => ...
>            b => ...
>
>or the sign(x) example above (where zero is in more than one clause).
>
>The natural programming interpretation would be to evaluate the
>clauses sequentially, though the natural mathematical interpretation
>might be to consider the order irrelevant, and assume that if two
>cases overlap, it doesn't matter which one you choose.  This also
>allows the implementation more freedom.  It may also make it easier to
>treat unevaluated case statements (though more on that some other
>time).
>  
>
Yes, but see guarded conditions programming where the order is 
(effectively) random:  the program must operate correctly regardless of 
the order.


RJF