@@ -45,7 +45,145 @@ There are 3 forms of valid type signatures in Nu:
4545-  Basic: E.g. ` int ` , ` bool ` , ` string ` , etc.
4646-  Compound:
4747  -  ` list<string> ` ,
48-     ` record<type: int, bar: string> ` 
48+     ` record<type: int, bar: string> ` ,
49+     ` table<name: string, age: int> ` 
50+ -  Sum types (aka type alternatives): E.g. ` oneof<int, string> ` 
51+ 
52+ ### List types  
53+ 
54+ -  ` list<something> `  - Read as ` list of elements of type something ` 
55+ 
56+ For example, ` list<int> `  would specify a list of integers:
57+ 
58+ ``` nu 
59+ def sum_two []: list<int> -> int { $in.0 + $in.1 } 
60+ 
61+ [1 11 111 1111] | sum_two 
62+ # => 12 
63+ 
64+ ["abc" "def" "ghi"] | sum_two 
65+ # error: command doesn't support list<string> input 
66+ ``` 
67+ 
68+ -  ` list `  - If no element type is specified, this is equivalent to ` list<any> ` .
69+ 
70+ ``` nu 
71+ def second []: list -> any { $in.1 } 
72+ 
73+ [1 11 111 1111] | second 
74+ # => 11 
75+ 
76+ ["abc" "def" "ghi"] | second 
77+ # => def 
78+ ``` 
79+ 
80+ ### Record types  
81+ 
82+ -  ` record<key_name: value_type> `  - Read as ` record containing a key key_name with value of type value_type ` 
83+ 
84+ ``` nu 
85+ def greet [person: record<name: string>] { 
86+   $"Hello, ($person.name)!" 
87+ } 
88+ 
89+ greet { name: Ellie } 
90+ # => Hello, Ellie! 
91+ 
92+ greet "Who" 
93+ # error: a string is not a record 
94+ 
95+ greet { given_name: Bob } 
96+ # error: the record is missing a "name" key 
97+ 
98+ greet { name: [] } 
99+ # error: the record's "name" value can't be coerced to string 
100+ 
101+ # The record may contain more keys besides the specified ones though: 
102+ greet { name: Bob, age: 32 } 
103+ # => Hello, Bob! 
104+ ``` 
105+ 
106+ We may also specify multiple keys that a record must possess as a comma separated ` name: value_type `  list. E.g.:
107+ 
108+ ``` nu 
109+ def greet [person: record<name: string, birthday: datetime, job: string>] { 
110+   print $"Hello, ($person.name) the ($person.job)!" 
111+   if ($person.birthday | format date "%m-%d") == (date now | format date "%m-%d") { 
112+     print "Happy birthday!" 
113+   } 
114+ } 
115+ 
116+ greet { name: Bob, job: Builder, birthday: 1998-11-28 } 
117+ # => Hello, Bob the Builder! 
118+ ``` 
119+ 
120+ Similar to lists, ` record `  or ` record<> `  specifies a record with any keys (or even an empty record):
121+ 
122+ ``` nu 
123+ def first_key []: record -> string { 
124+   columns | first 
125+ } 
126+ 
127+ { name: Ellie } | first_key 
128+ # => name 
129+ 
130+ { given_name: Bob } | first_key 
131+ # => given_name 
132+ 
133+ # this will pass type checking (but produce a runtime error) 
134+ {} | first_key 
135+ ``` 
136+ 
137+ ### Table types  
138+ 
139+ -  ` table<column_name: value_type> `  - Read as ` table containing a column column_name with values of type value_type ` 
140+ 
141+ Tables are just lists of records, so table types work very similarly to record types:
142+ 
143+ ``` nu 
144+ let data: table<date: datetime, temps: list<number>, condition: string> = [ 
145+     [date                        temps                                   condition      ]; 
146+     [2022-02-01T14:30:00+05:00,  [38.24, 38.50, 37.99, 37.98, 39.10],   'sunny'       ], 
147+     [2022-02-02T14:30:00+05:00,  [35.24, 35.94, 34.91, 35.24, 36.65],   'sunny'       ], 
148+     [2022-02-03T14:30:00+05:00,  [35.17, 36.67, 34.42, 35.76, 36.52],   'cloudy'      ], 
149+     [2022-02-04T14:30:00+05:00,  [39.24, 40.94, 39.21, 38.99, 38.80],   'rain'        ] 
150+ ] 
151+ 
152+ def temp_avg [] : table<date: datetime, temps: list<number>> -> table<date: datetime, avg_temp: number> { 
153+   insert avg_temp {|record| $record.temps | math avg} 
154+   | reject temps 
155+ } 
156+ 
157+ # Note that both the input and output table contain a column "condition", which 
158+ # is not mentioned in the type signature of temp_avg. This is fine. 
159+ $data | temp_avg 
160+ # => ╭───┬─────────────┬───────────┬──────────╮ 
161+ # => │ # │    date     │ condition │ avg_temp │ 
162+ # => ├───┼─────────────┼───────────┼──────────┤ 
163+ # => │ 0 │ 3 years ago │ sunny     │    38.36 │ 
164+ # => │ 1 │ 3 years ago │ sunny     │    35.60 │ 
165+ # => │ 2 │ 3 years ago │ cloudy    │    35.71 │ 
166+ # => │ 3 │ 3 years ago │ rain      │    39.44 │ 
167+ # => ╰───┴─────────────┴───────────┴──────────╯ 
168+ ``` 
169+ 
170+ ### Sum types  
171+ 
172+ -  ` oneof<a, b, c> `  - Read: one of ` a ` , ` b `  or ` c ` 
173+ 
174+ Example:
175+ 
176+ ``` nu 
177+ def foo [ 
178+     param: oneof<binary, string> 
179+ ] { 
180+   if ($param | describe) == "binary" { 
181+     $param | first 3 
182+   } else { 
183+     $param | str substring 0..<3 
184+   } 
185+ } 
186+ ``` 
49187
50188## Custom command parameters and flags  
51189
0 commit comments