docs: improve the docs by provide better examples and describe module publishing (#12308)
parent
579d5ae649
commit
81b95ece51
361
doc/docs.md
361
doc/docs.md
|
@ -102,8 +102,6 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
|
|||
* [Builtin functions](#builtin-functions)
|
||||
* [Printing custom types](#printing-custom-types)
|
||||
* [Modules](#modules)
|
||||
* [Manage Packages](#manage-packages)
|
||||
* [Publish package](#publish-package)
|
||||
* [Type Declarations](#type-declarations)
|
||||
* [Interfaces](#interfaces)
|
||||
* [Enums](#enums)
|
||||
|
@ -127,6 +125,8 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
|
|||
* [Tools](#tools)
|
||||
* [v fmt](#v-fmt)
|
||||
* [Profiling](#profiling)
|
||||
* [Package Management](#package-management)
|
||||
* [Publish package](#publish-package)
|
||||
* [Advanced Topics](#advanced-topics)
|
||||
* [Dumping expressions at runtime](#dumping-expressions-at-runtime)
|
||||
* [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
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```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)
|
||||
|
||||
anums := fnums[0..fnums.len]
|
||||
anums := fnums[..] // same as `anums := fnums[0..fnums.len]`
|
||||
println(anums) // => [1, 10, 100]
|
||||
println(typeof(anums).name) // => []int
|
||||
```
|
||||
|
@ -1832,7 +1843,6 @@ mut p := Point{
|
|||
x: 10
|
||||
y: 20
|
||||
}
|
||||
// you can omit the struct name when it's already known
|
||||
p = Point{
|
||||
x: 30
|
||||
y: 4
|
||||
|
@ -2065,16 +2075,14 @@ println(nums)
|
|||
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 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
|
||||
to reduce allocations and copying.
|
||||
|
||||
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.
|
||||
|
||||
Use `user.register()` or `user = register(user)`
|
||||
instead of `register(mut user)`.
|
||||
|
||||
#### Struct update syntax
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
### Interfaces
|
||||
|
@ -3573,7 +3431,7 @@ fn main() {
|
|||
|
||||
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
|
||||
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`
|
||||
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
|
||||
|
||||
## 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.
|
||||
|
||||
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
|
||||
your executable.
|
||||
|
||||
When you compile with `-prod`, the file *will be embedded inside* your
|
||||
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.
|
||||
|
||||
#### `$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
|
||||
serializers for any data format. V has compile-time `if` and `for` constructs:
|
||||
|
||||
```v wip
|
||||
// TODO: not fully implemented
|
||||
|
||||
```v
|
||||
struct User {
|
||||
name string
|
||||
age int
|
||||
}
|
||||
|
||||
// Note: T should be passed a struct name only
|
||||
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 {
|
||||
fn main() {
|
||||
$for field in User.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)
|
||||
println('$field.name is of type string')
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// `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
|
||||
}
|
||||
// Output:
|
||||
// name is of type string
|
||||
```
|
||||
|
||||
See [`examples/compiletime/reflection.v`](/examples/compiletime/reflection.v)
|
||||
for a more complete example.
|
||||
|
||||
## Limited operator overloading
|
||||
|
||||
```v
|
||||
|
@ -5234,7 +5227,7 @@ To improve safety and maintainability, operator overloading is limited:
|
|||
- `!=`, `>`, `<=` and `>=` are auto generated when `==` and `<` are defined.
|
||||
- Both arguments must have the same type (just like with all operators in V).
|
||||
- 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
|
||||
<!-- ignore because it doesn't pass fmt test (why?) -->
|
||||
|
|
|
@ -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
|
||||
// }
|
Loading…
Reference in New Issue