Hi, This morning I applied a patch to OpenAxiom (trunk) that supports pattern matching with retractable domains. I showed an example with the Syntax domain. I was asked whether there other places where the extension is relevant. The answer is emphatically yes. Virtually all the places where we say
retractIfCan(x)@Union(T,"failed") are the low handing fruits. (More elaborated, advanced examples will follow later). As an illustration, take the package ToolsForSign. It contains the following definition for `sign'. if R has RetractableTo Fraction Integer then sign r == (u := retractIfCan(r)@Union(Fraction Integer, "failed")) case Fraction(Integer) => sign(u::Fraction Integer) nonQsign r else if R has RetractableTo Integer then sign r == (u := retractIfCan(r)@Union(Integer, "failed")) case "failed" => "failed" sign(u::Integer) -- ... This the usual form of dealing with retractIfCan(), and I think it looks gastly (well, my opinion). For this code, we currently generate the following two Lisp functions (DEFUN |TOOLSIGN;sign;RU;3| (|r| $) (PROG (|u| #0=#:G1415) (RETURN (COND ((QEQCAR (LETT |u| (SPADCALL |r| (|getShellEntry| $ 17)) |TOOLSIGN;sign;RU;3|) 0) (CONS 0 (SPADCALL (PROG2 (LETT #0# |u| |TOOLSIGN;sign;RU;3|) (QCDR #0#) (|check-union| (QEQCAR #0# 0) (|Fraction| (|Integer|)) #0#)) (|getShellEntry| $ 18)))) ('T (SPADCALL |r| (|getShellEntry| $ 14))))))) (DEFUN |TOOLSIGN;sign;RU;4| (|r| $) (PROG (|u|) (RETURN (SEQ (LETT |u| (SPADCALL |r| (|getShellEntry| $ 20)) |TOOLSIGN;sign;RU;4|) (EXIT (COND ((QEQCAR |u| 1) (CONS 1 "failed")) ('T (CONS 0 (SPADCALL (QCDR |u|) (|getShellEntry| $ 21)))))))))) With the new case pattern construcy, we can rewrite sign() as if R has RetractableTo Fraction Integer then sign r == case r is [EMAIL PROTECTED](Integer) => sign u otherwise => nonQsign r else if R has RetractableTo Integer then sign r == case r is [EMAIL PROTECTED] => sign u otherwise => "failed" -- ... for which we generate (DEFUN |TOOLSIGN;sign;RU;3| (|r| $) (PROG (#0=#:G1420) (RETURN (LET ((#1=#:G1413 |r|)) (COND ((PROGN (LETT #0# (SPADCALL #1# (|getShellEntry| $ 17)) |TOOLSIGN;sign;RU;3|) (QEQCAR #0# 0)) (LET ((|u| (QCDR #0#))) (CONS 0 (SPADCALL |u| (|getShellEntry| $ 18))))) (T (SPADCALL |r| (|getShellEntry| $ 14)))))))) (DEFUN |TOOLSIGN;sign;RU;4| (|r| $) (PROG (#0=#:G1426) (RETURN (LET ((#1=#:G1425 |r|)) (COND ((PROGN (LETT #0# (SPADCALL #1# (|getShellEntry| $ 20)) |TOOLSIGN;sign;RU;4|) (QEQCAR #0# 0)) (LET ((|u| (QCDR #0#))) (CONS 0 (SPADCALL |u| (|getShellEntry| $ 21))))) (T (CONS 1 "failed"))))))) functionally equivalent to what we had before, but more efficient. ----- With the case pattern, we use x @ T to do `retractIfCan' match, while x : T is used for recovering a typed value from object of type Any. My reason for that choice of syntax is that `x @ T' indicates a form of restriction to a type T (when we think of narrowing the type of an expression), while `x : T' suggests type acquired at declaration point which is exactly what is packaged into an object of type Any. I have been asked whether I could switch the notation, e.g. using x : T for `retractIfCan' matching, and x @ T for type recovery. Technically, it is just a matter of switcing a token. But, I would like to here from people who prefer one way or another. -- Gaby ------------------------------------------------------------------------------ SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada. The future of the web can't happen without you. Join us at MIX09 to help pave the way to the Next Web now. Learn more and register at http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/ _______________________________________________ open-axiom-devel mailing list open-axiom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/open-axiom-devel