Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
887 lines (683 sloc) 18.9 KB
@t header
<script src="/js/jquery.min.js"></script>
<style>
h2 {
border-top: 1px solid #dfdfdf;
padding-top: 10px;
}
code {
font-family: 'Roboto Mono';
background-color: #f0f0f0;
padding: 1px 3px 1px 3px;
}
</style>
<script>
$(document).ready(function() {
$('.run').click(function() {
var pre = $(this).prev('pre')
localStorage.setItem('play', pre.text())
window.open('/play')
});
});
</script>
<div class='menu'>
<div class='center'>
<a target=_blank href='https://github.com/vlang-io/V/tree/master/examples'>Examples</a>
<a href='/play'>Playground</a>
<a href='https://blog.vlang.io'>Blog</a>
<a href='/#faq'>FAQ</a>
<a href='/#software'>Software built in V</a>
</div>
</div>
<div class='center'>
<h1>
<a href='/' style='color:black'>The V Programming Language</a>
</h1>
<div style='font-size:12px; text-align:center; position: relative; top:-10px;'>
Fast, safe, compiled language created for developing <a target=_blank href='https://volt.ws'>Volt</a>,
soon available for everyone.
<br><br>
Open source release in mid 2019.</div>
<div id='install'>
Install V from source in 0.5 seconds
<pre>wget vlang.io/v.c && gcc -o v v.c</pre>
<!--
or if you already have V
<pre>wget https://vlang.io/v.v && v v.v</pre>
-->
</div>
</div>
<div class='menu' ></div>
<div class='center'>
<div class='toc'>
<a href='#introduction'>Introduction</a>
<a href='#hello'>Hello World</a>
<a href='#comments'>Comments</a>
<a href='#fns'>Functions</a>
<a href='#vars'>Variables</a>
<a href='#btypes'>Basic types</a>
<a href='#consts'>Constants</a>
<a href='#strings'>Strings</a>
<a href='#arrays'>Arrays</a>
<a href='#maps'>Maps</a>
<a href='#if'>If statement</a>
<a href='#for'>For loop</a>
<a href='#switch'>Switch</a>
<a href='#structs'>Structs</a>
<a href='#methods'>Methods</a>
<a href='#recvs'>Mutable receivers & pure functions</a>
<a href='#interfaces'>Interfaces</a>
<a href='#enums'>Enums</a>
<a href='#option'>Option types</a>
<a href='#generics'>Generics</a>
<a href='#json'>Decoding JSON</a>
<a href='#testing'>Testing</a>
<br>
<a href='#cpp'>Translating C/C++ to V</a>
</div>
<div class='docs'>
<h2 id=introduction style='border:0'>Introduction</h2>
V is a statically typed compiled programming language designed for building maintainable software.
<p>
It's similar to Go and is also influenced by Oberon, Rust, Swift.
<p>
V is a very simple language. Going through this documentation will take you about half an hour,
and by the end of it you will learn pretty much the entire language.
<p>
Despite being simple, it gives a lot of power to the developer. Anything you can do in other languages,
you can do in V.
<p>
Found an error/typo? Please <a target=_blank
href='https://github.com/vlang-io/website/blob/master/docs.html'>submit a pull request</a>.
<h2 id=hello>Hello World</h2>
<pre>fn main() {
println('hello world')
}</pre>
<input class='run' type='button' value='Run'>
<p>
Functions are declared with <code>fn</code>. Return type goes after the function
name. In this case <code>main</code> doesn't return anything, so the type is
omitted.
<p>
Just like in C and all related languages, <code>main</code> is an entry point.
<p>
<code>println</code> is one of the few builtin functions. It prints the value
to standard output.
<h2 id=comments>Comments</h2>
<pre>
<comment>// This is a single line comment
/* This is a multiline comment.
/* It can be nested */
*/</comment></pre>
<h2 id=fns>Functions</h2>
<pre>
fn add(x int, y int) int {
return x + y
}
fn sub(x, y int) int {
return x - y
}
fn main() {
println(add(77, 33))
println(sub(100, 50))
}
</pre>
<input class='run' type='button' value='Run'>
<p>
Again, the type comes after the argument's name.
<h2 id=vars>Variables</h2>
<pre>
fn main() {
name := 'Bob'
age := 20
large_number := i64(9999999999)
println(name)
println(age)
println(large_number)
}
</pre>
<input class='run' type='button' value='Run'>
<p>
Variables are declared and initialized with <code>:=</code>. This is the only
way to declare variables in V. This means that variables always have an initial
value.
<p>
The variable's type is inferred from the value on the right hand side.
To force a different type, use type conversion:
the expression <code>T(v)</code> converts the value <code>v</code> to the
type <code>T</code>.
<p>
Unlike most other languages, V only allows defining variables in functions.
Global (module level) variables are not allowed. There's no global state in V.
<!--You can read why <a href='#'> here</a>.-->
<p>&nbsp;</p>
<pre>
fn main() {
mut age := 20
println(age)
age = 21
println(age)
}
</pre>
<input class='run' type='button' value='Run'>
<p>
To change the value of the variable use <code>=</code>. In V variables are
immutable by default. To be able to change the value of the variable, you
have to declare it with <code>mut</code>.
<p>
Please note the difference between <code>:=</code> and <code>=</code><br> <code>:=</code>
is used for declaring and initializing, <code>=</code> is used for assigning.
<p>&nbsp;</p>
<pre>
fn main() {
age = 21
}
</pre>
<input class='run' type='button' value='Run'>
<p>
This code will not compile, because variable <code>age</code> is not declared.
All variables need to be declared in V.
<h2 id=btypes>Basic types</h2>
<pre>
bool
string
i8 i16 i32 i64
u8 u16 u32 u64
byte <comment>// alias for u8 </comment>
int <comment>// alias for i32 </comment>
rune <comment>// alias for i32, represents a Unicode code point </comment>
f32 f64
</pre>
Please note, than unlike C and Go, <code>int</code> is always a 32 bit integer.
<h2 id=consts>Constants</h2>
<pre>
const (
PI = 3.14
WORLD = '世界'
)
fn main() {
println(PI)
println(WORLD)
}
</pre>
<input class='run' type='button' value='Run'>
<p>
Constants are declared with <code>const</code>. They can only be defined
at the module level (outside of functions).
<p>
Constant names must be capitalized. This helps distinguish them from variables.
<p>
Constant values can never be changed.
<p>
V constants are more flexible than in most languages. You can assign more complex values:
<pre>
struct Color {
r int
g int
b int
}
fn (c Color) str() string { return '{$c.r, $c.g, $c.b}' }
fn rgb(r, g, b int) Color { return Color{r: r, g: g, b: b} }
const (
NUMBERS = [1, 2, 3]
RED = Color{r: 255, g: 0, b: 0}
BLUE = rgb(0, 0, 255)
)
fn main() {
println(NUMBERS)
println(RED)
println(BLUE)
}
</pre>
<input class='run' type='button' value='Run'>
<p>
Global variables are not allowed, so this can be really useful.
<h2 id=strings>Strings</h2>
<pre>fn main() {
name := 'Bob'
println('Hello, $name!')
println(name.len)
bobby := name + 'by' <comment>// + is used to concatenate strings</comment>
println(bobby) <comment>// ==> "Bobby" </comment>
println(bobby.substr(1, 3)) <comment>// ==> "ob" </comment>
<comment>// println(bobby[1:3]) // This syntax will most likely replace the substr() method </comment>
}
</pre>
<input class='run' type='button' value='Run'>
<p>
In V, a string is a read-only array of bytes. String data is encoded using UTF-8.
<p>
Strings are immutable. This means that the substring function is very efficient:
no copying is performed, no extra allocations required.
<h2 id=arrays>Arrays</h2>
<pre>
fn main() {
nums := [1, 2, 3]
println(nums)
println(nums[1]) <comment>// ==> "2"</comment>
mut names := ['John']
names << 'Peter'
names << 'Sam'
<comment>// names << 10 <-- This will not compile. `names` is an array of strings.</comment>
println(names.len) <comment>// ==> "3"</comment>
println(names.contains('Alex')) <comment>// ==> "false"</comment>
<comment>// We can also preallocate a certain amount of elements.</comment>
nr_ids := 50
mut ids := [0 ; nr_ids] <comment>// This creates an array with 50 zeroes</comment>
for i := 0; i < nr_ids; i++ {
ids[i] = i <comment>// This is more efficient than </comment>
<comment>// ids << i</comment>
}
}
</pre>
<input class='run' type='button' value='Run'>
<p>
Array type is determined by the first element: <code>[1, 2, 3]</code> is an array of ints <br>
(<code>[]int</code>). <br>
<code>['a', 'b']</code> is an array of strings (<code>[]string</code>).
<p>
All elements in an array must have the same type. <code>[1, 'a']</code> will not compile.
<p>
<code>&lt;&lt;</code> is an operator that appends a value to the end of the array.
<p><code>.len</code> field returns the length of the array. Note, that it's a read-only field,
and it can't be modified by the user. All exported fields are read-only by default in V.
<p><code>.contains(val)</code> method returns true if the array contains <code>val</code>.
<h2 id=maps>Maps</h2>
<p>
TODO
<h2 id=if>If</h2>
<pre>
fn main() {
a := 10
b := 20
if a < b {
println('$a < $b')
} else if a > b {
println('$a > $b')
} else {
println('$a == $b')
}
}
</pre>
<input class='run' type='button' value='Run'>
<p>
<code>if</code> statements are pretty straightforward and similar to most
other languages.
<p>
Unlike other C-like languages, there are no parentheses surrounding the
condition, and the braces are always required.
</p>
<h2 id=for>For loop</h2>
V has only one looping construct: <code>for</code>.
<pre>
fn main() {
numbers := [1, 2, 3, 4, 5]
for num in numbers {
println(num)
}
names := ['Sam', 'Peter']
for i, name in names {
println('$i) $name') // Output: 0) Sam
} // 1) Peter
}
</pre>
<input class='run' type='button' value='Run'>
<p>
The <code>for .. in</code> loop is used for going through elements of an array.
If an index is required, an alternative form <code>for index, value in</code> can be used.
<p>&nbsp;</p>
<pre>
fn main() {
mut sum := 0
mut i := 0
for i <= 100 {
sum += i
i++
}
println(sum) // ==> "5050"
}
</pre>
<input class='run' type='button' value='Run'>
<p>
This form of the loop is similar to <code>while</code>
loops in other languages.
<p>
The loop will stop iterating once the boolean condition evaluates to false.
<p>
Again, there are no parentheses surrounding the
condition, and the braces are always required.
<p>&nbsp;</p>
<pre>
fn main() {
mut num := 0
for {
num++
if num >= 10 {
break
}
}
println(num) // ==> "10"
}
</pre>
<input class='run' type='button' value='Run'>
<p>
The condition can be omitted, this results in an infinite loop.
<p>&nbsp;</p>
<pre>
fn main() {
for i := 0; i < 10; i++ {
println(i)
}
}
</pre>
<input class='run' type='button' value='Run'>
<p>
Finally, there's the traditional C style <code>for</code> loop. It's safer than the `while` form
because with the latter it's easy to forget to update the counter and get
stuck in an infinite loop.
<h2 id=switch>Switch</h2>
<pre>
fn main() {
os := 'windows'
print('V is running on ')
switch os {
case 'darwin':
println('macOS.')
case 'linux':
println('Linux.')
default:
println(os)
}
}
</pre>
<input class='run' type='button' value='Run'>
<p>
A switch statement is a shorter way to write a sequence of <code>if - else</code> statements. It runs the first case whose value is equal to the condition expression.
<p>
Unlike C, <code>break</code> statement is not needed at the end of every block.
<h2 id=structs>Structs</h2>
<pre>
struct Point {
x int
y int
}
fn main() {
p := Point{
x: 10
y: 20
}
println(p.x) <comment>// Struct fields are accessed using a dot</comment>
<comment>// & prefix returns a pointer to the struct value.</comment>
<comment>// It's allocated on the heap and is automatically cleaned up
// by V at the end of the function, since it doesn't escape.</comment>
pointer := &Point{x:10, y:10}
println(pointer.x) <comment>// Pointers have the same syntax for accessing fields </comment>
}
</pre>
<input class='run' type='button' value='Run'>
<h2 id=methods>Methods</h2>
<!--
<pre>
import math
struct Point {
x int
y int
}
fn (a Point) distance_to(b Point) f64 {
return math.sqrt((a.x-b.x)**2 + (a.y-b.y)**2)
}
fn main () {
p := Point{10,10}
p2 := Point{20,20}
println(p.distance_to(p2))
}
</pre>
-->
<pre>
struct User {
age int
}
fn (u User) can_register() bool {
return u.age > 16
}
fn main() {
user := User{age: 10}
println(user.can_register()) <comment>// ==> "false" </comment>
user2 := User{age: 20}
println(user2.can_register()) <comment>// ==> "true" </comment>
}
</pre>
<input class='run' type='button' value='Run'>
<p>
V doesn't have classes. But you can define methods on types.
<p>
A method is a function with a special receiver argument.
<p>
The receiver appears in its own argument list between the <code>fn</code> keyword and the method name.
<p>
<!--
In this example, the <code>distance_to</code> method has a receiver of type <code>Point</code>
named <code>a</code>.
-->
In this example, the <code>can_register</code> method has a receiver of type <code>User</code>
named <code>u</code>.
<h2 id=recvs>Mutable receivers & pure functions</h2>
<pre>struct User {
is_registered bool
}
fn (u mut User) register() {
u.is_registered = true
}
fn main() {
mut user := User{}
println(user.is_registered) <comment>// ==> "false" </comment>
user.register()
<comment>// TODO: Maybe force marking methods that modify the receiver with `!`
// user.register()! </comment>
println(user.is_registered) <comment>// ==> "true" </comment>
}
</pre>
<input class='run' type='button' value='Run'>
<p>
Please note that functions can only modify receivers.<br><code>fn register(u mut User)</code>
will not compile.
<p>
V functions are partially pure: function arguments can never be modified by the function.
<p>
Another way to modify an object is simply to return a modified version: <br>
<pre>
<comment>// TODO: this syntax is not implemented yet </comment>
fn register(u User) User {
return { u, is_registered: true }
}
user = register(user)
</pre>
<h2 id=interfaces>Interfaces</h2>
<pre>
struct Dog {}
struct Cat {}
fn (d Dog) speak() string {
return 'woof'
}
fn (c Cat) speak() string {
return 'meow'
}
interface Speaker {
speak() string
}
fn perform(s Speaker) {
println(s.speak())
}
fn main() {
dog := Dog{}
cat := Cat{}
perform(dog) // ==> "woof"
perform(cat) // ==> "meow"
}
</pre>
<input class='run' type='button' value='Run'>
<p>
A type implements an interface by implementing its methods. There is no explicit declaration of intent, no "implements" keyword.
</p>
<p>
V interfaces are very efficient. There's no dynamic dispatch.
</p>
<h2 id=enums>Enums</h2>
<!--
<pre>
enum Color {
red, green, blue
}
fn main() {
mut color := Color.red
println(color) // ==> "red"
color = .green
is_green := color == .green
}
</pre>
-->
<pre>
enum Color {
red, green, blue
}
fn main() {
mut color := red <comment>// TODO: color := Color.green </comment>
color = green <comment>// TODO: color = .green</comment>
println(color) <comment>// ==> "1" TODO: print "green"? </comment>
}
</pre>
<input class='run' type='button' value='Run'>
<h2 id=option>Option types</h2>
<pre>struct User {
id int
}
struct Repo {
users []User
}
fn new_repo() Repo {
user := User{id:10}
return Repo {
users: [user]
}
}
fn (r Repo) find_user_by_id(id int) User? {
for user in r.users {
if user.id == id {
<comment>// V automatically wraps this into an option type </comment>
return user
}
}
return error('User $id not found')
}
fn main() {
repo := new_repo()
user := repo.find_user_by_id(10) or { <comment>// Option types must be handled by `or` blocks </comment>
return // <comment>`or` block must end with `return`, `break`, or `continue` </comment>
}
println(user.id) // <comment>==> "10" </comment>
}
</pre>
<!--
eprintln(err)
-->
<input class='run' type='button' value='Run'>
<p>
The amount of work required to "upgrade" a function to an optional function is minimal:
you have to add a <code>?</code> to the return type and return an error when something goes wrong.
<p>
If you don't need to return an error, you can simply <code>return None</code>. (TODO: <code>None</code> is
not implemented yet).
<h2 id=generics>Generics (July)</h2>
<pre>struct Repo &lt;T> {
db DB
}
fn new_repo&lt;T>(db DB) Repo&lt;T> {
return Repo&lt;T>{db: db}
}
<comment>// This is a generic function. V will generate it for every type it's used with.</comment>
fn (r Repo&lt;T>) find_by_id(id int) T? {
table_name := T.name <comment>// in this example getting the name of the type gives us the table name</comment>
return r.db.query_one&lt;T>('select * from $table_name where id = ?', id)
}
fn main() {
db := new_db()
users_repo := new_repo&lt;User>(db)
posts_repo := new_repo&lt;Post>(db)
user := users_repo.find_by_id(1)?
post := posts_repo.find_by_id(1)?
}
</pre>
<span style='font-size:80%'>The initial version of V had generics because arrays and maps were built with
them. Later I figured out a way to implement these data structures without generics. This simplified code
greatly.
<br><br>
Since I no longer needed them, they were moved to a branch, because maintaining generics is tough.
Generics will not be available when the language is released in June, but they should
be back by July.
</span>
<h2 id=json>Decoding JSON</h2>
<pre>struct User {
name string
age int
}
fn main() {
data := '{ "name": "Frodo", "age": 25 }'
user := json.decode(User, data) or {
eprintln('Failed to decode json')
return
}
println(user.name)
println(user.age)
}
</pre>
<input class='run' type='button' value='Run'>
<p>
JSON is very popular nowadays, that's why JSON support is built in.
<p>
The first argument of the <code>json.decode</code> function is the type to decode to.
The second argument is the json string.
<p>
V generates code for json encoding and decoding. No reflection is used. This results in much better
performance.
<h2 id=testing>Testing</h2>
<pre><comment>// hello.v</comment>
fn hello() string {
return 'Hello world'
}
<comment>// hello_test.v</comment>
fn test_hello() {
assert hello() == 'Hello world'
}
</pre>
All test functions have to be placed in <code>*_test.v</code> files and begin with <code>test_</code>.
To run the tests do <code>v hello_test.v</code>. To test an entire module do
<code>v test mymodule</code>.
<h2 id=cpp>Translating C/C++ to V</h2>
V can translate your C/C++ code to human readable V code.
Let's create a simple program <code>test.cpp</code> first:
<pre>#include &lt;vector>
#include &lt;string>
#include &lt;iostream>
int main() {
std::vector&lt;std::string> s;
s.push_back("V is ");
s.push_back("awesome");
std::cout << s.size() << std::endl;
return 0;
}
</pre>
Run <code>v translate test.cpp</code> and V will generate <code>test.v</code>:
<pre>fn main {
mut s := []string
s << 'V is '
s << 'awesome'
println(s.len)
}
</pre>
<p>
An online C/C++ to V translator is coming soon.
</div>
</div>
</body>
</html>
@t footer
You can’t perform that action at this time.