Examples in V
fn main() {
	println('hello world')
Last Run  :
hello world
// "bool" type
b1 := true
b2 := false

// "string" type
s := "hello"

// "rune" type - represents a Unicode code point
grinning_face := rune(0xf09f9880)

// numbers
n1 := i8(2)
n2 := byte(10)
n3 := i16(10)
n4 := u16(10)
n5 := 123 // Has the type "int"
n6 := u32(10)
n7 := i64(10)
n8 := u64(10)
n9 := 0.32 // Has the type "f32"
n10 := f64(0.32)

// pointers
p1 := byteptr(&s)
p2 := voidptr(&s)
name := 'Bob'
age := 20
large_number := i64(9999999999)
enum Color {
	red green blue

mut color := Color.red
// V knows that `color` is a `Color`. No need to use `color = Color.green` here.
color = .green
println(color) // "1"  TODO: print "green"?
A higher order function is a function that takes a function as an argument, or returns a function. Higher order function is in contrast to first order functions, which don’t take a function as an argument or return a function as output.
fn sqr(n int) int {
	return n * n

fn run(value int, op fn(int) int) int {
	return op(value)

fn main()  {
	println(run(5, sqr)) // "25"
// A defer statement defers the execution of a block of statements until the end of scope or until surrounding function returns.
fn read_log() {
	f := os.open('log.txt')
	defer { f.close() }
	// ...
	if !ok {
		// defer statement will be called here, the file will be closed
	// ...
	// defer statement will be called here, the file will be closed
module main

fn main() {
    numbers := [1, 2, 4, 5, 6, 7, 8, 9, 10]
    friends := ['Alex', 'Nedpals', 'Joe', 'Spytheman']
    mut empty_numbers := []int{}
    empty_numbers << 20
    empty_numbers << 30
Last Run  :
[1, 2, 4, 5, 6, 7, 8, 9, 10]
['Alex', 'Nedpals', 'Joe', 'Spytheman']
[20, 30]
// V doesn't have classes. But you can define methods on types.
// A method is a function with a special receiver argument.
// The receiver appears in its own argument list between the fn keyword and the method name.
// In this example, the can_register method has a receiver of type User named u.
// The convention is not to use receiver names like self or this, but a short, preferably one letter long, name.
struct User {
	age int

fn (u User) can_register() bool {
	return u.age > 16

user := User{age: 10}
println(user.can_register()) // "false" 

user2 := User{age: 20}
println(user2.can_register()) // "true"
Last Run  :
// A type implements an interface by implementing its methods.
// There is no explicit declaration of intent, no "implements" keyword.

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) {
	// TODO    
    str := s.speak()

dog := Dog{}
cat := Cat{}
perform(dog) // "woof" 
perform(cat) // "meow"
Last Run  :
struct Repo {
	db DB

fn new_repo(db DB) Repo {
	return Repo{db: db}

// This is a generic function. V will generate it for every type it's used with.
fn (r Repo) find_by_id(id int) ?T {
	table_name := T.name // in this example getting the name of the type gives us the table name
	return r.db.query_one('select * from $table_name where id = ?', id)

db := new_db()
users_repo := new_repo(db)
posts_repo := new_repo(db)
user := users_repo.find_by_id(1)?
post := posts_repo.find_by_id(1)?
// Having built-in JSON support is nice, but V also allows you to create efficient serializers for anything:
// TODO: not implemented yet
fn decode(data string) T {
	mut result := T{}
	for field in T.fields {
		if field.typ == 'string' {
			result.$field = get_string(data, field.name)
		} else if field.typ == 'int' {
			result.$field = get_int(data, field.name)
	return result

// generates to:
fn decode_User(data string) User {
	mut result := User{}
	result.name = get_string(data, 'name')
	result.age = get_int(data, 'age')
	return result
struct User {
	id int
	name string

struct Repo {
	users []User

fn new_repo() Repo {
	return Repo {
		users: [User{1, 'Andrew'}, User {2, 'Bob'}, User {10, 'Charles'}]

fn (r Repo) find_user_by_id(id int) ?User {
	for user in r.users {
		if user.id == id {
			// V automatically wraps this into an option type 
			return user
	return error('User $id not found')

fn main() {
	repo := new_repo()
	user := repo.find_user_by_id(10) or { // Option types must be handled by `or` blocks 
		return  // `or` block must end with `return`, `break`, or `continue` 
	println(user.id) // "10" 
	println(user.name) // "Charles"

// V combines Option and Result into one type, so you don't need to decide which one to use.
// The amount of work required to "upgrade" a function to an optional function is minimal: you have to add a ? to the return type and return an error when something goes wrong.
// If you don't need to return an error, you can simply return none.
// This is the primary way of handling errors in V. They are still values, like in Go, but the advantage is that errors can't be unhandled, and handling them is a lot less verbose.
// err is defined inside an or block and is set to the string message passed to the error() function. err is empty if none was returned.
user := repo.find_user_by_id(7) or {
	println(err) // "User 7 not found"

// You can also propagate errors:
resp := http.get(url)?

// http.get returns ?http.Response. It was called with ?, so the error is propagated to the calling function (which must return an optional) or in case of main leads to a panic.
// Basically the code above is a shorter version of
resp := http.get(url) or {

// V does not have a way to force unwrap an optional (like Rust's unwrap() or Swift's !). You have to use or { panic(err) } instead.
// Operator overloading goes against V's philosophy of simplicity and predictability.
// But since scientific and graphical applications are among V's domains, operator overloading is very important to have in order to improve readability:
// a.add(b).add(c.mul(d)) is a lot less readable than a + b + c * d.

// To improve safety and maintainability, operator overloading has several limitations:

// - It's only possible to overload +, -, *, / operators.
// - Calling other functions inside operator functions is not allowed.
// - Operator functions can't modify their arguments.
// - Both arguments must have the same type (just like with all operators in V).

struct Vec {
	x int
	y int

fn (a Vec) str() string {
	return '{$a.x, $a.y}'

fn (a Vec) + (b Vec) Vec {
	return Vec {
		a.x + b.x,
		a.y + b.y

fn (a Vec) - (b Vec) Vec {
	return Vec {
		a.x - b.x,
		a.y - b.y

fn main() {
	a := Vec{2, 3}
	b := Vec{4, 5}
	println(a + b) // "{6, 8}" 
	println(a - b) // "{-2, -2}" 
// V is a very modular language. Creating reusable modules is encouraged and is very simple.
// To create a new module, create a directory with your module's name and .v files with code:
// cd ~/code/modules
// mkdir mymodule
// vim mymodule/mymodule.v

// mymodule.v
module mymodule

// To export a function we have to use `pub`
pub fn say_hi() {
	println('hello from mymodule!')
// You can have as many .v files in mymodule/ as you want.
// Build it with v build module ~/code/modules/mymodule.

// That's it, you can now use it in your code:

module main

import mymodule

fn main() {
// Note that you have to specify the module every time you call an external function.
// This may seem verbose at first, but it makes code much more readable and easier to understand, since it's always clear which function from which module is being called. Especially in large code bases.
// Module names should be short, under 10 characters. Circular imports are not allowed.
// You can create modules anywhere.
// All modules are compiled statically into a single executable.
// If you want to write a module that will automatically call some setup/initialization code when imported (perhaps you want to call some C library functions), write a module init function inside the module:

fn init() int {
	// your setup code here ...
	return 1
// The init function cannot be public. It will be called automatically.
// You don't need to worry about formatting your code or style guidelines. vfmt takes care of that:
// v fmt -w file.v
// It's recommended to set up your editor, so that vfmt runs on every save.

// Always run vfmt before pushing your code.
// This is a single line comment.

/* This is a multiline comment.
   /* It can be nested. */
// The way it works is very similar to Go. It's very simple: there's no need to write documentation for your code, vdoc will generate it from the source code.
// Documentation for each function/type/const must be placed right before the declaration:

// clearall clears all bits in the array
fn clearall() {
// The comment must start with the name of the definition.

// An overview of the module must be placed in the first comment right after the module's name.

// To generate documentation, run v doc path/to/module (TODO this is temporarily disabled).
Last Run  :
V error: function `main` is not declared in the main module
Please add: 
fn main(){
... to your main program .v file, and try again.