docs: improve the docs by provide better examples and describe module publishing (#12308)

pull/12341/head
czkz 2021-10-31 12:32:31 +03:00 committed by GitHub
parent 579d5ae649
commit 81b95ece51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 231 additions and 189 deletions

View File

@ -102,8 +102,6 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
* [Builtin functions](#builtin-functions) * [Builtin functions](#builtin-functions)
* [Printing custom types](#printing-custom-types) * [Printing custom types](#printing-custom-types)
* [Modules](#modules) * [Modules](#modules)
* [Manage Packages](#manage-packages)
* [Publish package](#publish-package)
* [Type Declarations](#type-declarations) * [Type Declarations](#type-declarations)
* [Interfaces](#interfaces) * [Interfaces](#interfaces)
* [Enums](#enums) * [Enums](#enums)
@ -127,6 +125,8 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
* [Tools](#tools) * [Tools](#tools)
* [v fmt](#v-fmt) * [v fmt](#v-fmt)
* [Profiling](#profiling) * [Profiling](#profiling)
* [Package Management](#package-management)
* [Publish package](#publish-package)
* [Advanced Topics](#advanced-topics) * [Advanced Topics](#advanced-topics)
* [Dumping expressions at runtime](#dumping-expressions-at-runtime) * [Dumping expressions at runtime](#dumping-expressions-at-runtime)
* [Memory-unsafe code](#memory-unsafe-code) * [Memory-unsafe code](#memory-unsafe-code)
@ -479,7 +479,18 @@ windows_newline := '\r\n' // escape special characters like in C
assert windows_newline.len == 2 assert windows_newline.len == 2
``` ```
In V, a string is a read-only array of bytes. String data is encoded using UTF-8. In V, a string is a read-only array of bytes. String data is encoded using UTF-8:
```v
s := 'hello 🌎' // emoji takes 4 bytes
assert s.len == 10
arr := s.bytes() // convert `string` to `[]byte`
assert arr.len == 10
s2 := arr.bytestr() // convert `[]byte` to `string`
assert s2 == s
```
String values are immutable. You cannot mutate elements: String values are immutable. You cannot mutate elements:
```v failcompile ```v failcompile
@ -1041,7 +1052,7 @@ println(typeof(fnums).name) // => [3]int
fnums2 := [1, 10, 100]! // short init syntax that does the same (the syntax will probably change) fnums2 := [1, 10, 100]! // short init syntax that does the same (the syntax will probably change)
anums := fnums[0..fnums.len] anums := fnums[..] // same as `anums := fnums[0..fnums.len]`
println(anums) // => [1, 10, 100] println(anums) // => [1, 10, 100]
println(typeof(anums).name) // => []int println(typeof(anums).name) // => []int
``` ```
@ -1832,7 +1843,6 @@ mut p := Point{
x: 10 x: 10
y: 20 y: 20
} }
// you can omit the struct name when it's already known
p = Point{ p = Point{
x: 30 x: 30
y: 4 y: 4
@ -2065,16 +2075,14 @@ println(nums)
Note, that you have to add `mut` before `nums` when calling this function. This makes Note, that you have to add `mut` before `nums` when calling this function. This makes
it clear that the function being called will modify the value. it clear that the function being called will modify the value.
It is preferable to return values instead of modifying arguments. It is preferable to return values instead of modifying arguments,
e.g. `user = register(user)` (or `user.register()`) instead of `register(mut user)`.
Modifying arguments should only be done in performance-critical parts of your application Modifying arguments should only be done in performance-critical parts of your application
to reduce allocations and copying. to reduce allocations and copying.
For this reason V doesn't allow the modification of arguments with primitive types (e.g. integers). For this reason V doesn't allow the modification of arguments with primitive types (e.g. integers).
Only more complex types such as arrays and maps may be modified. Only more complex types such as arrays and maps may be modified.
Use `user.register()` or `user = register(user)`
instead of `register(mut user)`.
#### Struct update syntax #### Struct update syntax
V makes it easy to return a modified version of an object: V makes it easy to return a modified version of an object:
@ -2486,156 +2494,6 @@ fn init() {
The `init` function cannot be public - it will be called automatically. This feature is The `init` function cannot be public - it will be called automatically. This feature is
particularly useful for initializing a C library. particularly useful for initializing a C library.
### Manage Packages
Briefly:
```powershell
v [module option] [param]
```
###### module options:
```
install Install a module from VPM.
remove Remove a module that was installed from VPM.
search Search for a module from VPM.
update Update an installed module from VPM.
upgrade Upgrade all the outdated modules.
list List all installed modules.
outdated Show installed modules that need updates.
```
Read more:
You can also install modules already created by someone else with [VPM](https://vpm.vlang.io/):
```powershell
v install [module]
```
**Example:**
```powershell
v install ui
```
Modules could install directly from git or mercurial repositories.
```powershell
v install [--git|--hg] [url]
```
**Example:**
```powershell
v install --git https://github.com/vlang/markdown
```
Removing a module with v:
```powershell
v remove [module]
```
**Example:**
```powershell
v remove ui
```
Updating an installed module from [VPM](https://vpm.vlang.io/):
```powershell
v update [module]
```
**Example:**
```powershell
v update ui
```
Or you can update all your modules:
```powershell
v update
```
To see all the modules you have installed, you can use:
```powershell
v list
```
**Example:**
```powershell
> v list
Installed modules:
markdown
ui
```
To see all the modules that need updates:
```powershell
v outdated
```
**Example:**
```powershell
> v outdated
Modules are up to date.
```
### Publish package
1. Put a `v.mod` file inside the toplevel folder of your module (if you
created your module with the command `v new mymodule` or `v init` you already have a v.mod file).
```sh
v new mymodule
Input your project description: My nice module.
Input your project version: (0.0.0) 0.0.1
Input your project license: (MIT)
Initialising ...
Complete!
```
Example `v.mod`:
```v ignore
Module {
name: 'mymodule'
description: 'My nice module.'
version: '0.0.1'
license: 'MIT'
dependencies: []
}
```
Minimal file structure:
```
v.mod
mymodule.v
```
Check that your module name is used in `mymodule.v`:
```v
module mymodule
pub fn hello_world() {
println('Hello World!')
}
```
2. Create a git repository in the folder with the `v.mod` file
(this is not required if you used `v new` or `v init`):
```sh
git init
git add .
git commit -m "INIT"
````
3. Create a public repository on github.com.
4. Connect your local repository to the remote repository and push the changes.
5. Add your module to the public V module registry VPM:
https://vpm.vlang.io/new
You will have to login with your Github account to register the module.
**Warning:** _Currently it is not possibility to edit your entry after submiting.
Check your module name and github url twice as this cannot be changed by you later._
6. The final module name is a combination of your github account and
the module name you provided e.g. `mygithubname.mymodule`.
**Optional:** tag your V module with `vlang` and `vlang-module` on github.com
to allow for a better search experience.
## Type Declarations ## Type Declarations
### Interfaces ### Interfaces
@ -3573,7 +3431,7 @@ fn main() {
The timeout branch is optional. If it is absent `select` waits for an unlimited amount of time. The timeout branch is optional. If it is absent `select` waits for an unlimited amount of time.
It is also possible to proceed immediately if no channel is ready in the moment `select` is called It is also possible to proceed immediately if no channel is ready in the moment `select` is called
by adding an `else { ... }` branch. `else` and `> timeout` are mutually exclusive. by adding an `else { ... }` branch. `else` and `<timeout>` are mutually exclusive.
The `select` command can be used as an *expression* of type `bool` The `select` command can be used as an *expression* of type `bool`
that becomes `false` if all channels are closed: that becomes `false` if all channels are closed:
@ -4287,6 +4145,153 @@ fn main() {
} }
``` ```
## Package management
```powershell
v [module option] [param]
```
###### module options:
```
install Install a module from VPM.
remove Remove a module that was installed from VPM.
search Search for a module from VPM.
update Update an installed module from VPM.
upgrade Upgrade all the outdated modules.
list List all installed modules.
outdated Show installed modules that need updates.
```
You can install modules already created by someone else with [VPM](https://vpm.vlang.io/):
```powershell
v install [module]
```
**Example:**
```powershell
v install ui
```
Modules can be installed directly from git or mercurial repositories.
```powershell
v install [--git|--hg] [url]
```
**Example:**
```powershell
v install --git https://github.com/vlang/markdown
```
Removing a module with v:
```powershell
v remove [module]
```
**Example:**
```powershell
v remove ui
```
Updating an installed module from [VPM](https://vpm.vlang.io/):
```powershell
v update [module]
```
**Example:**
```powershell
v update ui
```
Or you can update all your modules:
```powershell
v update
```
To see all the modules you have installed, you can use:
```powershell
v list
```
**Example:**
```powershell
> v list
Installed modules:
markdown
ui
```
To see all the modules that need updates:
```powershell
v outdated
```
**Example:**
```powershell
> v outdated
Modules are up to date.
```
### Publish package
1. Put a `v.mod` file inside the toplevel folder of your module (if you
created your module with the command `v new mymodule` or `v init` you already have a v.mod file).
```sh
v new mymodule
Input your project description: My nice module.
Input your project version: (0.0.0) 0.0.1
Input your project license: (MIT)
Initialising ...
Complete!
```
Example `v.mod`:
```v ignore
Module {
name: 'mymodule'
description: 'My nice module.'
version: '0.0.1'
license: 'MIT'
dependencies: []
}
```
Minimal file structure:
```
v.mod
mymodule.v
```
The name of your module should be used with the `module` directive
at the top of all files in your module. For `mymodule.v`:
```v
module mymodule
pub fn hello_world() {
println('Hello World!')
}
```
2. Create a git repository in the folder with the `v.mod` file
(this is not required if you used `v new` or `v init`):
```sh
git init
git add .
git commit -m "INIT"
````
3. Create a public repository on github.com.
4. Connect your local repository to the remote repository and push the changes.
5. Add your module to the public V module registry VPM:
https://vpm.vlang.io/new
You will have to login with your Github account to register the module.
**Warning:** _Currently it is not possible to edit your entry after submiting.
Check your module name and github url twice as this cannot be changed by you later._
6. The final module name is a combination of your github account and
the module name you provided e.g. `mygithubname.mymodule`.
**Optional:** tag your V module with `vlang` and `vlang-module` on github.com
to allow for a better search experience.
# Advanced Topics # Advanced Topics
## Dumping expressions at runtime ## Dumping expressions at runtime
@ -4953,13 +4958,13 @@ V can embed arbitrary files into the executable with the `$embed_file(<path>)`
compile time call. Paths can be absolute or relative to the source file. compile time call. Paths can be absolute or relative to the source file.
When you do not use `-prod`, the file will not be embedded. Instead, it will When you do not use `-prod`, the file will not be embedded. Instead, it will
be loaded *the first time* your program calls `f.data()` at runtime, making be loaded *the first time* your program calls `embedded_file.data()` at runtime, making
it easier to change in external editor programs, without needing to recompile it easier to change in external editor programs, without needing to recompile
your executable. your executable.
When you compile with `-prod`, the file *will be embedded inside* your When you compile with `-prod`, the file *will be embedded inside* your
executable, increasing your binary size, but making it more self contained executable, increasing your binary size, but making it more self contained
and thus easier to distribute. In this case, `f.data()` will cause *no IO*, and thus easier to distribute. In this case, `embedded_file.data()` will cause *no IO*,
and it will always return the same data. and it will always return the same data.
#### `$tmpl` for embedding and parsing V template files #### `$tmpl` for embedding and parsing V template files
@ -5154,39 +5159,27 @@ the boolean expression is highly improbable. In the JS backend, that does nothin
Having built-in JSON support is nice, but V also allows you to create efficient Having built-in JSON support is nice, but V also allows you to create efficient
serializers for any data format. V has compile-time `if` and `for` constructs: serializers for any data format. V has compile-time `if` and `for` constructs:
```v wip ```v
// TODO: not fully implemented
struct User { struct User {
name string name string
age int age int
} }
// Note: T should be passed a struct name only fn main() {
fn decode<T>(data string) T { $for field in User.fields {
mut result := T{}
// compile-time `for` loop
// T.fields gives an array of a field metadata type
$for field in T.fields {
$if field.typ is string { $if field.typ is string {
// $(string_expr) produces an identifier println('$field.name is of type string')
result.$(field.name) = get_string(data, field.name)
} $else $if field.typ is int {
result.$(field.name) = get_int(data, field.name)
} }
} }
return result
} }
// `decode<User>` generates: // Output:
fn decode_User(data string) User { // name is of type string
mut result := User{}
result.name = get_string(data, 'name')
result.age = get_int(data, 'age')
return result
}
``` ```
See [`examples/compiletime/reflection.v`](/examples/compiletime/reflection.v)
for a more complete example.
## Limited operator overloading ## Limited operator overloading
```v ```v
@ -5234,7 +5227,7 @@ To improve safety and maintainability, operator overloading is limited:
- `!=`, `>`, `<=` and `>=` are auto generated when `==` and `<` are defined. - `!=`, `>`, `<=` and `>=` are auto generated when `==` and `<` are defined.
- Both arguments must have the same type (just like with all operators in V). - Both arguments must have the same type (just like with all operators in V).
- Assignment operators (`*=`, `+=`, `/=`, etc) - Assignment operators (`*=`, `+=`, `/=`, etc)
are auto generated when the operators are defined though they must return the same type. are auto generated when the corresponding operators are defined and operands are of the same type.
## Inline assembly ## Inline assembly
<!-- ignore because it doesn't pass fmt test (why?) --> <!-- ignore because it doesn't pass fmt test (why?) -->

View File

@ -0,0 +1,49 @@
// An example deserializer implementation
struct User {
name string
age int
}
fn main() {
data := 'name=Alice\nage=18'
user := decode<User>(data)
println(user)
}
fn decode<T>(data string) T {
mut result := T{}
// compile-time `for` loop
// T.fields gives an array of a field metadata type
$for field in T.fields {
$if field.typ is string {
// $(string_expr) produces an identifier
result.$(field.name) = get_string(data, field.name)
} $else $if field.typ is int {
result.$(field.name) = get_int(data, field.name)
}
}
return result
}
fn get_string(data string, field_name string) string {
for line in data.split_into_lines() {
key_val := line.split('=')
if key_val[0] == field_name {
return key_val[1]
}
}
return ''
}
fn get_int(data string, field string) int {
return get_string(data, field).int()
}
// `decode<User>` generates:
// fn decode_User(data string) User {
// mut result := User{}
// result.name = get_string(data, 'name')
// result.age = get_int(data, 'age')
// return result
// }