@@ -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 posess 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