Re: if-expression and variables

"William Sit" <[email protected]> Wed, 04 May 2011 22:59:42 -0400
Newsgroups gmane.comp.mathematics.axiom.general
Message-ID <[email protected]>
Dear Bill:

Thanks for answer the questions. I agree that we are 
drifting away from the original question -- which is a 
constant curse on Axiom.

Here is how I would combine "interpret test1(x0)" with 
"expr test1(x0)". Note that for test2, the target domain 
is Any (which is sort of a Union, and better than 
InputForm). Note that the source domain varies as the 
input argument of test2.

(24) -> test2(x0)==(integer? x0 => interpret test1(x0); 
expr test1(x0))
    Compiled code for test2 has been cleared.
    1 old definition(s) deleted for function or rule test2
                                                            
        Type: Void
(25) -> test2(y)
    Compiling function test2 with type Variable y -> Any

    (25)
    if y < 10
      then 2y
             2
      else 5y
                                                            
  Type: OutputForm
(26) -> test2(3)
    Loading 
j:/OpenAxiom/axiom014/mnt/windows/algebra/INTRET.o for
       package IntegerRetractions
    Compiling function test1 with type PositiveInteger -> 
InputForm
    Compiling function test2 with type PositiveInteger -> 
Any

    (26)  6
                                                         Type: 
PositiveInteger
(27) -> test2(y+1)
    Compiling function test1 with type Polynomial Integer 
-> InputForm
    Compiling function test2 with type Polynomial Integer 
-> Any

    (27)
    if y + 1 < 10
      then 2(y + 1)
                   2
      else 5(y + 1)

And to illustrate the possible problems with a "global 
substitution", I try a different definition for ex:

(13) -> ex:InputForm := ncParseFromString("if x<10 then 
x:=x+1 else x:=x-1")$Lisp; expr ex

    (13)
    if x < 10
      then x := x + 1
      else x := x - 1
                                                            
  Type: OutputForm
(14) -> destruct ex

    (14)  [IF,(< x 10),(LET x (+ x 1)),(LET x (- x 1))]
                                                          Type: 
List InputForm

(18) -> test1(x0)==sub(ex,x,x0)
                                                            
        Type: Void
(19) -> expr test1(y)
    Compiling function sub with type 
(InputForm,Symbol,InputForm) ->
       InputForm
    Compiling function test1 with type Variable y -> 
InputForm

    (19)
    if y < 10
      then y := y + 1
      else y := y - 1
                                                            
  Type: OutputForm

(20) -> interpret test1(3)
    Compiling function test1 with type PositiveInteger -> 
InputForm

    3 is not valid on the left-hand side of an assignment 
expression.
(20) -> expr test1(x+1)
    Compiling function test1 with type Polynomial Integer 
-> InputForm

    (20)
    if x + 1 < 10
      then x + 1 := x + 1 + 1
      else x + 1 := x + 1 - 1
                                                            
  Type: OutputForm
Even though the output of (20) is what you "expect", it 
should have been flagged just like when x0 = 3. Why does 
Axiom think it is okay to put x+1 on the left hand side of 
an assign? (If the right hand side is more complicated, I 
don't suppose we expect the system to actually solve for 
x; and even if it does, it would not know which root to 
take for say a quadratic.)

The problem is not because I use an assignment, but 
because an InputForm is supposedly free to do any 
computation, including a conditional increment/decrement 
on the input. Another problem, when dealing with the 
original question, as amended, is there is no "integrate" 
operation on InputForm.

Here's an unexpected turn out (I should have parenthesized 
the object of "if"): the system should have flagged an 
input or syntax error if it actually interpreted the ; to 
end the if-clause. Is NIL or the () regarded as an error 
indication in Lisp or InputForm?

                                                            
   Type: InputForm
