Welcome to Vale! Vale is a fast, safe, and simple programming language. This introduction will show how to write a program in Vale.
This reference assumes that you are familiar with basic programming concepts, and at least one other imperative language (like C, Java, Python, etc).
Vale is still "in alpha", which means it's a preview; you can write programs in it, but some of the features that make it easy aren't yet available.
Run the code to the right 0 to see it produce the output in the gray box.
We can make a local with the = symbol.
By default, a local is "final". A final local cannot be changed after it's made.
You can put the code into e.g. hello.vale and invoke the compiler with python3 valec.py hello.vale. (After 0.1, it will simply be vale build hello.vale.)
That will produce an executable named hello.exe (on Windows) or hello (on Mac or Linux).
Vale's x and x! are like Java's final String x and String x.
mut x does not declare a local named x. It changes an existing local's value.
Vale is a statically typed language, which means the type of every local and member is known at compile-time.
In this example, a is a str. We can even specify it after the local's name.
...though we usually leave it out, because Vale uses type inference to figure out the type of a for us.
Here we have a simple function that returns the argument plus two.
If we use the infer-ret keyword, Vale will automatically figure out the return type of the function. 3
If a block has only one line, we can leave off the ret and the semicolon.
We can also make a lambda, a function inside another one. 4
We can leave the type off of a lambda's parameter, to make it shorter. 5
We can shorten lambdas with the almighty underscore, which declares and immediately uses an implicit parameter.
infer-ret should be used sparingly, as it increases compile times.
See the Tuples section below for an example of how lambdas are super useful.
Taking out the parameter's type makes this a "generic" lambda, see generics for more.
This is known as Universal Function Call Syntax. This makes method chaining nicer, for example
a.f(3).g(true).h("Yendor")
as opposed to
h(g(f(a, 3), true), "Yendor").
Include vstl/list.vale for the split function.
A tuple is a simple struct, whose members are named 0, 1, 2, etc.
We can make a tuple in Vale with square brackets (like [5, true, "V"]), and can access them with a dot ,like arr.0.
We can only make a tuple if we know the number of elements at compile-time. If we don't know, then we must use an array.
We can make an array with the Array function.
stdinReadInt reads an integer from the user's keyboard. In this example, the user is entering 3.
stdinReadInt is experimental, expect the stdin/stdout API to change soon.
The type of arr here is Array<int>.
Arrays can't be resized at run-time. Lists can!
We can make one with the List function. 10
Vale's lists are like C#'s List, Java's ArrayList or C++'s vector; it's backed by an array, not a linked list.
We can loop with the each statement: 11
We can also get the index of the current iteration with the eachI statement.
The each statement is syntactic sugar for the each method:
each arr (x){ println(x); }
is equivalent to
arr.each((x){ println(x); })
These are planned features for Vale. See the roadmap for plans!
We'll be able to produce a variant, which is something that can be one of two types (or more).
To make a variant, use an if-statement, and return a different type from the then branch than the else branch.
Here, a is a variant, either a string or an integer. a's type is (str|int).
Later, we can use the match statement to determine if a actually contains a str or an int.
We'll be able to access a arbitrary fields of tuples or structs with square brackets, like arr[1 + 1], which would produce a variant. 12
Specifically, indexing this tuple gives a variant (int|bool|str), with a + function that calls the appropriate actual + depending on the run-time type (int vs bool vs str).
Next: Structs