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/17 16:41] – * tvcutsem | at:tutorial:basic [2020/02/09 22:05] (current) – elisag | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | < | ||
- | **This Tutorial is still under heavy construction!!** | ||
- | </ | ||
====== Functional and Imperative Programming ====== | ====== Functional and Imperative Programming ====== | ||
Line 10: | Line 7: | ||
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 any value. | 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 any value. | ||
- | In the examples we use the interactive AmbientTalk shell (iat) where the input and output prompt are represented by > and <code>>></ | + | In the examples we use the interactive AmbientTalk shell (iat) where the input and output prompt are represented by > and %%>>%% respectively. |
< | < | ||
Line 19: | Line 16: | ||
</ | </ | ||
- | Variable definitions can include an initialization expression that immediately initializes the variable. Variable assignment is performed by means of the well-known | + | Variable definitions can include an initialization expression that immediately initializes the variable. Variable assignment is performed by means of the well-known |
< | < | ||
Line 34: | Line 31: | ||
</ | </ | ||
- | < | + | < |
When using the '': | When using the '': | ||
</ | </ | ||
Line 40: | Line 37: | ||
===== Tables ===== | ===== Tables ===== | ||
- | Indexed tables represent | + | The //table// is AmbientTalk' |
< | < | ||
- | def t[ <size> ] { <expression> } | + | def t[ <sizeexpression> ] { <initexpression> } |
</ | </ | ||
- | This means that the <expression> will be evaluated | + | This constructs a table, |
< | < | ||
>def z := 0 | >def z := 0 | ||
Line 52: | Line 50: | ||
</ | </ | ||
- | 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 | + | 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 |
< | < | ||
>def vowels := [" | >def vowels := [" | ||
Line 62: | Line 60: | ||
</ | </ | ||
- | As shown in the definition of the varible //vowels//, evaluating a series of comma-separated data types between square brackets (aka a tabulation) results | + | As shown in the definition of the variable '' |
< | < | ||
Line 68: | Line 66: | ||
>>[1, [1, 2, [" | >>[1, [1, 2, [" | ||
</ | </ | ||
+ | |||
==== Table Splicing ==== | ==== Table Splicing ==== | ||
- | AmbientTalk provides the operator @ to splice tables into surrounding table expressions. | + | AmbientTalk provides the // |
< | < | ||
> | > | ||
Line 79: | Line 78: | ||
</ | </ | ||
- | The splicing operator can be also used for matching | + | 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] | >def [first, @rest] := [1,2,3,4] | ||
Line 86: | Line 85: | ||
>>[2, 3, 4] | >>[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]]; | ||
+ | >> | ||
+ | >a[1][2] | ||
+ | >>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 ===== | ===== Functions ===== | ||
- | As variables and tables, functions are defined with the keyword **def** in the form of: | + | 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. A basic function looks like this: | + | The argument list is just a list of local variables which are always evaluated one by one from left to right. Hence, AmbientTalk employs // |
< | < | ||
>def square (x) { x*x } | >def square (x) { x*x } | ||
Line 100: | Line 141: | ||
>>25 | >>25 | ||
</ | </ | ||
- | This example also illustrates | + | This example also illustrates |
< | < | ||
- | >def f(){nil} | + | >def f() { nil } |
>>< | >>< | ||
>f() | >f() | ||
>>nil | >>nil | ||
</ | </ | ||
- | The return value of a function is the result of the last statement | + | The return value of a function is the result of the last executed |
- | Functions have access | + | < |
+ | 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 | ||
< | < | ||
>def counter := 0 | >def counter := 0 | ||
Line 123: | Line 177: | ||
>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) | ||
Line 132: | Line 186: | ||
</ | </ | ||
- | This example also illustrates how a function can be made private by means of lexical | + | This example also illustrates how a function can be made "private" |
+ | |||
==== Variable-Length Argument Functions ==== | ==== Variable-Length Argument Functions ==== | ||
- | You can create functions that take an arbitrary number of arguments by means of the splicing operator | + | You can create functions that take an arbitrary number of arguments |
< | < | ||
- | >def sum(@args){ { | + | >def sum(@args) { |
def total := 0; | def total := 0; | ||
foreach: { |el| total := total + el } in: args; | foreach: { |el| total := total + el } in: args; | ||
- | total} | + | total |
+ | }; | ||
>>< | >>< | ||
> | > | ||
Line 160: | Line 216: | ||
</ | </ | ||
- | 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. | + | 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. |
- | A function can also declare optional arguments as shown below. Optional arguments can be omitted in a function call. Internally, the default | + | 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 | ||
< | < | ||
>def incr( number, step := 1){ number + step} | >def incr( number, step := 1){ number + step} | ||
Line 170: | Line 246: | ||
> | > | ||
>>6 | >>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]] | ||
</ | </ | ||
Line 186: | Line 285: | ||
>def [get, set] := makeCell(42); | >def [get, set] := makeCell(42); | ||
>> | >> | ||
+ | >get(); | ||
+ | >>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 get and set could be then passed | + | 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 ===== | ===== Blocks ===== | ||
- | In AmbientTalk, | + | In AmbientTalk, |
< | < | ||
{ |< | { |< | ||
</ | </ | ||
- | If the block do not require any parameter, the |< | + | |
+ | If the block does not require any parameter, the |< | ||
< | < | ||
- | >{| a, b| a+ b} (3,2) | + | >{|a, b| a+ b}(3,2) |
>>5 | >>5 | ||
</ | </ | ||
Note that the argument list passed to the block can define the different types of arguments previously explained. | Note that the argument list passed to the block can define the different types of arguments previously explained. | ||
< | < | ||
- | >{|a, b, @rest| | + | >def sum := {|a, b, @rest| |
def total := a + b; | def total := a + b; | ||
| | ||
- | | + | }; |
+ | >>< | ||
+ | >sum(1,2,3) | ||
>>6 | >>6 | ||
</ | </ | ||
Line 212: | Line 316: | ||
This example also illustrates that blocks are also used to iterate over enumerations, | This example also illustrates that blocks are also used to iterate over enumerations, | ||
- | AmbientTalk | + | < |
+ | AmbientTalk | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ===== Keywords ===== | ||
+ | |||
+ | AmbientTalk supports keyworded messages, as in Smalltalk and Self. We have already seen some examples | ||
< | < | ||
- | > | + | > |
- | >>< | + | def i := 0; |
- | >square(3) | + | def mapped[tbl.length] |
- | >>9 | + | |
+ | clo( tbl[ i ] ) | ||
+ | }; | ||
+ | } | ||
+ | >> | ||
</ | </ | ||
- | ===== Keywords ===== | + | It can be invoked as follows: |
+ | < | ||
+ | >map: square onto: [1,2,3] | ||
+ | >> | ||
+ | </ | ||
- | AmbientTalk supports keyword messages. We have already seen some examples of keyword messages in the previous sections such as the foreach structure. | + | In AmbientTalk |
< | < | ||
def foo: arg1 bar: arg2 {...} | def foo: arg1 bar: arg2 {...} | ||
- | def foo: | + | </ |
+ | 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 ===== | ===== 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. | ||
- | The basic types in AmbientTalk are numbers, fractions, text, tables and booleans. In fact, 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 ==== | ==== Numerical data types ==== | ||
- | AmbientTalk supports numbers and fractions which represent what other languages call integers and floating point numbers, respectively. | + | AmbientTalk supports numbers and fractions which represent what other languages call integers and double precision |
- | Note that since numerical types are objects in AmbientTalk, | + | Note that since numerical types are objects in AmbientTalk, |
< | < | ||
>1.inc() | >1.inc() | ||
>>2 | >>2 | ||
- | > | ||
- | >>1 | ||
>1.cos() | >1.cos() | ||
>> | >> | ||
Line 256: | Line 389: | ||
>>2 | >>2 | ||
</ | </ | ||
+ | |||
+ | Beware of the precedence rules for function application versus method invocation, which may lead to unexpected results, e.g.: | ||
+ | < | ||
+ | > | ||
+ | >>-1 | ||
+ | </ | ||
+ | This code is interpreted as '' | ||
Numbers also support some useful iterator methods such as: | Numbers also support some useful iterator methods such as: | ||
< | < | ||
- | >6.to: 0 step: 2 do: { |i| system.println(i) } | + | >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 | 6 | ||
4 | 4 | ||
2 | 2 | ||
+ | 0 | ||
>> | >> | ||
> | > | ||
Line 297: | Line 448: | ||
>> | >> | ||
</ | </ | ||
+ | |||
==== Tables ==== | ==== Tables ==== | ||
- | We have already | + | We have already |
< | < | ||
> | > | ||
Line 342: | Line 494: | ||
==== Booleans ==== | ==== Booleans ==== | ||
- | + | As any native type, booleans are objects so, they respond to keyword messages such as: | |
- | AmbientTalk supports infix operators for booleans as &, | and !. As any native type, booleans are objects so, they respond to keyword messages such as: | + | |
< | < | ||
< | < | ||
Line 351: | Line 502: | ||
</ | </ | ||
- | **=** and **!=** are the infix operators for equality and inequality. | + | '' |
< | < | ||
>(0 < 1).ifTrue: { 0 } | >(0 < 1).ifTrue: { 0 } | ||
Line 358: | Line 509: | ||
>>1 | >>1 | ||
> def [i, j] := [1,3] | > def [i, j] := [1,3] | ||
- | >>>[1, 3] | + | >>[1, 3] |
>{i < j}.whileTrue: | >{i < j}.whileTrue: | ||
1 | 1 | ||
Line 365: | Line 516: | ||
</ | </ | ||
- | Boolean infix operators such as & and | are not shortcut. Thus, both arguments will be evaluated. For lazy evaluation, you should use the natives methods. For example, false.and: { 1/0 } will return false without executing the second argument. | + | Compound boolean expressions can be created by means of a boolean' |
- | ===== Control Flow Structures | + | ===== Control Flow Constructs |
- | Control flow structures | + | Control flow constructs |
< | < | ||
- | if: booleanCondition then: { consequent } | + | if: booleanCondition then: consequentClosure |
- | if: booleanCondition then: { consequent } else: { alternative } | + | if: booleanCondition then: consequentClosure |
- | while: | + | while: |
- | foreach: | + | foreach: |
- | do: { body } if: condition | + | do: bodyClosure |
- | do: { body } unless: condition | + | do: bodyClosure |
</ | </ | ||
- | An example of usage for some of these structures is shown below in the definition of the sort function. | + | |
+ | <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 sort(table, cmp := { |e1,e2| e1 < e2 }) { | ||
- | def quickSort(table, | + | |
- | def left := low; | + | def left := low; |
- | def right := high; | + | def right := high; |
- | def pivot := table[(left+right) /- 2]; | + | def pivot := table[(left+right) /- 2]; |
- | def save := nil; | + | def save := nil; |
- | while: { left <= right } do: { | + | while: { left <= right } do: { |
- | | + | while: { cmp(table[left], |
- | left := left + 1 | + | left := left + 1 |
- | }; | + | }; |
- | | + | while: { cmp(pivot, table[right]) } do: { |
- | right := right - 1 | + | right := right - 1 |
- | }; | + | }; |
- | | + | if: (left <= right) then: { |
- | | + | // swap elements |
- | | + | save := table[left]; |
- | table[left] := table[right]; | + | table[left] := table[right]; |
- | table[right] := save; | + | table[right] := save; |
- | left := left + 1; | + | left := left + 1; |
- | right := right - 1; | + | right := right - 1; |
- | | + | }; |
- | }; | + | }; |
- | if: (low< | + | if: (low< |
- | if: (high> | + | if: (high> |
- | | + | table; |
- | | + | }; |
- | | + | quickSort(table, |
- | }; | + | }; |
>>< | >>< | ||
> | > | ||
>>[2, 4, 5, 6, 8, 37] | >>[2, 4, 5, 6, 8, 37] | ||
</ | </ | ||
+ | |||
+ | AmbientTalk has no '' |
at/tutorial/basic.1176820880.txt.gz · Last modified: 2007/04/17 16:43 (external edit)