docs: format more code blocks (#8011)
parent
a8378273a5
commit
6720dbef52
284
doc/docs.md
284
doc/docs.md
|
@ -213,9 +213,9 @@ or thinking about the order of files and declarations.
|
||||||
|
|
||||||
### Returning multiple values
|
### Returning multiple values
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
fn foo() (int, int) {
|
fn foo() (int, int) {
|
||||||
return 2, 3
|
return 2, 3
|
||||||
}
|
}
|
||||||
|
|
||||||
a, b := foo()
|
a, b := foo()
|
||||||
|
@ -226,21 +226,21 @@ c, _ := foo() // ignore values using `_`
|
||||||
|
|
||||||
### Variable number of arguments
|
### Variable number of arguments
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
fn sum(a ...int) int {
|
fn sum(a ...int) int {
|
||||||
mut total := 0
|
mut total := 0
|
||||||
for x in a {
|
for x in a {
|
||||||
total += x
|
total += x
|
||||||
}
|
}
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
println(sum()) // Output: 0
|
|
||||||
println(sum(1)) // 1
|
|
||||||
println(sum(2,3)) // 5
|
|
||||||
|
|
||||||
|
println(sum()) // 0
|
||||||
|
println(sum(1)) // 1
|
||||||
|
println(sum(2, 3)) // 5
|
||||||
// using array decomposition
|
// using array decomposition
|
||||||
a := [2,3,4]
|
a := [2, 3, 4]
|
||||||
println(sum(...a)) // <-- using prefix ... here. output: 9
|
println(sum(...a)) // <-- using prefix ... here. output: 9
|
||||||
b := [5, 6, 7]
|
b := [5, 6, 7]
|
||||||
println(sum(...b)) // output: 18
|
println(sum(...b)) // output: 18
|
||||||
```
|
```
|
||||||
|
@ -402,12 +402,11 @@ negative values).
|
||||||
|
|
||||||
### Strings
|
### Strings
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
name := 'Bob'
|
name := 'Bob'
|
||||||
println(name.len)
|
println(name.len)
|
||||||
println(name[0]) // indexing gives a byte B
|
println(name[0]) // indexing gives a byte B
|
||||||
println(name[1..3]) // slicing gives a string 'ob'
|
println(name[1..3]) // slicing gives a string 'ob'
|
||||||
|
|
||||||
windows_newline := '\r\n' // escape special characters like in C
|
windows_newline := '\r\n' // escape special characters like in C
|
||||||
assert windows_newline.len == 2
|
assert windows_newline.len == 2
|
||||||
```
|
```
|
||||||
|
@ -436,7 +435,7 @@ Both single and double quotes can be used to denote strings. For consistency,
|
||||||
|
|
||||||
For raw strings, prepend `r`. Raw strings are not escaped:
|
For raw strings, prepend `r`. Raw strings are not escaped:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
s := r'hello\nworld'
|
s := r'hello\nworld'
|
||||||
println(s) // "hello\nworld"
|
println(s) // "hello\nworld"
|
||||||
```
|
```
|
||||||
|
@ -445,7 +444,7 @@ println(s) // "hello\nworld"
|
||||||
|
|
||||||
Basic interpolation syntax is pretty simple - use `$` before a variable name.
|
Basic interpolation syntax is pretty simple - use `$` before a variable name.
|
||||||
The variable will be converted to a string and embedded into the literal:
|
The variable will be converted to a string and embedded into the literal:
|
||||||
```v nofmt
|
```v
|
||||||
name := 'Bob'
|
name := 'Bob'
|
||||||
println('Hello, $name!') // Hello, Bob!
|
println('Hello, $name!') // Hello, Bob!
|
||||||
```
|
```
|
||||||
|
@ -456,24 +455,24 @@ Format specifiers similar to those in C's `printf()` are also supported.
|
||||||
`f`, `g`, `x`, etc. are optional and specify the output format.
|
`f`, `g`, `x`, etc. are optional and specify the output format.
|
||||||
The compiler takes care of the storage size, so there is no `hd` or `llu`.
|
The compiler takes care of the storage size, so there is no `hd` or `llu`.
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
x := 123.4567
|
x := 123.4567
|
||||||
println('x = ${x:4.2f}')
|
println('x = ${x:4.2f}')
|
||||||
println('[${x:10}]') // pad with spaces on the left
|
println('[${x:10}]') // pad with spaces on the left
|
||||||
println('[${int(x):-10}]') // pad with spaces on the right
|
println('[${int(x):-10}]') // pad with spaces on the right
|
||||||
```
|
```
|
||||||
|
|
||||||
### String operators
|
### String operators
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
name := 'Bob'
|
name := 'Bob'
|
||||||
bobby := name + 'by' // + is used to concatenate strings
|
bobby := name + 'by' // + is used to concatenate strings
|
||||||
println(bobby) // "Bobby"
|
println(bobby) // "Bobby"
|
||||||
|
|
||||||
mut s := 'hello '
|
mut s := 'hello '
|
||||||
s += 'world' // `+=` is used to append to a string
|
s += 'world' // `+=` is used to append to a string
|
||||||
println(s) // "hello world"
|
println(s) // "hello world"
|
||||||
```
|
```
|
||||||
|
|
||||||
All operators in V must have values of the same type on both sides.
|
All operators in V must have values of the same type on both sides.
|
||||||
You cannot concatenate an integer to a string:
|
You cannot concatenate an integer to a string:
|
||||||
|
|
||||||
|
@ -519,10 +518,10 @@ All of these will be assigned the same value, 123. They will all have type
|
||||||
|
|
||||||
V also supports writing numbers with `_` as separator:
|
V also supports writing numbers with `_` as separator:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
num := 1_000_000 // same as 1000000
|
num := 1_000_000 // same as 1000000
|
||||||
three := 0b0_11 // same as 0b11
|
three := 0b0_11 // same as 0b11
|
||||||
float_num := 3_122.55 // same as 3122.55
|
float_num := 3_122.55 // same as 3122.55
|
||||||
hexa := 0xF_F // same as 255
|
hexa := 0xF_F // same as 255
|
||||||
oct := 0o17_3 // same as 0o173
|
oct := 0o17_3 // same as 0o173
|
||||||
```
|
```
|
||||||
|
@ -547,19 +546,16 @@ will have the type of `f64`.
|
||||||
|
|
||||||
### Arrays
|
### Arrays
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
mut nums := [1, 2, 3]
|
mut nums := [1, 2, 3]
|
||||||
println(nums) // "[1, 2, 3]"
|
println(nums) // "[1, 2, 3]"
|
||||||
println(nums[1]) // "2"
|
println(nums[1]) // "2"
|
||||||
nums[1] = 5
|
nums[1] = 5
|
||||||
println(nums) // "[1, 5, 3]"
|
println(nums) // "[1, 5, 3]"
|
||||||
|
|
||||||
println(nums[0..2]) // slicing gives an array "[1, 5]"
|
println(nums[0..2]) // slicing gives an array "[1, 5]"
|
||||||
|
|
||||||
println(nums.len) // "3"
|
println(nums.len) // "3"
|
||||||
nums = [] // The array is now empty
|
nums = [] // The array is now empty
|
||||||
println(nums.len) // "0"
|
println(nums.len) // "0"
|
||||||
|
|
||||||
// Declare an empty array:
|
// Declare an empty array:
|
||||||
users := []int{}
|
users := []int{}
|
||||||
```
|
```
|
||||||
|
@ -578,15 +574,13 @@ See [Access modifiers](#access-modifiers).
|
||||||
|
|
||||||
#### Array operations
|
#### Array operations
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
mut nums := [1, 2, 3]
|
mut nums := [1, 2, 3]
|
||||||
nums << 4
|
nums << 4
|
||||||
println(nums) // "[1, 2, 3, 4]"
|
println(nums) // "[1, 2, 3, 4]"
|
||||||
|
|
||||||
// append array
|
// append array
|
||||||
nums << [5, 6, 7]
|
nums << [5, 6, 7]
|
||||||
println(nums) // "[1, 2, 3, 4, 5, 6, 7]"
|
println(nums) // "[1, 2, 3, 4, 5, 6, 7]"
|
||||||
|
|
||||||
mut names := ['John']
|
mut names := ['John']
|
||||||
names << 'Peter'
|
names << 'Peter'
|
||||||
names << 'Sam'
|
names << 'Sam'
|
||||||
|
@ -613,12 +607,12 @@ arr := []int{len: 5, init: -1}
|
||||||
Setting the capacity improves performance of insertions,
|
Setting the capacity improves performance of insertions,
|
||||||
as it reduces the number of reallocations needed:
|
as it reduces the number of reallocations needed:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
mut numbers := []int{ cap: 1000 }
|
mut numbers := []int{cap: 1000}
|
||||||
println(numbers.len) // 0
|
println(numbers.len) // 0
|
||||||
// Now appending elements won't reallocate
|
// Now appending elements won't reallocate
|
||||||
for i in 0 .. 1000 {
|
for i in 0 .. 1000 {
|
||||||
numbers << i
|
numbers << i
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Note: The above code uses a [range `for`](#range-for) statement.
|
Note: The above code uses a [range `for`](#range-for) statement.
|
||||||
|
@ -630,7 +624,7 @@ with `s := arr.str()`.
|
||||||
|
|
||||||
Copying the data from the array is done with `.clone()`:
|
Copying the data from the array is done with `.clone()`:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
nums := [1, 2, 3]
|
nums := [1, 2, 3]
|
||||||
nums_copy := nums.clone()
|
nums_copy := nums.clone()
|
||||||
```
|
```
|
||||||
|
@ -638,7 +632,7 @@ nums_copy := nums.clone()
|
||||||
Arrays can be efficiently filtered and mapped with the `.filter()` and
|
Arrays can be efficiently filtered and mapped with the `.filter()` and
|
||||||
`.map()` methods:
|
`.map()` methods:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
nums := [1, 2, 3, 4, 5, 6]
|
nums := [1, 2, 3, 4, 5, 6]
|
||||||
even := nums.filter(it % 2 == 0)
|
even := nums.filter(it % 2 == 0)
|
||||||
println(even) // [2, 4, 6]
|
println(even) // [2, 4, 6]
|
||||||
|
@ -647,7 +641,6 @@ even_fn := nums.filter(fn (x int) bool {
|
||||||
return x % 2 == 0
|
return x % 2 == 0
|
||||||
})
|
})
|
||||||
println(even_fn)
|
println(even_fn)
|
||||||
|
|
||||||
words := ['hello', 'world']
|
words := ['hello', 'world']
|
||||||
upper := words.map(it.to_upper())
|
upper := words.map(it.to_upper())
|
||||||
println(upper) // ['HELLO', 'WORLD']
|
println(upper) // ['HELLO', 'WORLD']
|
||||||
|
@ -665,15 +658,15 @@ println(upper_fn) // ['HELLO', 'WORLD']
|
||||||
Arrays can have more than one dimension.
|
Arrays can have more than one dimension.
|
||||||
|
|
||||||
2d array example:
|
2d array example:
|
||||||
```v nofmt
|
```v
|
||||||
mut a := [][]int{len:2, init: []int{len:3}}
|
mut a := [][]int{len: 2, init: []int{len: 3}}
|
||||||
a[0][1] = 2
|
a[0][1] = 2
|
||||||
println(a) // [[0, 2, 0], [0, 0, 0]]
|
println(a) // [[0, 2, 0], [0, 0, 0]]
|
||||||
```
|
```
|
||||||
|
|
||||||
3d array example:
|
3d array example:
|
||||||
```v nofmt
|
```v
|
||||||
mut a := [][][]int{len:2, init: [][]int{len:3, init: []int{len:2}}}
|
mut a := [][][]int{len: 2, init: [][]int{len: 3, init: []int{len: 2}}}
|
||||||
a[0][1][1] = 2
|
a[0][1][1] = 2
|
||||||
println(a) // [[[0, 0], [0, 2], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
|
println(a) // [[[0, 0], [0, 2], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
|
||||||
```
|
```
|
||||||
|
@ -685,32 +678,35 @@ are used when providing a custom sorting condition.
|
||||||
|
|
||||||
```v nofmt
|
```v nofmt
|
||||||
mut numbers := [1, 3, 2]
|
mut numbers := [1, 3, 2]
|
||||||
numbers.sort() // 1, 2, 3
|
numbers.sort() // 1, 2, 3
|
||||||
numbers.sort(a > b) // 3, 2, 1
|
numbers.sort(a > b) // 3, 2, 1
|
||||||
```
|
```
|
||||||
|
|
||||||
```v nofmt
|
```v nofmt
|
||||||
struct User { age int name string }
|
struct User {
|
||||||
|
age int
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
mut users := [User{21, 'Bob'}, User{20, 'Zarkon'}, User{25, 'Alice'}]
|
mut users := [User{21, 'Bob'}, User{20, 'Zarkon'}, User{25, 'Alice'}]
|
||||||
users.sort(a.age < b.age) // sort by User.age int field
|
users.sort(a.age < b.age) // sort by User.age int field
|
||||||
users.sort(a.name > b.name) // reverse sort by User.name string field
|
users.sort(a.name > b.name) // reverse sort by User.name string field
|
||||||
```
|
```
|
||||||
|
|
||||||
### Maps
|
### Maps
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
mut m := map[string]int // Only maps with string keys are allowed for now
|
mut m := map[string]int{} // Only maps with string keys are allowed for now
|
||||||
m['one'] = 1
|
m['one'] = 1
|
||||||
m['two'] = 2
|
m['two'] = 2
|
||||||
println(m['one']) // "1"
|
println(m['one']) // "1"
|
||||||
println(m['bad_key']) // "0"
|
println(m['bad_key']) // "0"
|
||||||
println('bad_key' in m) // Use `in` to detect whether such key exists
|
println('bad_key' in m) // Use `in` to detect whether such key exists
|
||||||
m.delete('two')
|
m.delete('two')
|
||||||
|
|
||||||
// Short syntax
|
// Short syntax
|
||||||
numbers := {
|
numbers := {
|
||||||
'one': 1
|
'one': 1
|
||||||
'two': 2
|
'two': 2
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -835,22 +831,24 @@ println(s)
|
||||||
You can check the current type of a sum type using `is` and its negated form `!is`.
|
You can check the current type of a sum type using `is` and its negated form `!is`.
|
||||||
|
|
||||||
You can do it either in an `if`:
|
You can do it either in an `if`:
|
||||||
```v nofmt
|
```v
|
||||||
struct Abc {
|
struct Abc {
|
||||||
val string
|
val string
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Xyz {
|
struct Xyz {
|
||||||
foo string
|
foo string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Alphabet = Abc | Xyz
|
type Alphabet = Abc | Xyz
|
||||||
|
|
||||||
x := Alphabet(Abc{'test'}) // sum type
|
x := Alphabet(Abc{'test'}) // sum type
|
||||||
if x is Abc {
|
if x is Abc {
|
||||||
// x is automatically casted to Abc and can be used here
|
// x is automatically casted to Abc and can be used here
|
||||||
println(x)
|
println(x)
|
||||||
}
|
}
|
||||||
if x !is Abc {
|
if x !is Abc {
|
||||||
println('Not Abc')
|
println('Not Abc')
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
or using `match`:
|
or using `match`:
|
||||||
|
@ -926,11 +924,13 @@ match mut x {
|
||||||
|
|
||||||
`in` allows to check whether an array or a map contains an element.
|
`in` allows to check whether an array or a map contains an element.
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
nums := [1, 2, 3]
|
nums := [1, 2, 3]
|
||||||
println(1 in nums) // true
|
println(1 in nums) // true
|
||||||
|
m := {
|
||||||
m := {'one': 1, 'two': 2}
|
'one': 1
|
||||||
|
'two': 2
|
||||||
|
}
|
||||||
println('one' in m) // true
|
println('one' in m) // true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -966,15 +966,17 @@ V has only one looping keyword: `for`, with several forms.
|
||||||
|
|
||||||
#### Array `for`
|
#### Array `for`
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
numbers := [1, 2, 3, 4, 5]
|
numbers := [1, 2, 3, 4, 5]
|
||||||
for num in numbers {
|
for num in numbers {
|
||||||
println(num)
|
println(num)
|
||||||
}
|
}
|
||||||
names := ['Sam', 'Peter']
|
names := ['Sam', 'Peter']
|
||||||
for i, name in names {
|
for i, name in names {
|
||||||
println('$i) $name') // Output: 0) Sam
|
println('$i) $name')
|
||||||
} // 1) Peter
|
// Output: 0) Sam
|
||||||
|
// 1) Peter
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `for value in arr` form is used for going through elements of an array.
|
The `for value in arr` form is used for going through elements of an array.
|
||||||
|
@ -983,7 +985,7 @@ If an index is required, an alternative form `for index, value in arr` can be us
|
||||||
Note, that the value is read-only.
|
Note, that the value is read-only.
|
||||||
If you need to modify the array while looping, you have to use indexing:
|
If you need to modify the array while looping, you have to use indexing:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
mut numbers := [0, 1, 2]
|
mut numbers := [0, 1, 2]
|
||||||
for i, _ in numbers {
|
for i, _ in numbers {
|
||||||
numbers[i]++
|
numbers[i]++
|
||||||
|
@ -994,26 +996,36 @@ When an identifier is just a single underscore, it is ignored.
|
||||||
|
|
||||||
#### Map `for`
|
#### Map `for`
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
m := {'one':1, 'two':2}
|
m := {
|
||||||
|
'one': 1
|
||||||
|
'two': 2
|
||||||
|
}
|
||||||
for key, value in m {
|
for key, value in m {
|
||||||
println("$key -> $value") // Output: one -> 1
|
println('$key -> $value')
|
||||||
} // two -> 2
|
// Output: one -> 1
|
||||||
|
// two -> 2
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Either key or value can be ignored by using a single underscore as the identifier.
|
Either key or value can be ignored by using a single underscore as the identifier.
|
||||||
```v nofmt
|
```v
|
||||||
m := {'one':1, 'two':2}
|
m := {
|
||||||
|
'one': 1
|
||||||
|
'two': 2
|
||||||
|
}
|
||||||
// iterate over keys
|
// iterate over keys
|
||||||
for key, _ in m {
|
for key, _ in m {
|
||||||
println(key) // Output: one
|
println(key)
|
||||||
} // two
|
// Output: one
|
||||||
|
// two
|
||||||
|
}
|
||||||
// iterate over values
|
// iterate over values
|
||||||
for _, value in m {
|
for _, value in m {
|
||||||
println(value) // Output: 1
|
println(value)
|
||||||
} // 2
|
// Output: 1
|
||||||
|
// 2
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Range `for`
|
#### Range `for`
|
||||||
|
@ -1029,7 +1041,7 @@ from `low` up to *but not including* `high`.
|
||||||
|
|
||||||
#### Condition `for`
|
#### Condition `for`
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
mut sum := 0
|
mut sum := 0
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i <= 100 {
|
for i <= 100 {
|
||||||
|
@ -1045,7 +1057,7 @@ Again, there are no parentheses surrounding the condition, and the braces are al
|
||||||
|
|
||||||
#### Bare `for`
|
#### Bare `for`
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
mut num := 0
|
mut num := 0
|
||||||
for {
|
for {
|
||||||
num += 2
|
num += 2
|
||||||
|
@ -1196,19 +1208,17 @@ fn read_log() {
|
||||||
|
|
||||||
## Structs
|
## Structs
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
struct Point {
|
struct Point {
|
||||||
x int
|
x int
|
||||||
y int
|
y int
|
||||||
}
|
}
|
||||||
|
|
||||||
mut p := Point{
|
mut p := Point{
|
||||||
x: 10
|
x: 10
|
||||||
y: 20
|
y: 20
|
||||||
}
|
}
|
||||||
|
|
||||||
println(p.x) // Struct fields are accessed using a dot
|
println(p.x) // Struct fields are accessed using a dot
|
||||||
|
|
||||||
// Alternative literal syntax for structs with 3 fields or fewer
|
// Alternative literal syntax for structs with 3 fields or fewer
|
||||||
p = Point{10, 20}
|
p = Point{10, 20}
|
||||||
assert p.x == 10
|
assert p.x == 10
|
||||||
|
@ -1405,19 +1415,22 @@ no need in getters/setters or properties.
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
struct User {
|
struct User {
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (u User) can_register() bool {
|
fn (u User) can_register() bool {
|
||||||
return u.age > 16
|
return u.age > 16
|
||||||
}
|
}
|
||||||
|
|
||||||
user := User{age: 10}
|
user := User{
|
||||||
|
age: 10
|
||||||
|
}
|
||||||
println(user.can_register()) // "false"
|
println(user.can_register()) // "false"
|
||||||
|
user2 := User{
|
||||||
user2 := User{age: 20}
|
age: 20
|
||||||
|
}
|
||||||
println(user2.can_register()) // "true"
|
println(user2.can_register()) // "true"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1814,20 +1827,21 @@ For more information, see [Dynamic casts](#dynamic-casts).
|
||||||
|
|
||||||
### Enums
|
### Enums
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
enum Color {
|
enum Color {
|
||||||
red green blue
|
red
|
||||||
|
green
|
||||||
|
blue
|
||||||
}
|
}
|
||||||
|
|
||||||
mut color := Color.red
|
mut color := Color.red
|
||||||
// V knows that `color` is a `Color`. No need to use `color = Color.green` here.
|
// V knows that `color` is a `Color`. No need to use `color = Color.green` here.
|
||||||
color = .green
|
color = .green
|
||||||
println(color) // "green"
|
println(color) // "green"
|
||||||
|
|
||||||
match color {
|
match color {
|
||||||
.red { println('the color was red') }
|
.red { println('the color was red') }
|
||||||
.green { println('the color was green') }
|
.green { println('the color was green') }
|
||||||
.blue { println('the color was blue') }
|
.blue { println('the color was blue') }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -2092,7 +2106,7 @@ The third method is to provide a default value at the end of the `or` block.
|
||||||
In case of an error, that value would be assigned instead,
|
In case of an error, that value would be assigned instead,
|
||||||
so it must have the same type as the content of the `Option` being handled.
|
so it must have the same type as the content of the `Option` being handled.
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
fn do_something(s string) ?string {
|
fn do_something(s string) ?string {
|
||||||
if s == 'foo' {
|
if s == 'foo' {
|
||||||
return 'foo'
|
return 'foo'
|
||||||
|
@ -2153,7 +2167,7 @@ runtime parameter types. This is why `find_by_id` can omit `<T>`, because the
|
||||||
receiver argument `r` uses a generic type `T`.
|
receiver argument `r` uses a generic type `T`.
|
||||||
|
|
||||||
Another example:
|
Another example:
|
||||||
```v nofmt
|
```v
|
||||||
fn compare<T>(a T, b T) int {
|
fn compare<T>(a T, b T) int {
|
||||||
if a < b {
|
if a < b {
|
||||||
return -1
|
return -1
|
||||||
|
@ -2168,12 +2182,10 @@ fn compare<T>(a T, b T) int {
|
||||||
println(compare(1, 0)) // Outputs: 1
|
println(compare(1, 0)) // Outputs: 1
|
||||||
println(compare(1, 1)) // 0
|
println(compare(1, 1)) // 0
|
||||||
println(compare(1, 2)) // -1
|
println(compare(1, 2)) // -1
|
||||||
|
|
||||||
// compare<string>
|
// compare<string>
|
||||||
println(compare('1', '0')) // Outputs: 1
|
println(compare('1', '0')) // Outputs: 1
|
||||||
println(compare('1', '1')) // 0
|
println(compare('1', '1')) // 0
|
||||||
println(compare('1', '2')) // -1
|
println(compare('1', '2')) // -1
|
||||||
|
|
||||||
// compare<f64>
|
// compare<f64>
|
||||||
println(compare(1.1, 1.0)) // Outputs: 1
|
println(compare(1.1, 1.0)) // Outputs: 1
|
||||||
println(compare(1.1, 1.1)) // 0
|
println(compare(1.1, 1.1)) // 0
|
||||||
|
@ -2227,8 +2239,8 @@ Channels can be buffered or unbuffered and it is possible to `select` from multi
|
||||||
Channels have the type `chan objtype`. An optional buffer length can specified as the `cap` property
|
Channels have the type `chan objtype`. An optional buffer length can specified as the `cap` property
|
||||||
in the declaration:
|
in the declaration:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
ch := chan int{} // unbuffered - "synchronous"
|
ch := chan int{} // unbuffered - "synchronous"
|
||||||
ch2 := chan f64{cap: 100} // buffer length 100
|
ch2 := chan f64{cap: 100} // buffer length 100
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -2251,18 +2263,17 @@ fn main() {
|
||||||
Objects can be pushed to channels using the arrow operator. The same operator can be used to
|
Objects can be pushed to channels using the arrow operator. The same operator can be used to
|
||||||
pop objects from the other end:
|
pop objects from the other end:
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
import sync
|
|
||||||
|
|
||||||
mut ch := chan int{}
|
mut ch := chan int{}
|
||||||
mut ch2 := chan f64{}
|
mut ch2 := chan f64{}
|
||||||
n := 5
|
n := 5
|
||||||
x := 7.3
|
x := 7.3
|
||||||
ch <- n // push
|
ch <- n
|
||||||
|
// push
|
||||||
ch2 <- x
|
ch2 <- x
|
||||||
mut y := f64(0.0)
|
mut y := f64(0.0)
|
||||||
m := <-ch // pop creating new variable
|
m := <-ch // pop creating new variable
|
||||||
y = <-ch2 // pop into existing variable
|
y = <-ch2 // pop into existing variable
|
||||||
```
|
```
|
||||||
|
|
||||||
A channel can be closed to indicate that no further objects can be pushed. Any attempt
|
A channel can be closed to indicate that no further objects can be pushed. Any attempt
|
||||||
|
@ -2337,19 +2348,19 @@ if select {
|
||||||
#### Special Channel Features
|
#### Special Channel Features
|
||||||
|
|
||||||
For special purposes there are some builtin properties and methods:
|
For special purposes there are some builtin properties and methods:
|
||||||
```v nofmt
|
```v
|
||||||
struct Abc{x int}
|
struct Abc {
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
a := 2.13
|
a := 2.13
|
||||||
mut ch := chan f64{}
|
mut ch := chan f64{}
|
||||||
|
res := ch.try_push(a) // try to perform `ch <- a`
|
||||||
res := ch.try_push(a) // try to perform `ch <- a`
|
|
||||||
println(res)
|
println(res)
|
||||||
l := ch.len // number of elements in queue
|
l := ch.len // number of elements in queue
|
||||||
c := ch.cap // maximum queue length
|
c := ch.cap // maximum queue length
|
||||||
println(l)
|
println(l)
|
||||||
println(c)
|
println(c)
|
||||||
|
|
||||||
// mut b := Abc{}
|
// mut b := Abc{}
|
||||||
// mut ch2 := chan f64{}
|
// mut ch2 := chan f64{}
|
||||||
// res2 := ch2.try_pop(mut b) // try to perform `b = <-ch2
|
// res2 := ch2.try_pop(mut b) // try to perform `b = <-ch2
|
||||||
|
@ -2522,7 +2533,7 @@ Python, Go, or Java, except there's no heavy GC tracing everything or expensive
|
||||||
each object.
|
each object.
|
||||||
|
|
||||||
For developers willing to have more low level control, autofree can be disabled with
|
For developers willing to have more low level control, autofree can be disabled with
|
||||||
`-manualfree`, or by adding a `[manualfree]` on each function that wants manage its
|
`-manualfree`, or by adding a `[manualfree]` on each function that wants manage its
|
||||||
memory manually.
|
memory manually.
|
||||||
|
|
||||||
Note: right now autofree is hidden behind the -autofree flag. It will be enabled by
|
Note: right now autofree is hidden behind the -autofree flag. It will be enabled by
|
||||||
|
@ -2588,36 +2599,45 @@ V's ORM provides a number of benefits:
|
||||||
- Readability and simplicity. (You don't need to manually parse the results of a query and
|
- Readability and simplicity. (You don't need to manually parse the results of a query and
|
||||||
then manually construct objects from the parsed results.)
|
then manually construct objects from the parsed results.)
|
||||||
|
|
||||||
```v nofmt
|
```v
|
||||||
import sqlite
|
import sqlite
|
||||||
struct Customer { // struct name has to be the same as the table name (for now)
|
|
||||||
id int // a field named `id` of integer type must be the first field
|
struct Customer {
|
||||||
name string
|
// struct name has to be the same as the table name (for now)
|
||||||
nr_orders int
|
id int // a field named `id` of integer type must be the first field
|
||||||
country string
|
name string
|
||||||
|
nr_orders int
|
||||||
|
country string
|
||||||
}
|
}
|
||||||
|
|
||||||
db := sqlite.connect('customers.db')?
|
db := sqlite.connect('customers.db') ?
|
||||||
|
|
||||||
// select count(*) from Customer
|
// select count(*) from Customer
|
||||||
nr_customers := sql db { select count from Customer }
|
nr_customers := sql db {
|
||||||
|
select count from Customer
|
||||||
|
}
|
||||||
println('number of all customers: $nr_customers')
|
println('number of all customers: $nr_customers')
|
||||||
|
|
||||||
// V syntax can be used to build queries
|
// V syntax can be used to build queries
|
||||||
// db.select returns an array
|
// db.select returns an array
|
||||||
uk_customers := sql db { select from Customer where country == 'uk' && nr_orders > 0 }
|
uk_customers := sql db {
|
||||||
|
select from Customer where country == 'uk' && nr_orders > 0
|
||||||
|
}
|
||||||
println(uk_customers.len)
|
println(uk_customers.len)
|
||||||
for customer in uk_customers {
|
for customer in uk_customers {
|
||||||
println('$customer.id - $customer.name')
|
println('$customer.id - $customer.name')
|
||||||
}
|
}
|
||||||
|
|
||||||
// by adding `limit 1` we tell V that there will be only one object
|
// by adding `limit 1` we tell V that there will be only one object
|
||||||
customer := sql db { select from Customer where id == 1 limit 1 }
|
customer := sql db {
|
||||||
|
select from Customer where id == 1 limit 1
|
||||||
|
}
|
||||||
println('$customer.id - $customer.name')
|
println('$customer.id - $customer.name')
|
||||||
|
|
||||||
// insert a new customer
|
// insert a new customer
|
||||||
new_customer := Customer{name: 'Bob', nr_orders: 10}
|
new_customer := Customer{
|
||||||
sql db { insert new_customer into Customer }
|
name: 'Bob'
|
||||||
|
nr_orders: 10
|
||||||
|
}
|
||||||
|
sql db {
|
||||||
|
insert new_customer into Customer
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For more examples, see <a href='https://github.com/vlang/v/blob/master/vlib/orm/orm_test.v'>vlib/orm/orm_test.v</a>.
|
For more examples, see <a href='https://github.com/vlang/v/blob/master/vlib/orm/orm_test.v'>vlib/orm/orm_test.v</a>.
|
||||||
|
|
Loading…
Reference in New Issue