at:tutorial:basic
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
at:tutorial:basic [2007/04/04 11:24] – * elisag | at:tutorial:basic [2007/04/17 16:51] – tvcutsem | ||
---|---|---|---|
Line 1: | Line 1: | ||
< | < | ||
- | **IN PROGRESS** | + | **This Tutorial is still under heavy construction!!** |
- | - Could it be possible that the "table of contents" | + | |
- | - (TOADD_1:) how to define and deal with multidimensional tables. | + | |
</ | </ | ||
+ | ====== Functional and Imperative Programming ====== | ||
+ | |||
+ | This part of the tutorial explains AmbientTalk as a simple expression language with a flexible syntax which resembles languages like Ruby, Python and Javascript. This section mainly describes the basic features of the language, namely variables, functions, tables (i.e. arrays) and control flow primitives. | ||
- | ==== Functional and Imperative Programming | + | ===== Variables |
- | + | ||
- | This part of the tutorial shows AmbientTalk as a simple expression language with a minimum syntax which resembles very on Java script. This section mainly describes the basic features of the language, namely variables, functions and tables and control flow. | + | |
- | + | ||
- | ==== 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 19: | ||
</ | </ | ||
- | 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> | ||
+ | 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 52: | ||
>>[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 63: | ||
</ | </ | ||
- | As shown in the definition of the varible " | + | As shown in the definition of the variable '' |
< | < | ||
Line 62: | Line 70: | ||
</ | </ | ||
- | ==== Functions ==== | + | ==== Table Splicing ==== |
+ | |||
+ | AmbientTalk provides the operator @ to splice tables into surrounding table expressions. | ||
+ | < | ||
+ | > | ||
+ | >>[1, 2, 3, 4] | ||
+ | >[1, @[2,[3]], [4], @[5], @[], 6] | ||
+ | >>[1, 2, [3], [4], 5, 6] | ||
+ | </ | ||
+ | |||
+ | The splicing operator can be also used for matching table elements as shown below. | ||
+ | < | ||
+ | >def [first, @rest] := [1,2,3,4] | ||
+ | >>[1, 2, 3, 4] | ||
+ | >rest | ||
+ | >>[2, 3, 4] | ||
+ | </ | ||
+ | |||
+ | ===== Functions | ||
As variables and tables, functions are defined with the keyword **def** in the form of: | As variables and tables, functions are defined with the keyword **def** in the form of: | ||
Line 75: | Line 101: | ||
>>25 | >>25 | ||
</ | </ | ||
- | Functions can call themselves recusively and as in Pico, functions | + | This example also illustrates how functions are called. Calls to functions without parameters must also include the parenthesis as shown below. |
+ | < | ||
+ | >def f(){nil} | ||
+ | >>< | ||
+ | >f() | ||
+ | >> | ||
+ | </ | ||
+ | The return value of a function is the result of the last statement executed. Functions must always return a value - i.e. they cannot be abstract. The example also illustrates how to create dumb function that doesn' | ||
+ | |||
+ | Functions have access to the enclosing environment of its definition as shown in the following example. | ||
+ | < | ||
+ | >def counter := 0 | ||
+ | >>0 | ||
+ | > def inc() { counter := counter + 1} | ||
+ | >>< | ||
+ | >inc() | ||
+ | >>1 | ||
+ | </ | ||
+ | |||
+ | Functions can call themselves recusively and they can also be nested in the definitions | ||
< | < | ||
>def fac(n) { | >def fac(n) { | ||
Line 83: | Line 128: | ||
inner(n,1) | inner(n,1) | ||
} | } | ||
- | >>nil | + | >>< |
>fac(5) | >fac(5) | ||
>>120 | >>120 | ||
</ | </ | ||
- | Variables and other functions defined locally to a function | + | This example also illustrates how a function can be made private by means of lexical scope. |
+ | |||
+ | ==== Variable-Length Argument Functions ==== | ||
- | Unlike Pico, AmbientTalk doesn' | + | You can create |
+ | < | ||
+ | >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 := 0 | + | >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. | ||
+ | |||
+ | A function can also declare optional arguments as shown below. Optional arguments can be omitted in a function call. Internally, the default value provided in their definition is passed as the argument to the function. | ||
+ | < | ||
+ | >def incr( number, step := 1){ number + step} | ||
+ | >>< | ||
+ | > | ||
+ | >>4 | ||
+ | > | ||
+ | >>6 | ||
+ | </ | ||
+ | |||
+ | ===== 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 get and set could be then passed as arguments to other functions such as // | ||
+ | |||
+ | ===== Blocks ===== | ||
+ | |||
+ | In AmbientTalk, | ||
+ | < | ||
+ | { |< | ||
+ | </ | ||
+ | If the block do 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. | ||
+ | < | ||
+ | >{|a, b, @rest| | ||
+ | def total := a + b; | ||
+ | | ||
+ | | ||
+ | >>6 | ||
+ | </ | ||
+ | |||
+ | This example also illustrates that blocks are also used to iterate over enumerations, | ||
+ | |||
+ | AmbientTalk doesn’t support function assigment. However, one can assign blocks to variables. In order to call the block the name of the variable must be used. If the block defined parameters, these are required to the call as argument list. What follows is an example of such manipulation: | ||
+ | < | ||
+ | >def square := { |x| x * x } | ||
+ | >>< | ||
+ | > | ||
+ | >>9 | ||
+ | </ | ||
+ | |||
+ | ===== Keywords ===== | ||
+ | |||
+ | AmbientTalk supports keyword messages. We have already seen some examples of keyword messages in the previous sections such as the foreach structure. In AmbientTalk keywords are transformed by the parser into functions in the form: | ||
+ | < | ||
+ | def foo: arg1 bar: arg2 {...} | ||
+ | def foo: | ||
+ | </ | ||
+ | |||
+ | ===== Native Data Types ===== | ||
+ | |||
+ | |||
+ | 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 ==== | ||
+ | |||
+ | AmbientTalk supports numbers and fractions which represent what other languages call integers and floating point numbers, respectively. | ||
+ | |||
+ | Note that since numerical types are objects in AmbientTalk, | ||
+ | < | ||
+ | > | ||
+ | >>2 | ||
+ | > | ||
+ | >>1 | ||
+ | > | ||
+ | >> | ||
+ | >1 ** 5 | ||
+ | >>[1, 2, 3, 4] | ||
+ | >5 *** 1 | ||
+ | >>[5, 4, 3, 2, 1] | ||
+ | > | ||
+ | >>1 | ||
+ | > | ||
+ | >>1 | ||
+ | > | ||
+ | >>2 | ||
+ | </ | ||
+ | |||
+ | Numbers also support some useful iterator methods such as: | ||
+ | < | ||
+ | >6.to: 0 step: 2 do: { |i| system.println(i) } | ||
+ | 6 | ||
+ | 4 | ||
+ | 2 | ||
+ | >>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 introduce 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 ==== | ||
+ | |||
+ | |||
+ | AmbientTalk supports infix operators for booleans as &, | and !. As any native type, booleans are objects so, they respond to keyword messages such as: | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **=** and **!=** are the infix operators for equality and inequality. **true** and **false** are the boolean constant objects. What follows is some basic examples of boolean manipulation: | ||
+ | < | ||
+ | >(0 < 1).ifTrue: { 0 } | ||
+ | >>0 | ||
+ | >(3 != 5).ifTrue: { 1 } ifFalse: { 0 } | ||
>>1 | >>1 | ||
- | >sum := { | x, y| x + y } | + | > def [i, j] := [1,3] |
+ | >>> | ||
+ | >{i < j}.whileTrue: | ||
+ | 1 | ||
+ | 2 | ||
>>nil | >>nil | ||
- | > | ||
- | >>3 | ||
</ | </ | ||
- | ==== Blocks | + | 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. |
+ | |||
+ | ===== Control Flow Structures | ||
+ | |||
+ | Control flow structures are defined in the lexical root of AmbientTalk. The lexical root is an object containing globally visible native methods. We have already seen in the previous sections examples of usage of the foreach and if/then structures. The complete list of traditional control flow structures defined in AmbientTalk is shown below: | ||
+ | < | ||
+ | if: booleanCondition then: { consequent } | ||
+ | if: booleanCondition then: { consequent } else: { alternative } | ||
+ | while: { condition } do: { body } | ||
+ | foreach: { |v| body } in: [ table ] | ||
+ | do: { body } if: condition | ||
+ | do: { body } unless: condition | ||
+ | </ | ||
+ | An example of usage for some of these 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> | ||
+ | | ||
+ | }; | ||
+ | quickSort(table, | ||
+ | }; | ||
+ | >>< | ||
+ | > | ||
+ | >>[2, 4, 5, 6, 8, 37] | ||
+ | </ |
at/tutorial/basic.txt · Last modified: 2020/02/09 22:05 by elisag