(11) -> ex:InputForm := ncParseFromString("if x<10 then 
x:=x+1;2*x else 5*x^2")$
Lisp; expr ex

    (11)  NIL
                                                            
  Type: OutputForm
(12) -> flatten ex

    (12)  ()
                                                            
   Type: InputForm

William



On Tue, 3 May 2011 13:32:55 -0400
  Bill Page <[email protected]> wrote:
> William,
> 
> As usual this thread is drifting away from the original 
>question but I
> still think it is interesting from a more general point 
>of view. It
> seems to me that InputForm is an often under-appreciated 
>and
> under-used domain in Axiom.
> 
> On Tue, May 3, 2011 at 3:04 AM, you wrote:
>> Dear Bill:
>>
>> You are right. I should not have declare "It is not 
>>possible" (even with a
>> qualifier) since one can program around the 
>>difficulties.
> 
> True.  The question is: how much programming is required 
>versus how
> much one can do "off-the-shelf". With any system that is 
>designed to
> be extended like Axiom, this is always a moving target. 
>As user
> requirements are identified and programming solutions 
>found, these
> solutions should become candidates for inclusion in the 
>standard
> library.
> 
>> However, what you did essentially defines two different 
>>piecewise function, one
>> for numeric and one for symbolic, by using "interpret" 
>>and "expr".
> 
> There is only one definition of 'test1'
> 
> (3) -> ex:InputForm := parse("if x<10 then 2*x else 
>5*x^2");
> (4) -> test1(x0)==sub(ex, x,x0)
> 
> In that sense there is only one "function". (I think 
>this definition
> is more properly called a "mode".) This highlights a 
>significant
> difference between function definitions in the Axiom 
>interpreter
> versus the library compiler. Untyped modes will (usually 
>but not
> necessarily) be instantiated into fully typed functions. 
> Warning
> messages like:
> 
>  Compiling function test1 with type PositiveInteger -> 
>InputForm
> 
> are intend to inform the user that this "function" 
>resulted in one of
> possibly several different fully typed compiled 
>functions.
> 
>> If you use "interpret test1(y)" you would still get the 
>>wrong answer, and
> 
> Yes. It is the "wrong" answer in as much as it probably 
>differs wildly
> from what a beginning user would expect. That is way 
>other variants of
> Axiom choose to eliminate "<" to denote the default 
>ordering of
> polynomials. In these other systems "interpret test1(y)" 
>would not be
> evaluated since these is preferable over an apparently 
>wrong result.
> 
>> similarly, if you use "expr test1(3)", then you would 
>>not have the result
>> evaluated.
> 
> That is true. 'expr' is only a matter of "pretty 
>printing" and
> unevaluated expression (InputForm). 'interpret' on the 
>other hand
> applies all of Axiom's built-in and library-dependent 
>rules for
> evaluation.
> 
>> Of course, you can combine the two cases and again 
>>distinguish them
>> by testing if the input is a symbolic expression or 
>>numeric (keeping it
>> unevaluated in the first case, and evaluating in the 
>>second).
>>
> 
> I suppose you are suggesting a function that in Axiom 
>parlance might
> be called "interpretIfCan". It is not obvious to me how 
>one could
> "test if the input is a symbolic expression". In a deep 
>sense
> everything in Axiom (in fact in any computer system) is 
>"symbolic".
>From the point of view of Axiom's run-time system (i.e. 
>Lisp) some
> things are considered "atomic" such as symbols, 
>integers, etc. But
> 
> (5) -> sub(ex,x,3)
>   Compiling function sub with type 
>(InputForm,Symbol,InputForm) ->
>      InputForm
> 
>   (5)  (IF (< 3 10) (* 2 3) (* 5 (^ 3 2)))
>                                                           
>   Type: InputForm
> 
> is not atomic in this sense, yet it can be evaluated by 
>'interpret' to
> something which is:
> 
> (6) -> interpret(sub(ex,x,3))::InputForm
> 
>   (6)  6
>                                                           
>   Type: InputForm
> 
> It would certainly be possible in principle to implement 
>a function such as:
> 
>   evaluate: InputForm -> InputForm
> 
> which attempts to 'interpret' its input and if possible 
>returns the
> InputForm derived from the corresponding value, 
>otherwise it would
> return the input unchanged.
> 
>> Your routine sub is, I believe, not full proof. If x 
>>were modified inside f,
>> would a static substitution of all occurrences of x by y 
>>work? (isn't y
>> bound and x is not?). Or if there were a local variable 
>>x that temporarily
>> hides the scope of the outer x. By using f:InputForm, 
>>the dummy argument
>> for f is no longer a dummy; as a function, f is 
>>independent of the literal
>> used for its argument. Of course, we can identify the 
>>argument of f in the
>> sub routine without passing it as an argument for sub.
>>
> 
> I think 'sub' does exactly and only what I claimed.
> 
> (2) -> sub(f:InputForm, x:Symbol, y:InputForm):InputForm 
>== ( _;f); _
>          atom? f => (symbol? f => (symbol f = x => 
>y;f);f); _
>            [sub(g,x,y) for g in destruct f]::InputForm)
> 
> It finds all occurrences of the symbol (passed as formal 
>parameter x)
> in the InputForm (passed by parameter f). It inserts an 
>InputForm
> (passed as parameter y) into f where x occurs in f. The 
>result is
> still a value of type InputForm which may or may not be 
>able to be
> evaluated by 'interpret'. Nothing is "bound" in f. Also 
>there is no
> concept of "local variable" because the InputForm is not 
>yet evaluated
> in any way. The declaration "f:InputForm" is just like 
>any other
> similar declaration in an Axiom function. It says only 
>that the value
> passed by formal parameter f must be of type InputForm. 
>f is not a
> function, it just stands for some value of type 
>InputForm.
> 
>> I am sure that in lisp, you can do anything. (Tim: would 
>>you rise up to the
>> challenge?) I believe Stefan's question is whether it 
>>can be done
>> "intuitively" (even though he did not say so 
>>explicitly).
> 
> As you can see InputForm is only slightly removed from 
>Lisp. The
> underlying representation of InputForm is exactly a Lisp 
>s-expression
> of a particular form.
> 
>> Mathematica is able to provide that, because neither the 
>>input nor the output
>> is restricted by its type.
> 
> I think that is not very accurate. It might be better to 
>say that in
> Mathematica everything is of only one type: symbolic. In 
>Axiom terms
> this would be like making everything an InputForm. This 
>is not as
> "bad" or as "stupid" as it might sound. But it is not 
>very "algebraic"
> in the sense in which I used the word earlier.
> 
>> In Axiom, maybe we can do the same with a Union like
>> Union(Integer, InputForm).
> 
> I am not sure how Union would help in this case.
> 
>> ...
> 
> Regards,
> Bill Page.

William Sit, Professor Emeritus
Mathematics, City College of New York
Office: R6/291D Tel: 212-650-5179
Home Page: http://scisun.sci.ccny.cuny.edu/~wyscc/