The Swift Language ------------------ A *Swift script* describes data, application components, invocations of applications components, and the inter-relations (data flow) between those invocations. Data is represented in a script by strongly-typed single-assignment variables. The syntax superficially resembles C and Java. For example, { and } characters are used to enclose blocks of statements. Conventions ~~~~~~~~~~~ The following conventions will be used throughout the guide: - Swift source listings will appear in the following form: + [listing, swift] ---- // Swift script code ---- - When describing syntax, the code will appear as follows: + [listing, syntax] ---- := ---- + The following conventions are used for syntax blocks: ** Angle brackets indicate a labeled item that is to be substituted when writing actual code: ++ can be used to mean +a+, +b+, +myVariable+, etc. ** Square brackets indicate optional items: +[something optional]+ ** Single quotes indicate a literal character or string when the literal could otherwise be interpreted as being part of a special syntax symbol: +'''['+ means a literal left square bracket and not the beginning of an optional item. ** The pipe symbol is used to indicate two or more mutually exclusive choices: +A | C | B+ means either +A+ or +B+ or +C+. ** Parentheses are used for groupping ** The asterisk (+\*+) is used to indicate zero or more repetitions of the operand immediately to the left. For example, +A*+ signifies that the letter +A+ can appear any number of times, including not at all. ** A plus sign (+++) is used to indicate one or more repetition(s) Examples: [listing, syntax] ---- [] | ( ) | * + ---- [[language:values]] Values ~~~~~~ Values in Swift are the most basic form of data. All values have an associated <>. Examples of values are +1.0+, +"a string"+, etc. [[language:variables]] Variables ~~~~~~~~~ Swift variables are symbols that hold values. Variables have a type, which is specified when the variable is declared. It is also possible to <> a value to a variable when the variable is declared. A variable *declaration* has the following syntax: [listing, syntax, Variable Declaration] ---- [= ]; ---- It is also possible to declare multiple variables of the same type in one line: [listing, syntax, Multi-Variable Declaration] ---- [= ] (, [= ])* ---- Examples: [listing, swift] ---- int a; string message = "A message"; int c = 1, d = 2; ---- Variables must be *assigned* a value *exactly once*. The following Swift program will result in compile-time errors: [listing, swift] ---- int a = 2; a = 3; <1> int b; f(b); <2> ---- <1> Error: variable "a" can only be assigned once <2> Error: variable "b" is not initialized [[language:types-of-variables]] Types of Variables ^^^^^^^^^^^^^^^^^^ There are two types of variables: Local variables:: Local variables are ``normal'' variables which can be declared in any <> using variable declarations as shown above. Global variables:: Global variables are variables that are declared in the <> and are visible in all the scopes in a Swift program. Their declaration is prefixed with the keyword +global+ as shown below: + [listing, syntax, Global Variable] ---- global ; ---- + Example: + [listing, swift] ---- global float PI = 3.14159; ---- [[language:scoping-rules]] Scoping Rules ^^^^^^^^^^^^^ There are three types of scopes: *the main scope*, *function scopes*, and *sub-scopes*. Variables declared in a scope are always visible within that scope, regardless of whether they are declared lexically before use or not. [[language:main-scope]] Main scope:: The global scope is the top-level scope of a Swift program. <> can only be declared in the main scope. Sub-scopes:: Sub-scopes are scopes introduced by code blocks, which are sections of code surrounded by curly brackets (+{...}+) with the exception of function scopes. Sub-scopes create a hierarchy. Each sub-scope has a parent, which may, in turn, have its own parent. A variable declared in a scope is visible in all of its sub-scopes and then recursively visible in all sub-scopes of each sub-scope. A variable declared in a scope cannot be re-declared in a sub-scope. In other words, *shadowing* is not allowed: + [listing, swift] ---- int a = 1; if (true) { int a = 2; // Illegal: shadowing is no allowed } ---- + Whenever a variable is referenced in a scope, the Swift compiler will search for the corresponding variable declaration starting with the scope from which the reference is made and, if not found, continue recursively with all ancestor scopes until a declaration is found. Function scope:: A function scope is the scope of the body of a function declaration. The following are visible in a function scope: global variables, the formal parameters of the function, and variables declared within the function body. A function scope can have its own sub-scopes. [[language:types]] Types ~~~~~ *Types* in Swift can be *atomic* or *composite*. An *atomic* type can be either a *primitive* type or a *mapped* type. Swift provides a fixed set of primitive types, such as +integer+ and +string+. A mapped type indicates that the actual data does not reside in CPU addressable memory (as it would in conventional programming languages), but in POSIX-like files. Composite types are further subdivided into *structures* and *arrays*. Structures are similar in most respects to structure types in other languages. image:swift-types.png[] [[language:primitive-types-and-values]] Primitive Types and Values ^^^^^^^^^^^^^^^^^^^^^^^^^^ A primitive type is a type that represents a single item stored in internal memory. The primitive types in Swift are +int+, +string+, +float+, and +boolean+. [[language:types:int]] int +++ The +int+ type represents a 32 bit integer. Integer value literals are of the form: [listing, syntax, Integer Literal] ---- ['+'|'-']+ ---- Examples: [listing, swift] ---- int a = +1; int b = -2; int c = 9999999; ---- string ++++++ A string represents a sequence of characters. String literals are enclosed in double quotes and have the following form: [listing, syntax, String Literal] ---- '"'( | )*'"' ---- Where ++ is any character except double quotes or a backslash ('''\'), and [listing, syntax, Escape Sequence] ---- := '\' ('n' | 'r' | 't' | 'b' | 'f' | '"' | '\') ---- The following table lists the meaning of the escape sequences: [options="header, footer",width="55%", cols="1,3"] |============================================== | Sequence | Meaning | +\n+ | new line (ASCII code +10+) | +\r+ | carriage return (ASCII code +13+) | +\t+ | tab (ASCII code +9+) | +\b+ | backspace (ASCII code +8+) | +\f+ | form feed (ASCII code +12+) | +\"+ | a literal double quote character | +\\+ | a literal backslash |============================================== Examples of string literals include: [listing, swift] ---- string a = "A string"; string b = "A string containing a \n newline"; string c = "\"A string in quotes\""; ---- [[language:types:float]] float +++++ Floats represent a double precision (64 bit) floating point number. Float literals have the following syntax: [listing, syntax, Float Literal] ---- ['+'|'-'] '.' [('e' | 'E') ['+'|'-'] ] ---- Example: [listing, swift] ---- float a = 1.0; float b = -1.2e-3; float c = 2e50; ---- boolean +++++++ A boolean represents a truth value. Boolean literals are either +'true'+ or +'false'+. [listing, swift] ---- boolean a = true; boolean b = false; ---- [[language:mapped-types]] Mapped types ^^^^^^^^^^^^ Mapped types are types that represent data that resides in a (single) file. They can be thought of as file references (or pointers to files). Users can define any number of mapped types to distinguish between different types of files used in a Swift program. A mapped type can be defined as follows: [listing, syntax, Type Declaration] ---- type ; ---- When declaring a mapped type, an optional +mapping+ can be specified in order to describe the location of the file represented by a variable. The following example declares a mapped type and variable that points to a file named +input.txt+: [listing, swift] ---- type image; image input <"input.txt">; ---- TIP: See also: <>, <>, <> [[language:structures]] Structures and Structure Expressions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Structures are types that can be used to encapsulate a fixed number of *fields* and are similar to structures in C. A structure's fields can mix primitive, mapped and composite types. The syntax for declaring a structure is as follows: [listing, syntax, Structure Declaration] ---- type { [ ;]+ } ---- Fields in a structure can be accessed as follows: [listing, syntax, Structure Field Access] ---- . ---- The following example declares and uses a structure named +Employee+ that holds some basic data of a hypothetical employee: [listing, swift] ---- type employee { string name; int id; string location; } employee e; e.name = "John Doe"; e.id = 1000; e.location = "Room 1401"; ---- It is also possible to initialize structure variables using a *structure expression*. The syntax of a structure expression is: [[language:structure-expressions]] [listing, syntax, Structure Expression] ---- { (: )* } ---- The last part of the employee example above can be simplified to: [listing, swift] ---- employee e; e = {name: "John Doe", id: 1000, location: "Room 1401"}; ---- TIP: See also: <>, <>, <>, <> [[language:arrays]] Arrays and Array Expressions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Swift arrays are data types that contain a variable number of items of the same type. Each item in an array has an associated *key* or *index*. Arrays can be declared as follows: [listing, syntax, Array Declaration] ---- '[' ']' ; ---- Key types are restricted to primitive types. If the +keyType+ is omitted, it defaults to +int+: [listing, syntax] ---- '[]' ; // this is equivalent to '[' int ']' ; ---- Arrays in Swift are automatically grown to accommodate the number of items stored in them. Additionally, arrays are *sparse*. In other words, array keys can be arbitrary values (as long as they match the declared key type). Array items are accessed using the following syntax: [listing, syntax, Array Item Access] ---- '[' ']' ---- For example, the following snippet of code declares an array with +int+ keys (the default) which stores +string+ values and adds a few items to it: [listing, swift] ---- string[] array; array[0] = "Zero"; array[2] = "Two"; array[100] = "One hundred"; ---- The following is an example of an array with strings as key values: [listing, swift] ---- float[string] constants; constants["PI"] = 3.14159; constants["e"] = 2.71828; ---- [[language:funny-array-struct-ref]] If the item type is a <> type, Swift allows a ``slicing'' access mode that produces an array with all the values of a particular field of the item type and with the same key type as the key type of the array. The syntax is the same as for structure field access. In other words, if +s+ is a structure containing some field +f+, and if +a+ is an array of +s+, then the following are equivalent: +a[].f+ and +a.f[]+. Example: [listing, swift] ---- type myStruct { int a; float b; } myStruct[] array = [{a: 1, b: 0.1}, {a: 2, b: 1.6}]; f(array.b); <1> ---- <1> Invokes function +f+ with an +float[]+ array equal to +[0.1, 1.6]+. Alternative ways of initializing arrays are: *array expressions*, *sparse array expressions*, and *range expressions*. [[language:array-expressions]] Array Expressions +++++++++++++++++ Array expressions have the following basic syntax: [listing, syntax, Array Expression] ---- '[' [ (, )*] ']' ---- When array expressions are used, indices are automatically created by Swift, starting from *zero* for the first array item and incrementing by one for each subsequent element: [listing, swift] ---- string[] array = ["Zero", "One", "Two"] trace(array[0]); // "Zero" trace(array[1]); // "One" trace(array[2]); // "Two" ---- [[language:sparse-array-expressions]] Sparse Array Expressions ++++++++++++++++++++++++ Sparse array expressions can be used to initialize an array with values that correspond to non-consecutive or non-integer keys. The syntax of a sparse array expression is: [listing, syntax, Sparse Array Expression] ---- { [: (, : )*] } ---- Examples: [listing, swift] ---- float[string] constants; constants = {"PI": 3.14159, "e": 2.71828}; string[] orders; orders = {1: "One", 10: "Ten", 100: "Hundred", 1000: "Thousand"}; ---- [[language:range-expressions]] Range Expressions +++++++++++++++++ Range expressions are compact way of describing arithmetic sequences. The syntax is: [listing, syntax, Range Expression] ---- '[' :[:] ']' ---- A range expression returns an array containing the sequence of numbers starting at ++, with the last element not greater than ++ and with a difference if ++ between two consecutive elements. The parameters must be numeric literals. If they are integers, then the returned array has type +int[]+ and the step is optional (assumed to be +1+ if missing). If the parameters are float literals, the type of the range expression is +float[]+ and the step is mandatory. The actual implementation generates lazy arrays for range expressions. Example: [listing, swift] ---- int[] a = [1:4]; // a = [1, 2, 3, 4] int[] b = [1:6:2]; // b = [1, 3, 5] int[] c = [0.0:10.0:3.33]; // c = [0.0, 3.33, 6.66, 9.99] ---- TIP: See also: <> Special Types ^^^^^^^^^^^^^ Special types are types that do not fall neatly into any of the above categories. There are two special types in Swift: +auto+ and +external+. [[language:types:auto]] The Auto Type +++++++++++++ The +auto+ type is used as a special array index type. Arrays declared with an +auto+ key type can be constructed progressively, without regard to what particular value the index for an item will be. It is used in conjunction with the <> operator (+<<+). The +auto+ type does not have associated literal values, and items in an array declared with +auto+ indices cannot be accessed randomly. Certain operations, such as the <> statement, can be used to associate a variable of type +auto+ with an opaque value that can be used to refer to items in arrays with +auto+ keys. The following example attempts to clarify this: [listing, swift] ---- int[auto] a; a << 1; a << 2; a << 4; a << 8; int[auto] b; foreach value, key in a { b[key] = a[key]; } // b is now an exact copy of a ---- [[language:external-type]] The external type +++++++++++++++++ The +external+ type is a special type of mapped type. It tells Swift to suspend its normal file management when dealing with variables of type +external+ (see <>). This is distinct from Swift's <>, dependency tracking mechanism>>, which remains in effect. The purpose of the +external+ type is to expose otherwise hidden dependencies to Swift in order to ensure correct functioning of a script. [[language:mapping-declarations]] Mapping Declarations ~~~~~~~~~~~~~~~~~~~~ Variables with a <> or a composite type containing mapped types will have an associated physical file for every mapped value. Mappers allow a user to specify how mapped values are associated with physical files. Mappers are specified as part of the variable declaration as follows: [listing, syntax, Mapping Declaration] ---- '<' ; [] '>'; ---- where [listing, syntax] ---- := = (, = )* ---- Mapper parameters can be specified in any order. Certain mapper parameters are mandatory, while others can be omitted and assume default values. Example: [listing, swift] ---- type file; file inf ; ---- As a shortcut, it is possible to use a string literal when only one mapped value (or file) is involved. The previous example is equivalent to: [listing, swift] ---- type file; file inf <"input.dat">; ---- The usefulness of mappers becomes more obvious when more complex data structures are involved. A number of mappers support deeply nested data structures and arrays. These can be used to automatically provide a mapping between non-trivial collections of files and Swift variables. If a variable of a mapped type is declared without an explicit mapping declaration, Swift will default to using the <>, which automatically assigns temporary files to mapped values. TIP: See also: <>, <>. [[language:expressions]] Expressions ~~~~~~~~~~~ Expressions are pieces of code that produce a value as a result. Previous sections already contain a few examples of expressions, namely <>, <>, and <>. In addition to that, value literals are also expressions. What follows is a description of all expression types in Swift: Primitive type literals:: Also called *constants*, these are literal values corresponding to Swift's primitive types. They are described in the section about <>. Variable references:: <> references produce the values currently stored in the referenced variable. When a variable name is used in an expression context, Swift applies the <> to determine the particular variable to be used and produces its value. Array expressions:: Used to construct array values. See <>. Sparse array expressions:: Used to construct array values with sparse keys. See <>. Range expressions:: Produce arrays containing arithmetic series. See <>. Structure expressions:: Used to construct structure values. See <>. Array subscript references:: Similar to variable references, array subscript expressions are used to obtain the value of a particular item in an <>. Structure field references:: Produce the value stored in a field of a structure-typed variable or, in the case of the <>, an array with values stored in a field of a structure-typed variable. Function expressions:: Function expressions produce the result of the application of a function to some parameters. For details, please see the section about <>. Operator expressions:: Operator expressions differ from function expressions in syntax and in that, unlike functions, operators are not user-defineable. For details, see the section on <>. [[language:operators]] Operators ~~~~~~~~~ Swift provides a standard set of arithmetic and logic operators. There are two types of operators: *unary* and *binary*. Unary operators are operators that have a single operand. They are used in *prefix notation*: [listing, syntax] ---- ---- Binary operators have two operands and are used in *infix notation*: [listing, syntax] ---- ---- Each operator has a precedence level. If two or more operators with the same precedence level appear consecutively in an expression, the expression is evaluated from left to right. In the following example, ++ is evaluated first, followed by ++: [listing, syntax] ---- ---- Specifically, + + is calculated, yielding some value which we will call ++. The value of the entire expression will then be + +: This behavior can be modified by using parentheses, which ensure that their contents is evaluated as a standalone sub-expression. In the previous example, parentheses can be used to force the evaluation of ++ first: [listing, syntax] ---- '(' ')' ---- If two or more consecutive operators have different precedence levels, then the operators are evaluated in the order of their precedence, starting with the lowest level. For example, multiplication has a lower precedence level than addition, so the following expression evaluates to +7+ rather than +8+: [listing, swift] ---- 1 + 2 * 3 ---- The following table lists the precedence level of Swift operators: [options="header",cols="^2,^4,<6", width="60%"] |========================================================= | Level | Operator(s) | Description | 1 | +!+ | Logical negation | 1 | +-+ | Negation operator | 2 | +*+, +/+, +%/+, +%%+ | Multiplicative operators | 3 | +\++, +-+ | Additive operators | 4 | +<+, +>+, +<=+, +>=+ | Relational operators | 5 | +==+, +!=+ | Equality operators | 6 | +&&+ | Logical AND | 7 | +\|\|+ | Logical OR |========================================================= The types of the operands are relevant, and there may exist multiple implementations for an operator, depending on the types of the operands. For example, the addition operator, +\++, can either add integers or floating point numbers, and the type of the resulting value will depend on the type of operands. When describing operators, the operand types and result types are indicated using the following syntax: [listing, syntax] ---- -> -> ---- The unary operators in Swift are: `! boolean -> boolean`:: Logical negation operator. `- int -> int`:: Integer negation operator. `- float -> float`:: Float negation operator The binary operators are: `int * int -> int`:: Integer multiplication `float * float -> float`:: Floating point multiplication `int * float -> float`:: Floating point multiplication. The integer operand is first converted to a float and then the multiplication is performed as with `float * float -> float`. `float * int -> float`:: Same as above. `int / int -> float`:: Floating point division. The operands are first converted into floats and then the division is performed. For example, the result of +3 / 2+ is +1.5+. `float / int -> float`, `int / float -> float`, `float / float -> float`:: Same as above except that for operands that are already +float+, no conversion is necessary. `int %/ int -> int`:: Integer division. Evaluates the quotient of the division of the first operand (divisor) with the second operand (dividend). The quotient is defined as the number with the largest absolute value such that `|quotient * dividend| < |divisor|`. + The quotient is negative if the divident and divisor have opposite signs. Example: + [listing,swift] ---- int q1 = 5 %/ 2; // 2 int q2 = -7 %/ 2; // -3 ---- `int %% int -> int`:: Integer remainder. The result of this operation is a number, `r = (a %% b)`, such that `(a %/ b) * b + r = a` `float %% float -> float`:: Floating point remainder. The result of `a %% b` is a floating point number `r`, such that `r = a - (b * q)`, where q is an integer whose magnitude is as large as possible while satisfying `|b * q| < |a|`. `int + int -> int`:: Integer addition. Self explanatory. `float + float -> float`, `float + int -> float`, `int + float -> float`:: Floating point addition. Also self explanatory. `string + any -> string`, `any + string -> string`:: String concatenation. Evaluates to a string formed by concatenating the string representation of the first operand with the string representation of the second operand. `int - int -> int`:: Integer subtraction `float - float -> float`, `float - int -> float`, `int - float -> float`:: Floating point subtraction. `int < int -> boolean`, `float < float -> boolean`:: Less than. Evaluates to +true+ if the first operand is strictly less than the second operand. Otherwise it evaluates to +false+. `int <= int -> boolean`, `float <= float -> boolean`:: Less or equal. Evaluates to +true+ if the first operand is less than or equal to the second operand. Otherwise it evaluates to +false+. `int > int -> boolean`, `float > float -> boolean`:: Greater than. Evaluates to +true+ if the first operand is strictly greater than the second operand. Otherwise it evaluates to +false+. `int >= int -> boolean`, `float >= float -> boolean`:: Greater or equal. Evaluates to +true+ if the first operand is greater than or equal to the second operand. Otherwise it evaluates to +false+. `any == any -> boolean`:: Equals. Evaluates to +true+ if the operands are equal. If one of the operands is an +int+ and the other a +float+, the +int+ is first converted to a +float+ after which the +float+ values are tested for equality. `any != any -> boolean`:: Not equals. The result of `a != b` is the same as the result of `!(a == b)`. `boolean && boolean -> boolean`:: Logical *AND*. Evaluates to +true+ if and only if both operands are +true+. `boolean || boolean -> boolean``:: Logical *OR*. Evaluates to +true+ if at least one operand is +true+. Program Structure ~~~~~~~~~~~~~~~~~ A general swift program has the following structure: [listing, syntax, Swift Program Structure] ---- * ( | )* ---- The Import Statement ^^^^^^^^^^^^^^^^^^^^ The +import+ statement can be used to bring definitions from an external Swift source file into the current program. The syntax is: [listing, syntax, Import Statement] ---- import '"' '"'; ---- where ++ is the path to a +.swift+ file without extension. For example: [listing, swift] ---- import "/usr/local/swift/lib/constants"; import "../lib/functions"; import "defs"; ---- If a relative path is specified as a *target*, Swift will attempt to resolve the file using directory in which the current Swift script is running. If the *target* is a plain file name, Swift will first look for the corresponding file in the current directory. If no such file is found in the current directory, Swift will attempt to find the file in directories specified using the +SWIFT_LIB+ environment variable. The +SWIFT_LIB+ variable can contain one or more directories separated by the system's path separator character (":" in Linux / OS X and ";" in Windows). Example: [listing, shell] ---- export SWIFT_LIB=${HOME}/swift/defs:${HOME}/swift/functions ---- [[language:functions]] Functions ~~~~~~~~~ Functions represent code abstractions. They can have zero or more *formal parameters* (or formal input parameters) and zero or more *formal return parameters* (or formal output parameters). [[language:function-declarations]] Function Declarations ^^^^^^^^^^^^^^^^^^^^^ Functions are declared using the following syntax: [listing, syntax, Function Declaration] ---- '(' ')' { } := [ '(' (, )* ')' ] := [ (, )* ] := [ = ] ---- Function Invocation ^^^^^^^^^^^^^^^^^^^ A function is ``applied'' or used through a function invocation. When a function is invoked, a number of *actual parameters* is supplied. They must correspond to formal parameters in the function declaration. A function invocation has the following form: [listing, syntax, Function Invocation] ---- [] = (); := | '(' (, )* ')' ] := [] [ = ] := [ , ] [ ] := (, )* := = (, = )* ---- Alternatively, functions with a single return argument can be invoked as part of a function invocation <>: [listing, syntax] ---- '(' ')' ---- The following example shows a function definition and invocation: [listing, swift] ---- (int result) add(int a, int b) { result = a + b; } int sum = add(1, 5); ---- Both output and input parameters are optional. The following example declares and invokes a function with no output parameters: [listing, swift] ---- printMessage(string msg) { trace("Message: ", msg); } printMessage("Hello world!"); ---- Correspondingly, the following example declares and invokes a function with no input parameters: [listing, swift] ---- (int result) one() { result = 1; } int n = one(); ---- As hinted by the function declaration syntax, input parameters can have a default value, in which case they become *optional parameters*. Optional parameters can be omitted when a function is invoked, in which case they assume the default value specified in the function declaration. If specified, an optional argument must be passed as a keyword actual parameter. Keyword parameters are said to be *passed by name*. Example: [listing, swift] ---- (int result) increment(int n, int amount = 1) { result = n + amount; } int a = 10; int b = increment(a); <1> int c = increment(a, amount = 2); <2> ---- <1> the default value for +amount+ is used, so +b+ will be +11+ <2> +c+ will be +12+ Parameter Binding ^^^^^^^^^^^^^^^^^ The are a number of rules that govern the binding of actual parameters to formal parameters. If a function has more than one formal output parameter, then the binding can be done either positionally or by name, but the two cannot be mixed. If parameters are passed by name, the order in which actual output parameters are specified can be arbitrary. The following example illustrates both options: [listing, swift] ---- (int a, int b, int c) f() { a = 1; b = 2; c = 3; } // positional binding int a1, b1, c1; (a1, b1, c1) = f(); // keyword binding int a2, b2, c2; (c2 = c, b2 = b, a2 = a) = f(); ---- Additionally, actual output parameters can be declared as part of the function invocation: [listing, swift] ---- (int a3, int b3, int c3) = f(); ---- As seen previous, input parameters can also be passed possitionally or by name. In particular, optional parameters must always be passed by name. The two method can be mixed with the following restriction: parameters passed positionally must be specified first. In other words, no positional parameters are allowed after a keyword parameter. As is the case with named output parameters, the order in which named input parameters are passed is not relevant. Example: [listing, swift] ---- (int result) addFour(int a, int b, int c, int d = 1) { result = a + b + c + d; } int r1 = addFour(d = 4, c = 3, b = 2, a = 1); int r2 = addFour(1, 2, d = 4, c = 3); ---- By contrast, the following invocations of +addFour+ are illegal: [listing, swift] ---- int r3 = addFour(1, 2, 3, 4); <1> int r4 = addFour(a = 1, 2, 3, d = 4); <2> ---- <1> Illegal: parameter +d+ is optional and must be passed by name <2> Illegal: positional parameters follow a named parameter [[language:application-functions]] Application Functions ^^^^^^^^^^^^^^^^^^^^^ Application functions are a mechanism to give command-line applications the appearence of a Swift function. This allows a Swift program to invoke a command line application as if it were a normal Swift function. Application functions are declared as follows: [listing, syntax, Application Functions] ---- app '(' ')' { * *; } := | := := (stdout | stderr | stdin) = ---- The formal parameters have the same form as in the case of normal <>. The ++ can either be a string naming a path to an executable (or just an executable), or an identifier that will be <> by the Swift run-time to an executable. The expressions for the command line arguments must evaluate to primitive values, which will be converted by Swift to strings and passed as the application's command line. The expressions for standard stream redirects must be of type +string+ and name files in/from which the applications' streams will be redirected. Example: [listing,swift] ---- app (file outf) sort(file inf, int field) { sort "-k" filename(inf) stdout = filename(outf); } ---- TIP: See also: <> Statements ~~~~~~~~~~ Statements in Swift are entities that express relationships between data. [[language:assignment-statement]] Assignment Statement ^^^^^^^^^^^^^^^^^^^^ The assignment statement associates a <> variable or <> member of a declared variable or an <> item of a declared variable with the result of an <> (``expression'' may sound fancy, but it includes primitive literals). The syntax for the assignment statement is: [listing, syntax, Assignment Statement] ---- = ; := ( | )* := '[' ']' := '.' ---- [[language:lvalue]] LValues +++++++ Examples: [listing, swift] ---- int a, b, c; int[] v; a = 1; b = a + 2; c = abs(-b); v[1] = a; v[2] = b; ---- [[language:append-statement]] Append Statement ^^^^^^^^^^^^^^^^ The append statement allows appending to an <> declared with the <> key type. The syntax is: [listing, syntax, Append Statement] ---- '<<' ; ---- Example: [listing, swift] ---- int[auto] a; a << 1; a << 2; a << 4; ---- If Statement ^^^^^^^^^^^^ The if statement allows the expression of conditional data relationships based on the value of some arbitrary boolean expression. The syntax is: [listing, syntax] ---- := if '(' ')' [ (else ) | (else ) ] := ; := ; := { * } ---- If ++ evaluates to +true+, then ++ takes effect. If ++ evaluates to +false+, then there are two choices, depending on whether an the exact form of the +else+ part: +else+ is followed by an ++:: the nested if statement is evaluated +else+ is followed by ++:: ++ takes effect. no +else+ part is specified:: the effect of the overall +if+ statement is the same as if no statement was present at all. Example: [listing, swift, If Statement] ---- int x = ...; int step, sign; if (x >= 0) { step = 1; } else { step = 0; } if (x > 0) { sign = 1; } else if (x < 0) { sign = -1; } else { sign = 0; } ---- Switch Statement ^^^^^^^^^^^^^^^^ The switch statement is a convenient way of expressing conditional relationships based on multiple possible values of an expression. The syntax is: [listing, syntax, Switch Statement] ---- switch '(' ')' { ( | )* } := case : := default: := := ---- The switch statement tests the value of the expression successively against ++. Once a match is found, the corresponding ++ are evaluated. If none of ++ are equal to the switch expression, and if a ++ is present, the statements corresponding to ++ are evaluated. If two or more case expressions evaluate to the same value, and if the switch expression is equal to that value, only the statements for the first case will be evaluated. [[language:foreach-statement]] Foreach Statement ^^^^^^^^^^^^^^^^^ The foreach statement allows parametrization of statements based on the values (and optionally keys) of an array: [listing, syntax, Foreach Statement] ---- foreach [, ] in { } ---- The ++ must be of <> type. The +foreach+ statement evaluates the contained ++ for each value stored in the array. At each evaluation the value is bound to the ++. If a ++ is also specified, the corresponding array index will be bound to it. The types of ++ and ++ are automatically inferred by the Swift compiler from the type of ++ and they do not need to be declared separately. By default, +foreach+ parallelizes the evaluation of ++ as much as possible. For details about that, see <>. Here is an example foreach statement without an index variable: [listing, swift] ---- int[] squares; foreach x in [0:16] { squares[x] = x * x; } ---- And one which does use the index variable: [listing, swift] ---- int[] a = ...; int[] b; foreach value, index in a { b[index] = value; } ---- Iterate Statement ^^^^^^^^^^^^^^^^^ The +iterate+ statement can be used to implement convergence algorithms in which a set of statements is evaluated repeatedly until a certain condition is met. A counter is provided to distinguish between the evaluation steps. The +iterate+ statement has the following form: [listing, syntax, Iterate Statement] ---- iterate { } until '(' ')'; ---- The ++ is an integer typed variable and it does not need to be declared separately. Its initial value is +0+. The ++ must evaluate to a +boolean+ value. The iterate statement performs the following steps: 1. Initialize ++ to +0+ 2. Evaluate ++ 3. Increment ++ 4. Evaluate ++. If it is +true+, +iterate+ completes. 5. Go to step 2 Example: [listing, swift] ---- vector b = ...; vector[] a; a[0] = initialGuess(); iterate i { vector nextGuess = computeNextVector(a[i], op(a[i])); a[i + 1] = nextGuess; } until (error(b, op(nextGuess)) < 0.1); ---- The termination expression may depend on the index variable or variables declared inside the body of +iterate+. However, the values of the latter will reflect the values calculated as part of the last evaluation of the body, and may not reflect the incremented value of the iteration variable. The following example illustrates this issue: [listing, swift] ---- iterate i { trace(i); <1> } until(i == 1); iterate i { trace(i); <2> int j = i; } until(j == 1); ---- <1> Will print +0+ <2> Will print +0+ and +1+ In the first case, +i+ starts as +0+, the +trace+ is evaluated (and prints a +0+), then +i+ is incremented to +1+ and the termination condition is evaluated. The termination condition will be +true+ on the first evaluation. By contrast, in the second case, during the first evaluation of the body, the variable +j+ is assigned the initial value of +i+, which is +0+. The index variable, +i+, is then incremented to +1+. However, the termination expression refers to +j+, whose last value is +0+, and therefore it evaluates to +false+.