]> Cypherpunks repositories - gostls13.git/commitdiff
Clarify conversions, include making them constructors for arrays etc.
authorRob Pike <r@golang.org>
Fri, 9 May 2008 03:23:01 +0000 (20:23 -0700)
committerRob Pike <r@golang.org>
Fri, 9 May 2008 03:23:01 +0000 (20:23 -0700)
SVN=118194

doc/go_lang.txt

index 36cb941cf9d5d715ecd769de025c0fe241961151..54cae82cc7f54dad2de09379a206f1adf8801bd6 100644 (file)
@@ -623,54 +623,6 @@ followed by a parenthesized expression list.  In effect, they are a
 conversion from expression list to compound value.
 
 
-Array literals
-----
-
-Array literals represent array values. All the contained expressions must
-be of the same type, which is the element type of the resulting array.
-
-  ArrayLit = ArrayType "(" [ ExpressionList ] ")" .
-
-  []int()
-  []int(1, 2, 3)
-  []string("x", "y")
-
-Unresolved issues: Are elements converted?  What about length?
-
-
-Map Literals
-----
-
-Map literals represent map values.  They comprise a list of (key, value)
-pairs written as successive values.
-All keys must have the same type; all values must have the same type.
-
-
-  MapLit = MapType "(" KeyValueList ")" .
-  KeyValueList = [ KeyValue { "," KeyValue } ].
-  KeyValue = Expression "," Expression .
-
-  [string]map int("one",1, "two",2)
-  [int]map bool(2,true, 3,true, 5,true, 7,true)
-
-Unresolved issues: Are elements converted?
-Colon for a separator or comma?
-
-
-Struct literals
-----
-
-Struct literals represent struct constants.  They comprise a list of
-expressions that represent the individual fields of a struct.  The
-individual expressions must match those of the specified struct type.
-
-  StructLit = StructType "(" [ ExpressionList ] ")" .
-
-  Point(2, 3)
-  ColoredPoint(4, 4, "green")
-  struct { a, b int } (7, 8)
-
-
 Pointer types
 ----
 
@@ -699,8 +651,6 @@ can be constructed such as:
 By the end of the package source, all forward-declared types must be
 fully declared if they are used.
 
-There are no pointer literals.
-
 
 Channel types
 ----
@@ -727,9 +677,6 @@ particular to dereference a channel pointer.
   var ch *chan int;
   ch = new(chan int);  // new returns type *chan int
 
-There are no channel literals.
-
-
 Function types
 ----
 
@@ -879,8 +826,6 @@ compatible interface type.  It is legal to assign an interface
 variable to any struct pointer variable but if the struct type is
 incompatible the result will be nil.
 
-There are no interface literals.
-
 
 The polymorphic "any" type
 ----
@@ -949,9 +894,7 @@ vice versa. Note that the declaration order of the methods is not relevant.
 Literals
 ----
 
-  Literal = BasicLit | CompoundLit .
-  BasicLit = char_lit | string_lit | int_lit | float_lit | "nil" .
-  CompoundLit = ArrayLit | MapLit | StructLit | FunctionLit .
+  Literal = char_lit | string_lit | int_lit | float_lit | FunctionLit | "nil" .
 
 
 Declarations
@@ -1159,8 +1102,9 @@ Expression syntax is based on that of C but with fewer precedence levels.
     Expression "." "(" Type ")" .
   
   Call = Expression "(" [ ExpressionList ] ")" .
-  Conversion = TypeName "(" Expression ")" |
-               "convert" "(" Type "," Expression ")" .
+  Conversion = "convert" "(" Type [ "," ExpressionList ] ")" |
+               ConversionType "(" [ ExpressionList ] ")" .
+  ConversionType = TypeName | ArrayType | MapType | StructType | InterfaceType .
   Allocation = "new" "(" Type [ "," Expression ] ")" .
 
   binary_op = log_op | rel_op | add_op | mul_op .
@@ -1245,7 +1189,7 @@ The keyword
 represents the ``zero'' value for a pointer type or interface type.
 
 The only operations allowed for nil are to assign it to a pointer or
-interface value and to compare it for equality or inquality with a
+interface variable and to compare it for equality or inequality with a
 pointer or interface value.
 
   var p *int;
@@ -1261,6 +1205,8 @@ TODO: how does this definition jibe with using nil to specify
 conversion failure if the result is not of pointer type, such
 as an any variable holding an int?
 
+TODO: if interfaces were explicitly pointers, this gets simpler.
+
 
 Allocation
 ----
@@ -1294,40 +1240,82 @@ TODO: argument order for dimensions in multidimensional arrays
 Conversions
 ----
 
