at:tutorial:basic
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
at:tutorial:basic [2007/04/04 11:02] – elisag | at:tutorial:basic [2020/02/09 22:05] (current) – elisag | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | < | + | ====== Functional and Imperative Programming |
- | **IN PROGRESS** | + | |
- | - Could it be possible that the "table of contents" | + | This part of the tutorial |
- | - (TOADD_1:) how to define and deal with multidimensional tables. | + | |
- | </ | + | |
- | + | ||
- | ==== Functional and Imperative Programming ==== | + | |
- | + | ||
- | This part of the tutorial | + | |
- | ==== Variables ==== | + | ===== Variables |
- | As usual, one can define, assign and refer to a variable. Variable definitions are made with the keyword **def**. Note that AmbientTalk is a dynamically typed language so, variables do not have a type but, they just contain | + | As usual, one can define, assign and refer to a variable. Variable definitions are made with the keyword **def**. Note that AmbientTalk is a dynamically typed language, so variables do not have a type but can contain |
- | In the examples we use the interactive AmbientTalk shell (iat) where the input and output prompt are represented by > and >> | + | In the examples we use the interactive AmbientTalk shell (iat) where the input and output prompt are represented by > and %%>>%% respectively. |
< | < | ||
Line 22: | Line 16: | ||
</ | </ | ||
- | Variable definitions can be combined with assignments as shown above. As in Pico, assignments uses the ":=" | + | Variable definitions can include an initialization expression that immediately initializes the variable. Variable assignment is performed by means of the well-known '' |
- | An assignment consists of one or more expressions, | ||
< | < | ||
>[x, y] := [ y, x ] | >[x, y] := [ y, x ] | ||
>> | >> | ||
</ | </ | ||
- | Reference is just done by evaluating the variable. | ||
- | ==== Tables ==== | + | As we will explain later, the '' |
- | As in Pico, indexed tables represent what other languages call arrays or lists. Tables are unidimensional and their indexes range from 1 to the size of the table. As variables, one can define, assign and refer to a table. Table definition | + | The variable name is used to refer a variable. The variable |
< | < | ||
- | def t[ <size> ] { < | + | >x |
+ | >>7 | ||
</ | </ | ||
- | This means that the <expression> will be evaluated | + | |
+ | <note important> | ||
+ | When using the '': | ||
+ | </note> | ||
+ | |||
+ | ===== Tables ===== | ||
+ | |||
+ | The //table// is AmbientTalk' | ||
+ | < | ||
+ | def t[ < | ||
+ | </ | ||
+ | This constructs a table, the size of which is determined by ''< | ||
< | < | ||
>def z := 0 | >def z := 0 | ||
Line 44: | Line 49: | ||
>>[1, 2, 3, 4, 5] | >>[1, 2, 3, 4, 5] | ||
</ | </ | ||
- | Although there is no special constructor for definition of multidimensional tables, a table entry can contain another table. This is internally stored as a unidimensional table whose entries are other tables. | ||
+ | Although there is no special constructor for definition of multidimensional tables, a table entry can contain another table. This is internally stored as a one-dimensional table whose entries are other tables. | ||
< | < | ||
- | > | + | > |
>> | >> | ||
- | > | + | > |
>>[1, 2, [" | >>[1, 2, [" | ||
> | > | ||
Line 55: | Line 60: | ||
</ | </ | ||
- | As shown in the definition of the varible " | + | As shown in the definition of the variable '' |
< | < | ||
Line 62: | Line 67: | ||
</ | </ | ||
- | ==== Functions ==== | + | |
+ | ==== Table Splicing ==== | ||
+ | |||
+ | AmbientTalk provides the //splice operator// '' | ||
+ | < | ||
+ | > | ||
+ | >>[1, 2, 3, 4] | ||
+ | >[1, @[2,[3]], [4], @[5], @[], 6] | ||
+ | >>[1, 2, [3], [4], 5, 6] | ||
+ | </ | ||
+ | |||
+ | The splicing operator can be also used in the left-hand side of an assignment or definition to separate the head of a table with its rest elements, as shown below. | ||
+ | < | ||
+ | >def [first, @rest] := [1,2,3,4] | ||
+ | >>[1, 2, 3, 4] | ||
+ | >rest | ||
+ | >>[2, 3, 4] | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Multidimensional Tables ==== | ||
+ | |||
+ | As mentioned before, there is no special constructor for definition of multidimensional tables, a table entry can contain another table. In what follows we have a closer look to manipulations with multidimensional tables. | ||
+ | |||
+ | < | ||
+ | def a := [[1,0,0], [0,1,0], [0,0,1]]; | ||
+ | >> | ||
+ | > | ||
+ | >>0 | ||
+ | >a[1] | ||
+ | >>[1, 0, 0] | ||
+ | > | ||
+ | >>3 | ||
+ | >a | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | An implicit definition of the same table can be expressed as follows: | ||
+ | |||
+ | < | ||
+ | def i := 0; | ||
+ | def aux[3] {0}; | ||
+ | def b[3] { i := i + 1; aux := [0,0,0]; aux[i] :=1; aux}; | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | You can find later in this chapter a helper function for creating matrices | ||
+ | |||
+ | |||
+ | |||
+ | ===== Functions | ||
- | As variables and tables, functions are defined with the keyworkd | + | Analogous to variables and tables, functions are defined with the keyword **def** in the form of: |
< | < | ||
def functionname( < | def functionname( < | ||
</ | </ | ||
- | The argument list is just a list of local variables which are always evaluated one by one from left to right. | + | The argument list is just a list of local variables which are always evaluated one by one from left to right. |
< | < | ||
>def square (x) { x*x } | >def square (x) { x*x } | ||
Line 75: | Line 141: | ||
>>25 | >>25 | ||
</ | </ | ||
- | As usual, | + | This example also illustrates the // |
+ | < | ||
+ | >def f() { nil } | ||
+ | >>< | ||
+ | >f() | ||
+ | >> | ||
+ | </ | ||
+ | The return value of a function is the result of the last executed statement. Functions always return a value, but a function can always opt to return the //nil// object. | ||
+ | |||
+ | < | ||
+ | A function definition is a statement. The body of a function can contain a list of statements, each separated by '';'' | ||
+ | < | ||
+ | def funA() { | ||
+ | // do something useful | ||
+ | } | ||
+ | def funB() { | ||
+ | // do something else | ||
+ | } | ||
+ | </ | ||
+ | The parser will complain saying that '' | ||
+ | </ | ||
+ | |||
+ | Functions in AmbientTalk are //lexically scoped//, which means that free variables are looked up in the enclosing environment of the function definition. This is illustrated in the following example: | ||
+ | < | ||
+ | >def counter := 0 | ||
+ | >>0 | ||
+ | > def inc() { counter := counter + 1} | ||
+ | >>< | ||
+ | >inc() | ||
+ | >>1 | ||
+ | </ | ||
+ | |||
+ | Functions | ||
< | < | ||
>def fac(n) { | >def fac(n) { | ||
def inner(n, result) { | def inner(n, result) { | ||
- | if: (n =0) then: { result } else: { inner( n-1, n * result) | + | if: (n = 0) then: { result } else: { inner( n-1, n * result) |
}; | }; | ||
inner(n,1) | inner(n,1) | ||
} | } | ||
- | >>nil | + | >>< |
>fac(5) | >fac(5) | ||
>>120 | >>120 | ||
</ | </ | ||
- | Note that variables and functions defined locally to functions are only visible in the scope of the function where there were defined. Notice also that a function name can also be used just to refer the function but without calling it. | ||
- | Unlike Pico, AmbientTalk doesn' | + | This example also illustrates how a function can be made " |
+ | |||
+ | |||
+ | ==== Variable-Length Argument Functions ==== | ||
+ | |||
+ | You can create functions that take an arbitrary number | ||
< | < | ||
- | >def sum := 0 | + | >def sum(@args) { |
+ | def total := 0; | ||
+ | foreach: { |el| total := total + el } in: args; | ||
+ | total | ||
+ | }; | ||
+ | >>< | ||
+ | > | ||
+ | >>6 | ||
+ | </ | ||
+ | |||
+ | When the //sum// function is called, the //args// table is spliced and passed as the argument list to the function. Note that the //args// table can also be modified inside the body of the function. | ||
+ | |||
+ | Alternatively, | ||
+ | < | ||
+ | >def sum(a, b, @rest){ { | ||
+ | def total := a + b; | ||
+ | foreach: { |el| total := total + el } in: rest; | ||
+ | total} | ||
+ | >>< | ||
+ | > | ||
+ | >>6 | ||
+ | </ | ||
+ | |||
+ | In that case, the //sum// function still accepts an arbitrary number of arguments as long as two arguments are supplied. //a// and //b// are considered as mandatory arguments of the argument list. | ||
+ | |||
+ | The splice operator can also be used to transform a table into an argument list for a function, for example: | ||
+ | < | ||
+ | def args := [3,4,5]; | ||
+ | > sum(1,2, @args); | ||
+ | >> 15 | ||
+ | </ | ||
+ | |||
+ | One way to think about this is that the splice operator splices the '' | ||
+ | < | ||
+ | > sum(1, | ||
+ | >> 21 | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Optional Parameters ==== | ||
+ | |||
+ | A function can also declare optional arguments as shown below. Optional arguments can be omitted in a function call. If this is the case, the default expression provided in their definition is evaluated and passed as argument to the function instead. | ||
+ | < | ||
+ | >def incr( number, step := 1){ number + step} | ||
+ | >>< | ||
+ | > | ||
+ | >>4 | ||
+ | > | ||
+ | >>6 | ||
+ | </ | ||
+ | |||
+ | As is customary in languages with the above optional arguments, AmbientTalk requires mandatory parameters to be defined //before// optional parameters, which should in turn be defined //before// a variable-argument parameter, if any. | ||
+ | |||
+ | Let us show how to use optional arguments to define an auxilary function that creates matrices: | ||
+ | |||
+ | < | ||
+ | def makeMatrix(n, | ||
+ | def [i,j] := [0,0]; | ||
+ | def makeCol(i, | ||
+ | def col[m] { j := j + 1; init(i,j) } | ||
+ | }; | ||
+ | def matrix[n] { i := i + 1; makeCol(i, | ||
+ | }; | ||
+ | >def c := makeMatrix(3); | ||
+ | >> | ||
+ | >c[1] := [1,2,3] | ||
+ | >>[1, 2, 3] | ||
+ | >c | ||
+ | >> | ||
+ | >def d := makeMatrix(4, | ||
+ | {|i,j| if: (i == j) then: {1} else: {0}}); | ||
+ | >> [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] | ||
+ | </ | ||
+ | |||
+ | ===== Closures ===== | ||
+ | |||
+ | As you have probably noticed in the previous examples, | ||
+ | |||
+ | The function name can be thus used to refer the function (without calling it). This will also return a closure to that function. As an example consider the // | ||
+ | < | ||
+ | >def makeCell(val){ | ||
+ | def getter() { val} ; | ||
+ | def setter(v) {val := v}; | ||
+ | [getter, setter] | ||
+ | } | ||
+ | >>< | ||
+ | >def [get, set] := makeCell(42); | ||
+ | >> | ||
+ | > | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | This example also illustrates how a function can make public some of its local fields or functions by returning them as its return value. The '' | ||
+ | |||
+ | ===== Blocks ===== | ||
+ | |||
+ | In AmbientTalk, | ||
+ | < | ||
+ | { |< | ||
+ | </ | ||
+ | |||
+ | If the block does not require any parameter, the |< | ||
+ | < | ||
+ | >{|a, b| a+ b}(3,2) | ||
+ | >>5 | ||
+ | </ | ||
+ | Note that the argument list passed to the block can define the different types of arguments previously explained. | ||
+ | < | ||
+ | >def sum := {|a, b, @rest| | ||
+ | def total := a + b; | ||
+ | | ||
+ | }; | ||
+ | >>< | ||
+ | > | ||
+ | >>6 | ||
+ | </ | ||
+ | |||
+ | This example also illustrates that blocks are also used to iterate over enumerations, | ||
+ | |||
+ | < | ||
+ | AmbientTalk borrows its block syntax from languages like Smalltalk and Self, where the role of the curly braces is played by square brackets, i.e. '' | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ===== Keywords ===== | ||
+ | |||
+ | AmbientTalk supports keyworded messages, as in Smalltalk and Self. We have already seen some examples of keyword messages in the previous sections such as the '' | ||
+ | |||
+ | < | ||
+ | >def map: clo onto: tbl { | ||
+ | def i := 0; | ||
+ | def mapped[tbl.length] { | ||
+ | i := i+1; | ||
+ | clo( tbl[ i ] ) | ||
+ | }; | ||
+ | } | ||
+ | >> < | ||
+ | </ | ||
+ | |||
+ | It can be invoked as follows: | ||
+ | < | ||
+ | >map: square onto: [1,2,3] | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | In AmbientTalk keyworded functions and function calls are actually syntactic sugar. They are transformed by the parser into their canonical equivalent. Hence: | ||
+ | < | ||
+ | def foo: arg1 bar: arg2 {...} | ||
+ | </ | ||
+ | is transformed into: | ||
+ | < | ||
+ | def foo: | ||
+ | </ | ||
+ | |||
+ | It is also possible to invoke keyworded functions using the canonical function application syntax: | ||
+ | |||
+ | < | ||
+ | foo: | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | Be careful when nesting calls to keyworded functions: a call of the form '' | ||
+ | </ | ||
+ | |||
+ | ===== Native Data Types ===== | ||
+ | |||
+ | The basic data types in AmbientTalk are numbers (i.e. integers), fractions (i.e. double precision floating point numbers), text (i.e. strings), tables (i.e. arrays) and booleans. In fact, instances of these data types are nothing but objects and as such, they respond to a variety of native methods. Objects will be the subject of the next chapter of the tutorial. This section explains the basic data types and includes some examples how to manipulate them. The complete list of methods can be found in the language reference. | ||
+ | |||
+ | |||
+ | |||
+ | ==== Numerical data types ==== | ||
+ | |||
+ | AmbientTalk supports numbers and fractions which represent what other languages call integers and double precision floating point numbers, respectively. | ||
+ | |||
+ | Note that since numerical types are objects in AmbientTalk, | ||
+ | < | ||
+ | > | ||
+ | >>2 | ||
+ | > | ||
+ | >> | ||
+ | >1 ** 5 | ||
+ | >>[1, 2, 3, 4] | ||
+ | >5 *** 1 | ||
+ | >>[5, 4, 3, 2, 1] | ||
+ | > | ||
+ | >>1 | ||
+ | > | ||
+ | >>1 | ||
+ | > | ||
+ | >>2 | ||
+ | </ | ||
+ | |||
+ | Beware of the precedence rules for function application versus method invocation, which may lead to unexpected results, e.g.: | ||
+ | < | ||
+ | > | ||
+ | >> | ||
+ | </ | ||
+ | This code is interpreted as '' | ||
+ | |||
+ | Numbers also support some useful iterator methods such as: | ||
+ | < | ||
+ | >1.to: 5 do: { |i| system.println(i)} | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | 5 | ||
+ | >1.to: 5 step: 2 do: { |i| system.println(i)} | ||
+ | 1 | ||
+ | 3 | ||
+ | 5 | ||
+ | > | ||
+ | 6 | ||
+ | 4 | ||
+ | 2 | ||
+ | 0 | ||
+ | >>nil | ||
+ | > | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | ==== Texts ==== | ||
+ | |||
+ | |||
+ | A text data type represent a string of characters. Texts are often created using sequences of characters surrounded by double quotes ("). AmbientTalk doesn' | ||
+ | < | ||
+ | >" | ||
+ | >> | ||
+ | >" | ||
+ | >> | ||
+ | >" | ||
+ | | ||
+ | } | ||
+ | >>" | ||
+ | >" | ||
+ | >>" | ||
+ | >" | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | AmbientTalk also provides some useful support for pattern matching using regular expressions. | ||
+ | < | ||
+ | >" | ||
+ | >> | ||
+ | >" | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Tables ==== | ||
+ | |||
+ | |||
+ | We have already introduced how to define tables. Let us now focus on how to manipulate them with the native methods provided by the table object. | ||
+ | < | ||
+ | > | ||
+ | >>[1, 3] | ||
+ | > | ||
+ | >>[2, 3, 4] | ||
+ | >def vowels := [" | ||
+ | >> | ||
+ | > | ||
+ | >>5 | ||
+ | > | ||
+ | >>" | ||
+ | > | ||
+ | >>" | ||
+ | > | ||
+ | >> | ||
+ | > | ||
+ | >>" | ||
+ | > | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | Tables also support some useful iterator methods as shown below. | ||
+ | |||
+ | < | ||
+ | >def sum:= 0; | ||
>>0 | >>0 | ||
- | >sum := sum + 1 | + | >[1, |
+ | >> | ||
+ | >sum | ||
+ | >>6 | ||
+ | >def sumNnum (@args) { | ||
+ | args.inject: | ||
+ | } | ||
+ | >>< | ||
+ | > | ||
+ | >>6 | ||
+ | </ | ||
+ | |||
+ | ==== Booleans ==== | ||
+ | |||
+ | As any native type, booleans are objects so, they respond to keyword messages such as: | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | < | ||
+ | >(0 < 1).ifTrue: { 0 } | ||
+ | >>0 | ||
+ | >(3 != 5).ifTrue: { 1 } ifFalse: { 0 } | ||
>>1 | >>1 | ||
- | >sum := { | x, y| x + y } | + | > def [i, j] := [1,3] |
+ | >>[1, 3] | ||
+ | >{i < j}.whileTrue: | ||
+ | 1 | ||
+ | 2 | ||
>>nil | >>nil | ||
- | > | ||
- | >>3 | ||
</ | </ | ||
- | ==== Blocks | + | Compound boolean expressions can be created by means of a boolean' |
+ | |||
+ | ===== Control Flow Constructs | ||
+ | |||
+ | Control flow constructs are defined in the " | ||
+ | < | ||
+ | if: booleanCondition then: consequentClosure | ||
+ | if: booleanCondition then: consequentClosure else: alternativeClosure | ||
+ | while: conditionClosure do: body | ||
+ | foreach: iteratorClosure in: table | ||
+ | do: bodyClosure if: condition | ||
+ | do: bodyClosure unless: condition | ||
+ | </ | ||
+ | |||
+ | <note warn> | ||
+ | Note that '' | ||
+ | </ | ||
+ | |||
+ | The above definitions in the lexical root of AmbientTalk are simply convenience functions for the methods defined on booleans and closures. For example, an if-statement can also be encoded as a message send, as in Smalltalk: '' | ||
+ | |||
+ | An example of usage for some of the above structures is shown below in the definition of the sort function. | ||
+ | < | ||
+ | >def sort(table, cmp := { |e1,e2| e1 < e2 }) { | ||
+ | def quickSort(table, | ||
+ | def left := low; | ||
+ | def right := high; | ||
+ | def pivot := table[(left+right) /- 2]; | ||
+ | def save := nil; | ||
+ | while: { left <= right } do: { | ||
+ | while: { cmp(table[left], | ||
+ | left := left + 1 | ||
+ | }; | ||
+ | while: { cmp(pivot, table[right]) } do: { | ||
+ | right := right - 1 | ||
+ | }; | ||
+ | if: (left <= right) then: { | ||
+ | // swap elements | ||
+ | save := table[left]; | ||
+ | table[left] := table[right]; | ||
+ | table[right] := save; | ||
+ | left := left + 1; | ||
+ | right := right - 1; | ||
+ | }; | ||
+ | }; | ||
+ | if: (low< | ||
+ | if: (high> | ||
+ | table; | ||
+ | }; | ||
+ | quickSort(table, | ||
+ | }; | ||
+ | >>< | ||
+ | > | ||
+ | >>[2, 4, 5, 6, 8, 37] | ||
+ | </ | ||
+ | |||
+ | AmbientTalk has no '' |
at/tutorial/basic.1175677361.txt.gz · Last modified: 2007/04/04 11:03 (external edit)