|
|
last edited 17 years ago |
1 | ||
Editor:
Time: 2007/11/18 17:32:01 GMT-8 |
||
Note: Untag Union is not supported in Aldor |
changed: - Based on the Aldor presentation by Stephen Watt: http://www.aldor.org/docs/reports/ukqcd-2000/intro1-ukqcd00.pdf and http://www.aldor.org/docs/HTML/chap2.html First Exampes I Doubling integers \begin{aldor} #include "axiom" double(n: Integer): Integer == n + n \end{aldor} \begin{axiom} double(3) \end{axiom} The first program is one which doubles integers. This program illustrates a number of things: 1. The Aldor language is itself almost empty. This allows libraries to define their own environments all the way down to such basic questions such as what an integer ought to be. Therefore, almost all programs begin with an "#include" line to establish a basic context. The "#include" line in this example provides a context in which Integer has a specific meaning, provided by the stand-alone Aldor library. 2. The symbol "==" indicates a definition --- in this case a definition of a function named "double". 3. The function has two declarations, using the notation ": Integer". Names indicating values (variables, parameters, etc) may each contain values of only a specific type. The first declaration in this program states that the parameter n must be an Integer. The second asserts that the result of the function will also be an Integer. (The type of the function itself is represented as "Integer -> Integer"; a name and type together are called a signature, as in "double: Integer -> Integer".) 4. The declarations cause the exports from the type "Integer" to be visible. Typically, a type exports special values (such as 0 and 1) and functions on its members. In this example, the name "+" has a meaning as an exported function from "Integer". 5. The body of the function "double" is the expression "n + n". The value of this expression is returned as the result of the function. It is not necessary to use an explicit "return" statement, although it is permitted. This turns out to be very convenient when many functions have very short definitions, as is normal with abstract data types or object-oriented programs. First Exampes II Square roots \begin{aldor} #include "axiom" -- Compute a square root by six steps of Newton's method. -- This gives 17 correct digits for numbers between 1 and 10. DF ==> DoubleFloat; miniSqrt(x: DF): DF == { r := x; r := (r*r + x)/(2.0*r); r := (r*r + x)/(2.0*r); r := (r*r + x)/(2.0*r); r := (r*r + x)/(2.0*r); r := (r*r + x)/(2.0*r); r := (r*r + x)/(2.0*r); r } \end{aldor} \begin{axiom} miniSqrt(10.0) \end{axiom} Our second program illustrates several more aspects of the language: 1. Comments begin with two hyphens '--' and continue to the end of the line. 2. Abbreviations ('macros') may be defined using '==>'. The line DF ==> DoubleFloat; causes 'DF' to be replaced by 'DoubleFloat' wherever it is used. 3. A function's body may be a compound expression. In this example the body of the function is a sequence consisting of eight expressions separated by semicolons and grouped together by braces. These expressions are evaluated in the order given. The value of the last expression is the value of the sequence, and hence is the value of the function. 4. The semicolons separate expressions. It is permitted, but not necessary, to have one after the last expression in a sequence. 5. Variables may be assigned values using ':='. 6. The variable 'r' is local to the function 'miniSqrt': it will not be seen from outside it. Variables may be made local to a function by a 'local' declaration or, as in this case, implicitly, by assignment. 7. In this function the variable 'r' contains double precision floating point values. Since this may be inferred from the program, it is not necessary to provide a type declaration. First Exampes III A loop and output \begin{aldor} #include "axiom" factorial(n: Integer): Integer == { p := 1; for i in 1..n repeat p := p * i; p } \end{aldor} \begin{axiom} output("factorial 10 = ", factorial 10) \end{axiom} The third program has a loop and produces some output. Things to notice about this program are: 1. This example has expressions which occur at the top-level, outside any function definition. This illustrates how the entire source program is treated as an expression sequence, which may (or may not) contain definitions among other things. This entire source program is treated in the same way as a compound expression forming the body of a function: it is evaluated from top to bottom, performing definitions, assignments and function calls along the way. 2. As we saw in a previous example, the declarations ': Integer' suffice to make the exports from Integer visible within the factorial function. This gives meaning to '1', '*' and '..'. These declarations do not, however, cause the the exports from Integer to be visible at the top-level of the file, outside the function factorial. This conservative behaviour turns out to be quite desirable when writing large programs, since adding a new function to a working program will not pollute the name space of the program into which it is inserted. 3. The last line of the example produces some output. Output is in doen by Axiom not Aldor. 4. The last line is simple but refers to many things. We shall say exactly where each of them comes from: * The name 'output' is a operator. * The expression '"factorial 10 ="' is a String constant. * We have already seen where 'factorial' and '10' come from. 5. Let us look more closely at the use of the factorial function in the last line: 'factorial 10'. No parentheses are needed here because the function has only a single argument. If the function took two arguments, e.g. '5, 5', or if the argument were a more complicated expression, e.g. '5+5', then parentheses would be required to force the desired grouping. 6. A word of caution is necessary here: the manner of output is deefined by the particular library, not the language. The form of output in this example is approprate when using '#include "aldor"' but will not work when using '#include "axiom"'. (In the AXIOM library, output is done by coercion to type OutputForm). First Examples IV This one is not compatible with Axiom \begin{aldor} #include "axiom" MiniList(S: BasicType): LinearAggregate(S) == add { Rep == Union(nil: Pointer, rec: Record(first: S, rest: %)); import from Rep, SingleInteger; local cons (s:S,l:%):% == per(union [s, l]); local first(l: %): S == rep(l).rec.first; local rest (l: %): % == rep(l).rec.rest; empty (): % == per(union nil); empty?(l: %):Boolean == rep(l) case nil; sample: % == empty(); [t: Tuple S]: % == { l := empty(); for i in length t..1 by -1 repeat l := cons(element(t, i), l); l } [g: Generator S]: % == { r := empty(); for s in g repeat r := cons(s, r); l := empty(); for s in r repeat l := cons(s, l); l } generator(l: %): Generator S == generate { while not empty? l repeat { yield first l; l := rest l } } apply(l: %, i: SingleInteger): S == { while not empty? l and i > 1 repeat (l, i) := (rest l, i-1); empty? l or i ~= 1 => error "No such element"; first l } (l1: %) = (l2: %): Boolean == { while not empty? l1 and not empty? l2 repeat { if first l1 ~= first l2 then return false; (l1, l2) := (rest l1, rest l2) } empty? l1 and empty? l2 } (out: TextWriter) << (l: %): TextWriter == { empty? l => out << "[]"; out << "[" << first l; for s in rest l repeat out << ", " << s; out << "]" } } \end{aldor} Click above to see errors. A few points will help in understanding this program: 1. The first thing to note is that the new type constructor is defined as a function MiniList whose body is an 'add' expression, itself containing several function definitions. It is these internal functions of an 'add' function which provide the means to manipulate values belonging to the resulting types (such as MiniList(Integer) in this case). 2. This program uses various names we have not seen before, for example 'Record', 'Pointer', 'element', etc. Some of these, such as 'Pointer', are made visible by the #include line, while others, such as 'element', are made visible by declaring values to belong to particular types. The names which have meanings in 'aldor' are detailed in chapter 25 and chapter 26. 3. While BasicType and LinearAggregate(S) are both type categories, the types in these categories have different characteristics. The difference lies in what exports their types must provide: * Every type which is a BasicType must supply an equality test ('='), an output function ('<<'), and a few other operations. Since S is declared to be a BasicType, the implementation of MiniList can use the '=' and '<<' from S in the definitions of MiniList's own operations. * Every type which is a LinearAggregate(S) must supply several other operations, such as a constructor function called 'bracket' to form new values, a test function called 'empty?', and so on. MiniList(S) provides a LinearAggregate(S), so it must supply all these operations. Users of MiniList(S) will be able to rely on these operations being available. 4. The first line of the 'add' expression defines a type 'Rep' (specific to 'MiniList'). This is how values of the type being defined are really represented. The fact that they are represented this way is not visible outside the 'add' expression. 5. Several of the functions defined in the body have parameters or results declared to be of type '%'. In any 'add' expression, the name '%' refers to the type under construction. For now, '%' can be thought of as a shorthand for 'MiniList(S)'. 6. There are several uses of the operations 'per' and 'rep' in this program. These are conversions which allow a data value to be regarded in is public guise, as a member of '%', or by its private representation as a member of 'Rep'. * 'rep: % -> Rep' * 'per: Rep -> %' These can be remembered by types they produce: 'rep' produces a value in Rep, the representation, and 'per' produces a value in %, percent. 7. Some of the function definitions are preceded by the word 'local'. This means they will be private to the 'add', and consequently will not be available to users of MiniList. 8. Some of the definitions have left-hand sides with an unusual syntax For example:: [t: Tuple S]: % == ... [g: Generator S]: % == ... (l1: %) = (l2: %): Boolean == ... (out: TextWriter) << (l: %): TextWriter == ... In general, the left-hand sides of function definitions in Aldor look like function calls with added type declarations. Some names have infix syntax, for instance, '=' and '<<' above. These are nevertheless just names and, aside from the grouping, behave in exactly the same way as other names. The special syntactic properties of names may be avoided by enclosing them in parentheses. Other special syntactic forms are really just a nice way to write certain function calls. The form '[a,b,c]' is competely equivalent to the call 'bracket(a,b,c)'. With this explanation, we see that the defining forms above are equivalent to the following, more orthodox forms:: bracket(t: Tuple S): % == ... bracket(g: Generator S): % == ... (=) (l1: %, l2: %): Boolean == ... (<<)(out: TextWriter, l: %): TextWriter == ... The use of the type 'Generator S' will be explained in chapter 9. 9. The function 'generator' illustrates how a type can define its own traversal method, which allows the new type to decide how its component values should be obtained, say for use in a loop. Such a definition utilises the function 'generate', in conjuction with 'yield': each time a 'yield' is encountered, 'generate' makes the given value available to the caller and then suspends itself. This technique is described more fully in section 9.3. When the next value is needed, the generator resumes where it left off. Since MiniList(S) provides a 'generator' function for MiniLists, it is possible to use them in a 'for' loop. For example, in the output function '<<', we see the line:: for s in rest l repeat out << ", " << s; Here 'rest l' is traversed by the generator to obtain values for 's'. Questions 1 How to implement type 'Pointer' in Axiom? 2 How is the Aldor type Generate related to Axiom's Stream? From billpage Mon Jul 9 12:26:31 -0500 2007 From: billpage Date: Mon, 09 Jul 2007 12:26:31 -0500 Subject: untagged Union in Aldor Message-ID: <20070709122631-0500@wiki.axiom-developer.org> \begin{aldor} #include "axiom" macro I == Integer; main():String == { import from I, Float; U == Union(Integer, Float); import from U; i: I := 2; s: Float := 1.5; ui: U := union i; us: U := union s; u: U := if odd? random(10) then ui else us; if u case Integer$'Integer' then { "Integer"; } else { "Float"; } } \end{aldor} From anonymous Tue Jul 10 03:16:32 -0500 2007 From: anonymous Date: Tue, 10 Jul 2007 03:16:32 -0500 Subject: Untag Union is not supported in Aldor Message-ID: <20070710031632-0500@wiki.axiom-developer.org> http://www.aldor.org/docs/HTML/chap18.html Section 18.6: Untagged unions are not supported by Aldor, thus all unions must be converted to tagged unions. This means that Union(Integer, Float) needs to become something like AXIOMTypeUnion(i:Integer, f:Float). The case statement requires the tag as its first argument, case thus you write x case i instead of x case Integer. Converting to and from tagged unions is essentially the same as with AXIOMTypeRecord types. To create a union value from one of its branches, you wrap the value in square brackets, thus [3.3] converts the float value ``3.3'' to a union value. Similarly, if x has type AXIOMTypeUnion(i:Integer, f:Float), x.i converts x to an Integer value taking a runtime error if x was in the other branch of the union (for more information on unions in Aldor see part II). Partial functions in old AXIOM were often declared as returning AXIOMTypeUnion(%, "failed"); by convention this is represented in Aldor as AXIOMTypeUnion(value1:%, failed: 'failed') (recall that 'failed' is syntactic shorthand for AXIOMTypeEnumeration(failed)).
Based on the Aldor presentation by Stephen Watt: http://www.aldor.org/docs/reports/ukqcd-2000/intro1-ukqcd00.pdf and http://www.aldor.org/docs/HTML/chap2.html
Doubling integers
(1) -> <aldor> #include "axiom" double(n: Integer): Integer == n + n</aldor>
Compiling FriCAS source code from file /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/8999780659057009231-25px001.as using Aldor compiler and options -O -Fasy -Fao -Flsp -lfricas -Mno-ALDOR_W_WillObsolete -DFriCAS -Y $FRICAS/algebra -I $FRICAS/algebra Use the system command )set compiler args to change these options. "/var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/8999780659057009231-25px001.as",line 1: #include "axiom" ^ [L1 C1] #1 (Error) Could not open file `axiom'.
The )library system command was not called after compilation.
double(3)
There are no exposed library operations named double but there is one unexposed operation with that name. Use HyperDoc Browse or issue )display op double to learn more about the available operation.
Cannot find a definition or applicable library operation named double with argument type(s) PositiveInteger
Perhaps you should use "@" to indicate the required return type,or "$" to specify which version of the function you need.
The first program is one which doubles integers. This program illustrates a number of things:
Square roots
#include "axiom"
Compiling FriCAS source code from file /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/3174503116170322985-25px003.as using Aldor compiler and options -O -Fasy -Fao -Flsp -lfricas -Mno-ALDOR_W_WillObsolete -DFriCAS -Y $FRICAS/algebra -I $FRICAS/algebra Use the system command )set compiler args to change these options. "/var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/3174503116170322985-25px003.as",line 1: #include "axiom" ^ [L1 C1] #1 (Error) Could not open file `axiom'.
The )library system command was not called after compilation.
miniSqrt(10.0)
There are no library operations named miniSqrt Use HyperDoc Browse or issue )what op miniSqrt to learn if there is any operation containing " miniSqrt " in its name.
Cannot find a definition or applicable library operation named miniSqrt with argument type(s) Float
Perhaps you should use "@" to indicate the required return type,or "$" to specify which version of the function you need.
Our second program illustrates several more aspects of the language:
--
and continue to the end of the line.macros
) may be defined using ==>
. The lineDF ==> DoubleFloat?;
causes DF
to be replaced by DoubleFloat
wherever it is used.
:=
.r
is local to the function 'miniSqrt': it will not be seen from outside it. Variables may be made local to a function by a local
declaration or, as in this case, implicitly, by assignment.r
contains double precision floating point values. Since this may be inferred from the program, it is not necessary to provide a type declaration.A loop and output
#include "axiom" factorial(n: Integer): Integer == { p := 1; for i in 1..n repeat p := p * i; p }
Compiling FriCAS source code from file /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/8840088320957572233-25px005.as using Aldor compiler and options -O -Fasy -Fao -Flsp -lfricas -Mno-ALDOR_W_WillObsolete -DFriCAS -Y $FRICAS/algebra -I $FRICAS/algebra Use the system command )set compiler args to change these options. "/var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/8840088320957572233-25px005.as",line 1: #include "axiom" ^ [L1 C1] #1 (Error) Could not open file `axiom'.
The )library system command was not called after compilation.
output("factorial 10 = ",factorial 10)
factorial 10 = 3628800
The third program has a loop and produces some output. Things to notice about this program are:
: Integer
suffice to make the exports from Integer visible within the factorial function. This gives meaning to 1
, '* and
..'.These declarations do not, however, cause the the exports from Integer to be visible at the top-level of the file, outside the function factorial. This conservative behaviour turns out to be quite desirable when writing large programs, since adding a new function to a working program will not pollute the name space of the program into which it is inserted.
output
is a operator."factorial 10 ="
is a String constant.factorial
and 10
come from.factorial 10
. No parentheses are needed here because the function has only a single argument. If the function took two arguments, e.g. 5, 5
, or if the argument were a more complicated expression, e.g. 5+5
, then parentheses would be required to force the desired grouping.#include "aldor"
but will not work when using #include "axiom"
. (In the AXIOM library, output is done by coercion to type OutputForm?). This one is not compatible with Axiom
#include "axiom"
MiniList(S: BasicType): LinearAggregate(S) == add { Rep == Union(nil: Pointer,rec: Record(first: S, rest: %));
import from Rep,SingleInteger;
local cons (s:S,l:%):% == per(union [s, l]); local first(l: %): S == rep(l).rec.first; local rest (l: %): % == rep(l).rec.rest;
empty (): % == per(union nil); empty?(l: %):Boolean == rep(l) case nil; sample: % == empty();
[t: Tuple S]: % == { l := empty(); for i in length t..1 by -1 repeat l := cons(element(t,i), l); l } [g: Generator S]: % == { r := empty(); for s in g repeat r := cons(s, r); l := empty(); for s in r repeat l := cons(s, l); l } generator(l: %): Generator S == generate { while not empty? l repeat { yield first l; l := rest l } } apply(l: %, i: SingleInteger): S == { while not empty? l and i > 1 repeat (l, i) := (rest l, i-1); empty? l or i ~= 1 => error "No such element"; first l } (l1: %) = (l2: %): Boolean == { while not empty? l1 and not empty? l2 repeat { if first l1 ~= first l2 then return false; (l1, l2) := (rest l1, rest l2) } empty? l1 and empty? l2 } (out: TextWriter) << (l: %): TextWriter == { empty? l => out << "[]"; out << "[" << first l; for s in rest l repeat out << ", " << s; out << "]" } }
Compiling FriCAS source code from file /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/8737543771828864454-25px007.as using Aldor compiler and options -O -Fasy -Fao -Flsp -lfricas -Mno-ALDOR_W_WillObsolete -DFriCAS -Y $FRICAS/algebra -I $FRICAS/algebra Use the system command )set compiler args to change these options. "/var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/8737543771828864454-25px007.as",line 1: #include "axiom" ^ [L1 C1] #1 (Error) Could not open file `axiom'.
The )library system command was not called after compilation.
Click above to see errors.
A few points will help in understanding this program:
add
expression, itself containing several function definitions. It is these internal functions of an add
function which provide the means to manipulate values belonging to the resulting types (such as MiniList?(Integer) in this case).Record
, Pointer
, element
, etc. Some of these, such as Pointer
, are made visible by the #include line, while others, such as element
, are made visible by declaring values to belong to particular types. The names which have meanings in aldor
are detailed in chapter 25 and chapter 26.
=
), an output function (<<
), and a few other operations. Since S is declared to be a BasicType?, the implementation of MiniList? can use the =
and <<
from S in the definitions of MiniList?'s own operations.bracket
to form new values, a test function called empty?
, and so on. MiniList?(S) provides a LinearAggregate?(S), so it must supply all these operations. Users of MiniList?(S) will be able to rely on these operations being available.add
expression defines a type Rep
(specific to MiniList
). This is how values of the type being defined are really represented. The fact that they are represented this way is not visible outside the add
expression.%
. In any add
expression, the name %
refers to the type under construction. For now, %
can be thought of as a shorthand for MiniList(S)
.per
and rep
in this program. These are conversions which allow a data value to be regarded in is public guise, as a member of %
, or by its private representation as a member of Rep
.
rep: % -> Rep
per: Rep -> %
These can be remembered by types they produce: rep
produces a value in Rep, the representation, and per
produces a value in %, percent.
local
. This means they will be private to the add
, and consequently will not be available to users of MiniList?.For example:
[t: Tuple S]: % == ... [g: Generator S]: % == ... (l1: %) = (l2: %): Boolean == ... (out: TextWriter) << (l: %): TextWriter == ...
In general, the left-hand sides of function definitions in Aldor look like function calls with added type declarations. Some names have infix syntax, for instance, =
and <<
above. These are nevertheless just names and, aside from the grouping, behave in exactly the same way as other names. The special syntactic properties of names may be avoided by enclosing them in parentheses. Other special syntactic forms are really just a nice way to write certain function calls. The form '[a,b,c]?' is competely equivalent to the call bracket(a,b,c)
.
With this explanation, we see that the defining forms above are equivalent to the following, more orthodox forms:
bracket(t: Tuple S): % == ... bracket(g: Generator S): % == ... (=) (l1: %, l2: %): Boolean == ... (<<)(out: TextWriter, l: %): TextWriter == ...
The use of the type Generator S
will be explained in chapter 9.
generator
illustrates how a type can define its own traversal method, which allows the new type to decide how its component values should be obtained, say for use in a loop. Such a definition utilises the function generate
, in conjuction with 'yield': each time a yield
is encountered, generate
makes the given value available to the caller and then suspends itself. This technique is described more fully in section 9.3. When the next value is needed, the generator resumes where it left off. Since MiniList?(S) provides a generator
function for MiniLists?, it is possible to use them in a for
loop. For example, in the output function <<
, we see the line:
for s in rest l repeat out << ", " << s;
Here rest l
is traversed by the generator to obtain values for s
.
Questions
Pointer
in Axiom?#include "axiom"
macro I == Integer; main():String == { import from I,Float; U == Union(Integer, Float); import from U; i: I := 2; s: Float := 1.5; ui: U := union i; us: U := union s; u: U := if odd? random(10) then ui else us; if u case Integer$'Integer' then { "Integer"; } else { "Float"; } }
Compiling FriCAS source code from file /var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/2258505555743574552-25px008.as using Aldor compiler and options -O -Fasy -Fao -Flsp -lfricas -Mno-ALDOR_W_WillObsolete -DFriCAS -Y $FRICAS/algebra -I $FRICAS/algebra Use the system command )set compiler args to change these options. "/var/lib/zope2.10/instance/axiom-wiki/var/LatexWiki/2258505555743574552-25px008.as",line 1: #include "axiom" ^ [L1 C1] #1 (Error) Could not open file `axiom'.
The )library system command was not called after compilation.
Untagged unions are not supported by Aldor, thus all unions must be converted to tagged unions. This means that Union(Integer, Float) needs to become something like AXIOMTypeUnion?(i:Integer, f:Float). The case statement requires the tag as its first argument, case thus you write x case i instead of x case Integer. Converting to and from tagged unions is essentially the same as with AXIOMTypeRecord? types. To create a union value from one of its branches, you wrap the value in square brackets, thus [3.3]? converts the float value ``3.3'' to a union value. Similarly, if x has type AXIOMTypeUnion?(i:Integer, f:Float), x.i converts x to an Integer value taking a runtime error if x was in the other branch of the union (for more information on unions in Aldor see part II). Partial functions in old AXIOM were often declared as returning AXIOMTypeUnion?(%, "failed"); by convention this is represented in Aldor as AXIOMTypeUnion?(value1:%, failed: failed
) (recall that failed
is syntactic shorthand for AXIOMTypeEnumeration?(failed)).