Copyright © 1996, 1997 Lucent Technologies Inc. All rights reserved.

8.2 Monadic expressions

Monadic expressions are expressions with monadic operators, together with a few more specialized notations:


monadic-expression: term monadic-operator monadic-expression array [ expression ] of data-type array [ expressionopt ] of { init-list } list of { expression-list } chan of data-type data-type monadic-expression monadic-operator: one of + - ! ~ ref * <- hd tl len

8.2.1 Monadic additive operators

The - operator produces the negative of its operand, which must have an arithmetic type. The type of the result is the same as the type of its operand.

The + operator has no effect; it is supplied only for symmetry. However, its argument must have an arithmetic type and the type of the result is the same.

8.2.2 Logical negation

The ! operator yields the int value 1 if its operand has the value 0, and yields 0 otherwise. The operand must have type int.

8.2.3 One's complement

The ~ operator yields the 1's complement of its operand, which must have type int or byte. The type of the result is the same as that of its operand.

8.2.4 Reference and indirection operators

If e is an expression of an adt type, then ref e is an expression of ref adt type whose value refers to (points to) an anonymous object with value e. The ref operator differs from the unary & operator of C; it makes a new object and returns a reference to it, rather than generating a reference to an existing object.

If e is an expression of type ref adt, then * e is the value of the adt itself. The value of e must not be nil.

For example, in

	Point: adt { ... };
	p: Point;
	pp: ref Point;
	p = Point(1, 2);
	pp = ref p;	# pp is a new Point; *pp has value (1, 2)
	p = Point(3, 4);	# This makes *pp differ from p
	*pp = Point(4, 5);	# This does not affect p
the expression *pp at first refers to a copy of the value stored in p, so *pp == p is true; however, when p is changed later, *pp does not change.

8.2.5 Head and tail

The operand of the hd operator must be a non-empty list. The value is the first member of the list and has that member's type.

The operand of the tl operator must be a non-empty list. The value is the tail of the list, that is, the part of the list after its first member. The tail of a list with one member is nil.

8.2.6 Length

The operand of the len operator is a string, an array, or a list. The value is an int giving the number of elements currently in the item.

8.2.7 Channel communication

The operand of the communication operator <- has type chan of sometype. The value of the expression is the first unread object previously sent over that channel, and has the type associated with the channel. If the channel is empty, the program delays until something is sent.

As a special case, the operand of <- may have type array of chan of sometype. In this case, all of the channels in the array are tested; one is fairly selected from those that have data. The expression yields a tuple of type (int, sometype ); its first member gives the index of the channel from which data was read, and its second member is the value read from the channel. If no member of the array has data ready, the expression delays.

Communication channels are treated more fully in §§9.8 and 9.12 below with the discussion of the alt and spawn statements.

8.2.8 Creation of arrays

In the expressions


array [ expression ] of data-type array [ expressionopt ] of { init-list ,opt }
the value is a new array of the specified type. In both forms, the expression must be of type int, and it supplies the size of the array. In the first form, the type is given, and the values in the array are initialized as appropriate to the underlying type. In the second form, a comma-separated list of values to initialize the array is given, optionally followed by a trailing comma. The type of the array is taken from the types of the initializers, which must all be the same. The list of initializers has the syntax

init-list: element init-list , element element: expression expression => expression * => expression
In an init-list of plain expressions (without =>), the members of the array are successively initialized with the corresponding elements of the init-list. An element of the form e1=>e2 initializes the member of the array at subscript e1 with the expression e2. After such an element has been given, subsequent simple elements (without =>) begin initializing at position e1+1 and so on. Each of the first expressions must be of type int and must evaluate to a constant (§8.5).

If an element of the form * =>e2 is present, all members of the array not otherwise initialized are set to the value e2. The expression e2 is evaluated for each subscript position, but in an undefined order. For example,

	arr := array[3] of { * => array[3] of { * => 1 } };
yields a 2-dimensional array (actually an array of arrays) filled with 1's.

If the expression giving the size of the array is omitted, its size is taken from the largest subscript of a member explicitly initialized. It is erroneous to initialize a member twice.

8.2.9 Creation of lists

The value of an expression


list of { expression-list }
is a list consisting of the expressions given. The types of the expressions must be identical, and this type is the underlying type of the list. The first expression is the head of the list, and the remaining expressions are a list constituting its tail. Where a list is expected, nil specifies an empty list.

8.2.10 Creation of channels

The value of


chan of data-type
is an initialized channel of the specified type. Just a declaration of a channel leaves it initialized only to nil; before it can be used it must be created. For example,
	ch: chan of int;		# just declares, sets ch to nil
	. . .
	ch = chan of int;	# creates the channel and assigns it

8.2.11 Casts

An expression of the form


data-type monadic-expression
in which a type name is followed by an expression is called a cast, and converts the monadic expression to the named type. Only certain specialized forms are provided for.

8.2.11.1 Arithmetic casts

In arithmetic casts, the named type must be one of byte, int, big, or real, and the monadic-expression must have arithmetic type. For example,

	byte 10
is an expression of byte type and value 10. When real values are converted to integral ones, they are rounded to the nearest integer, and away from 0 if there is a tie. The effect of overflow during conversion is undefined.

8.2.11.2 Casts to strings

Here the named data type is string. In a first form, the monadic expression has arithmetic type (byte, int, big, or real) and the value is a string containing the decimal representation of the value, which may be either positive or negative. A real operand is converted as if by format %g, and if the result is converted back to real, the original value will be recovered exactly.

In a second form, the monadic expression has type array of byte. The value is a new string containing the Unicode characters obtained by interpreting the bytes in the array as a UTF-8 representation of that string. (UTF-8 is a representation of 16-bit Unicode characters as one, two, or three bytes.) The result of the conversion is undefined if the byte array ends within a multi-byte UTF-8 sequence.

8.2.11.3 Casts from strings

In a first form, the monadic expression is a string, and the named type is an arithmetic type. The value is obtained by converting the string to that type. Initial white space is ignored; after a possible sign, conversion ceases at the first character not part of a number.

In a second form, the named type is array of byte and the monadic-expression is a string. The value is a new array of bytes containing the UTF-8 representation of the Unicode characters in the string. For example,

	s := "Ångström";
	a := array of byte s;
	s = string a;
takes the string s apart into bytes in the second line, and puts it back in the third. The length of s is 8, because it contains that many characters; the length of a is larger, because some of its characters require more than one byte in the UTF-8 representation.

8.2.11.4 Casts to adt and ref adt

Here the named type is that of an adt or ref adt, and the monadic expression is a comma-separated list of expressions within parentheses. The value of the expression is an instance of an adt of the named type whose data members are initialized with the members of the list, or whose single data member is initialized with the parenthesized expression. In case the type is ref adt, the value is a reference to the new instance of the adt.

The expressions in the list, read in order, correspond with the data members of the adt read in order; their types and number must agree. Placement of any function members of the adt is ignored. For example,

	Point: adt {
		x: int;
		eq: fn (p: Point): int;
		y: int;
	};
	. . .
	p: Point;
	p = Point(1, 2);
puts in p a Point whose x value is 1 and whose y value is 2. The declaration and assignment could also be written
	p := Point(1, 2);

05/Jun/97