Book Image

Getting Started with V Programming

By : Navule Pavan Kumar Rao
4 (1)
Book Image

Getting Started with V Programming

4 (1)
By: Navule Pavan Kumar Rao

Overview of this book

A new language on the block, V comes with a promising set of features such as fast compilation and interoperability with other programming languages. This is the first book on the V programming language, packed with concise information and a walkthrough of all the features you need to know to get started with the language. The book begins by covering the fundamentals to help you learn about the basic features of V and the suite of built-in libraries available within the V ecosystem. You'll become familiar with primitive data types, declaring variables, arrays, and maps. In addition to basic programming, you'll develop a solid understanding of the building blocks of programming, including functions, structs, and modules in the V programming language. As you advance through the chapters, you'll learn how to implement concurrency in V Programming, and finally learn how to write test cases for functions. This book takes you through an end-to-end project that will guide you to build fast and maintainable RESTful microservices by leveraging the power of V and its built-in libraries. By the end of this V programming book, you'll be well-versed with the V programming language and be able to start writing your own programs and applications.
Table of Contents (19 chapters)
1
Section 1: Introduction to the V Programming Language
4
Section 2: Basics of V Programming
12
Section 3: Advanced Concepts in V Programming

Features of V programming

Despite being a very new and constantly evolving programming language, V has got all the most sought-after features that satisfy the needs of modern-day programmers. In this section, we will explore various features of V.

Performance

V has Clang, GCC, or MSVC as its primary backend, depending on the OS, which allows it to compile to human-readable C. Having these compilers as the main backend allows V to have easy interoperability with C. V, with its innovative memory management, performs a minimal amount of memory allocation by using value types and string buffers. A program written in V gets compiled to native binaries without any dependencies. Also, V compiles the whole application into a single binary, which makes it easy to deploy.

Speed

At the time of writing this book, according to the official website, https://vlang.io/, with a Clang backend, V compiles ~110k LOCs per second, per CPU core. With x64 and a TCC backend, V compiles ~1 million LOCs per CPU core.

No null values

A null value indicates nothing. A null value neither represents an empty nor a default value. Having null values in a programming language enforces you to handle the null scenarios using multiple checks. These checks, when missed, might lead to errors.

V does not have null or nil values, unlike other programming languages such as Java, C#, Python, or Go. This is because all the types in V are zeroed in by default. Zeroed in means that they are assigned with default values, such as an empty string for string types, 0 for integers, and false for Boolean types. Thus, V does not rely on the compiler to check whether the type is null or not, thereby preventing the program from creating several errors.

No global variables

Global variables allow you to maintain the state at the application level. Though this sounds comforting, global variables slowly lead to reliability problems that arise due to the growing number of actors on such variables.

In V, global variables are disabled by default. These global variables can be declared using the __global keyword and running the V program with the -enable-globals argument. The reason why V facilitates working with global variables is to allow the implementation of low-level applications such as programming OS kernels or system drivers. In such cases, you may need to have variables that can be accessed globally.

No undefined values

In V, when you declare a variable of any type, you must initialize it. Otherwise, it leads to compilation errors. Also, in the case of structs, which are detailed in Chapter 8, Structs, the fields of a struct are zeroed into their default values.

Error handling

V has a very simple approach to dealing with errors. You have the flexibility to deal with these errors using an or {} block or let the errors propagate using the optional operator, ?. You can also build custom errors using the built-in error method, which accepts a string as an input argument. The different ways to deal with errors will be demonstrated in the Functions can have optional return types section of Chapter 7, Functions.

Powerful concurrency

V has a very powerful concurrency framework. It is essential for an application running on a high-end computing device to be able to utilize its resources, such as its CPU cores, efficiently. Through V's built-in concurrency model, using the go keyword, you can spawn functions to run concurrently on other threads, different from the thread where the main program runs. The functions that run concurrently are called coroutines.

You can have shared variables to synchronize the data between coroutines by enforcing read-only locks using the rlocks keyword or read/write/modify locks using the lock keyword. This approach is demonstrated in the Sharing data between the main thread and concurrent tasks section of Chapter 10, Concurrency. With this traditional concurrency synchronization technique, the coroutines communicate by sharing data or memory.

As creating shared variables and manually enforcing locks is often cumbersome, V has a built-in library called sync that implements advanced concurrency patterns known as channels. A channel allows you to share data by establishing a communication channel among coroutines. A channel acts as a medium where a coroutine pushes data into it and other channels pop the data out of it. We will learn about channels, along with their features and how to work with buffered and unbuffered channels, in Chapter 11, Channels – An Advanced Concurrency Pattern.

Easy cross-compilation

V allows you to generate cross-platform binaries with its cross-platform compilation capabilities. With this feature, from a *nix OS, you can generate your application's executable that targets *nix OS variants, as well as Windows or macOS. From a *nix OS, let's say Ubuntu, create a file named hello.v and add the following code to it:

module main
fn main() {
    os := $if windows { 'Windows' } $else { 'Unix' }
    println('Hello, $os user!')
}

The $ symbol in the preceding code tells the compiler to evaluate the following if condition right away during compile time. Also, windows is a built-in term that's used to identify the OS type.

Run the preceding code using the v run hello.v command. You will see Hello, Unix user! as the output.

From the *nix OS, you can run the following command to create a cross-compiled executable targeting the Windows OS.

Before you start generating a cross-compiled binary for the hello.v program, you need to install mingw-64, which is required to generate an executable targeting the Windows OS. To install mingw-64, run the following command:

sudo apt install -y mingw-w64

Alternatively, you can try sudo apt install -y mingw-w64 on Debian-based distributions or sudo pacman -S mingw-w64-gcc on Arch.

Once mingw-64 has been installed, run the following command from the Ubuntu OS to generate the executables that can run on the Windows OS, as follows:

v -os windows hello.v

The preceding command will generate an executable named hello.exe. Now, transfer the .exe file to the Windows OS. Running the executable from Command Prompt will output Hello, Windows user!.

You can also cross-compile to generate *nix binaries from a Windows OS. All you need to do is install Clang for Windows, as described at https://clang.llvm.org/get_started.html, and run the following command, which generates the *nix binary:

v -os linux hello.v

Similarly, to generate an executable for macOS, run the following command:

v -os macos hello.v

V to JavaScript conversion

In addition to C as a primary backend, V also has JavaScript and WASM backends. V programs can be translated into JavaScript. To translate the hello.v into JavaScript, you can run the following command:

v -o hello.js hello.v

It is as simple as the preceding command. The outcome will produce a JavaScript file named hello.js that reflects the functionality written in the hello.v program.

Profiling

V has an built-in profiling tool that you can use to analyze how your program is behaving or how many times a function gets called on average by a function per call. You might need this information to debug and optimize the application code. To run the profiler against the V program, let's say hello.v, run the following command:

v -profile profile.txt hello.v

Notice the usage of the -profile argument, followed by the text file. Running the preceding command generates a binary for the hello.v program. Running the binary generates profile.txt with a detailed list of all the function calls with three columns. Each of the columns in the text file represents the number of calls, average time per call, and total time per call.