-There are three ways to convert a value from one type to another.
-
-The most general is a call to the intrinsic special function "convert"
-with arguments the type name and the value to be converted.
-
-       var i int = convert(int, PI * 1000.0);
-       chars_as_ints := convert([]int, "now is the time");
-
-If the destination type is a known type name, the conversion can be
-rewritten to look syntactically like a call to a function with that
-name.
-
-       i := int(PI * 1000.0);
-       s := AStructType(an_interface_variable);
-
-A conversion can be written as a parenthesized type after a period.
-Although intended for ease of conversion within a method call chain,
-this form works in any expression context.
+Conversions create new values of a specified type derived from the
+elements of a list of expressions of a different type.
+
+The most general conversion takes the form of a call to "convert",
+with the result type and a list of expressions as arguments:
+
+       convert(int, PI * 1000.0);
+       convert([]int, 1, 2, 3, 4);
+
+If the result type is a basic type, pointer type, or
+interface type, there must be exactly one expression and there is a
+specific set of permitted conversions, detailed later in the section.
+These conversions are called ``simple conversions''.
+TODO: if interfaces were explicitly pointers, this gets simpler.
+
+       convert(int, 3.14159);
+       convert(uint32, ~0);
+       convert(interface{}, new(S))
+       convert(*AStructType, interface_value)
+
+For other result types - arrays, maps, structs - the expressions
+form a list of values to be assigned to successive elements of the
+resulting value.  If the type is an array or map, the list may even be
+empty.  Unlike in a simple conversion, the types of the expressions
+must be equivalent to the types of the elements of the result type;
+the individual values are not converted.  For instance, if result
+type is []int, the expressions must be all of type int, not float or
+uint.  (For maps, the successive elements must be key-value pairs).
+For arrays and struct types, if fewer elements are provided than
+specified by the result type, the missing elements are
+initialized to the respective ``zero'' value for that element type.
+
+These conversions are called ``compound conversions''.
+
+       convert([]int)  // empty array of ints
+       convert([]int, 1, 2, 3)
+       convert([5]int, 1, 2);  // == convert([5]int, 1, 2, 0, 0, 0)
+       convert(map[string]int, "1", 1, "2", 2)
+       convert(struct{ x int; y float }, 3, sqrt(2.0))
+
+There is syntactic help to make conversion expressions simpler to write.
+
+If the result type is of ConversionType (a type name, array type,
+map type, structure type, or interface type, essentially anything
+except a pointer), the conversion can be rewritten to look
+syntactically like a call to a function whose name is the type:
+
+       int(PI * 1000.0);
+       AStructType(an_interface_variable);
+       struct{ x int, y float }(3, sqrt(2.0))
+       []int(1, 2, 3, 4);
+       map[string]int("1", 1, "2", 2);
+       
+This notation is convenient for declaring and initializing
+variables of composite type:
+
+       primes := []int(2, 3, 5, 7, 9, 11, 13);
+
+Simple conversions can also be written as a parenthesized type after
+an expression and a period.  Although intended for ease of conversion
+within a method call chain, this form works in any expression context.
+TODO: should it?
 
        var s *AStructType = vec.index(2).(*AStructType);
        fld := vec.index(2).(*AStructType).field;
-       f := 1000.(float);
+       a := foo[i].(string);
 
-TODO: are there parameters to any conversions? go.y has oexpr_list as the
-contents of a TypeName() conversion; i expected expr instead and that's what
-the others have.
-
-Only some conversions are permitted.
+As said, for compound conversions the element types must be equivalent.
+For simple conversions, the types can differ but only some combinations
+are permitted:
 
 1) Between integer types.  If the value is a signed quantity, it is
 sign extended to implicit infinite precision; otherwise it is zero
-extended.  It is then truncated to fit in the destination type size.
+extended.  It is then truncated to fit in the result type size.
 For example, uint32(int8(0xFF)) is 0xFFFFFFFF.  The conversion always
-yields a valid value; for instance, there is no signal for overflow.
+yields a valid value; there is no signal for overflow.
 
 2) Between integer and floating point types, or between floating point
 types.  To avoid overdefining the properties of the conversion, for
@@ -1344,6 +1332,18 @@ should incompatible conversions fail immediately?
 conversions yield nil values. TODO: is nil right here? Or should
 incompatible conversions fail immediately?
 
+5) Strings permit two special conversions.
+
+5a) Converting an integer value yields a string containing the UTF-8
+representation of the integer.
+
+       string(0x65e5)  // "\u65e5"
+
+5b) Converting an array of uint8s yields a string whose successive
+bytes are those of the array.  (Recall byte is a synonym for uint8.)
+
+       string([]byte('h', 'e', 'l', 'l', 'o')) // "hello"
+
 Note that there is no linguistic mechanism to convert between pointers
 and integers. A library may be provided under restricted circumstances
 to acccess this conversion in low-level code but it will not be available