Vyxapedia

Beginners' Page

Welcome to the landing page for Vyxal beginners! This resource is intended to guide you from your very first encounter with Vyxal to a point where you can practice solving problems, self-study, and seek help through other channels.


link Conventions and Terminology

A couple of terms and conventions are important to establish and will be used throughout much of this page and website.

  • Arity refers to the number of arguments an element takes as input. A niladic function (nilad) takes zero (0) arguments, monads take one (1), dyads take two (2), and triads take three (3). There are some elements whose arity is not fixed, including ones that consume the entire stack or pop a variable number of elements depending on the context.
  • Elements are functions that apply to values on the stack. These pop any number of arguments (including zero) and push any number of values (including zero) back onto the stack. When dealing with multiple values, the first one pushed will be the last one popped (as is the case with a stack).
  • Modifiers are prefix operators that modify the next element. These are not to be confused with elements that manipulate function objects, as function objects are also values (functions are first-class members in Vyxal).
  • Structures are syntax components in Vyxal, such as if-else statements, loops, lambdas, etc. These are technically also elements, as they manipulate values on the stack and can be modified.

Vyxal is 0-indexed, meaning that the first index of a list is 0 and the last index of a list with N values is N - 1. Index access in lists wraps around, so -1 also refers to the last value, and 4 in a list of 3 values refers to the second value.


link The Stack

Vyxal operates primarily on stacks. The main program has a main stack and functions and lambdas have their own sub-stacks. The principle of a stack is that it is First-In-Last-Out (FILO) - much like a stack of objects in real life, the first item placed onto the stack is the last one retrieved, and retrieving an item will yield the most recently placed item.

The terms are "push" (push an item: place an item on top of the stack) and "pop" (pop an item: remove and retrieve the top of a stack). In Vyxal, the empty stack is popped, it attempts to read a line from input and returns 0 if it cannot.


link Literal Syntax

Vyxal has six types of literals. They are all fairly self-explanatory with some examples.

  • Number Literals are created with .0123456789. Placing these adjacently will create one number literal, exactly as you would expect.
    • To push multiple numbers, separate them with spaces or newlines; for example, 23 456 will push 23 and then 456.
    • A number cannot have multiple decimal points. As such, 123.456.789 pushes 123.456 and then 0.789.
  • String Literals are delimited by backticks (`content goes here`). Unless the D flag is specified, if there are non-ASCII characters in the string, they will be used for string compression (see Your First Program for an example).
  • Base 255 Compressed Number Literals are delimited by ». Each character is indexed into the codepage (with » removed) and converted from base 255.
  • Base 255 Compressed String Literals are delimited by «. The characters are converted just like base 255 compressed numbers are (but with « removed instead). Then, the number is converted into a base-27 number and each digit is indexed into  etaoinshrdlcumwfgypbvkjxqz (note the leading space).
  • Single-Character Literals are written as \x and push the character x. Vyxal does not distinguish between strings of length 1 and characters.
  • Double-Character Literals are written as ‛xy and push the string xy.

link Your First Program

Let's start with a very simple program - Hello World. To get started, head over to the Vyxal interpreter on this site or the official online interpreter.

As mentioned above, Vyxal's strings are delimited by backticks (`...`). Thus, the most basic solution is:

`Hello, World!`

If a string is not terminated at the end of the program, is it implicitly closed, so you can remove the last`. However, there is a shorter way to output Hello, World! using dictionary-compressed strings.

There are 95 printable ASCII characters and a newline, so there are 160 other characters. If the D flag is specified, the characters are left alone. Otherwise, if these characters are present in the string, they will be paired together and indexed into the list of these characters. Then, each pair is converted into base 160 and indexed into the dictionary. If the number is too large (the dictionary does not contain a word for all 25600 possible indexes), the characters stay as-is.

Hello is at index 4539 which is 28, 59 in base 160, so it is represented by the characters ƈṡ. Likewise, World is ƛ€. This leads to the following solution:

`ƈṡ, ƛ€!`

Again, the last ` can be removed if this is at the end of the program. Note that Vyxal also has the niladic element kH (Hello, World!) for this.

Be careful! Compression is not always trivial. The string withree can be compressed as with + ree which would be `λ»ree`, but `wi∧ḭ` is one byte shorter. øD (Dictionary Compression) is guaranteed to find the shortest possible form.


link Vectorization

Before we continue, let's introduce vectorization, a common concept in array languages and golfing languages. Multiplying two lists together doesn't work in most languages (e.g. in Python, [1, 2, 3] * [4, 5, 6] results in an error). Taking the dot product is a possible alternative behavior, but a much more commonly useful behavior instead is to multiply corresponding pairs of elements, so [1, 2, 3] * [4, 5, 6] gives [4, 10, 18]. This is known as vectorization.

Try the following online (⟨1|2|3⟩ is a list - we'll get into the format later):

⟨1|2|3⟩ ⟨4|5|6⟩ *

Many built-ins vectorize in Vyxal. For example, (Function Call) will vectorize down to each individual value, so ⟨-1|0|1⟩ † returns ⟨0|1|0⟩ and ⟨⟨1|0⟩|⟨0|1⟩⟩ † yields ⟨⟨0|1⟩|⟨1|0⟩⟩. Some elements explicitly specify that they do not vectorize; for example, (Logical And): ⟨1|0⟩ ⟨2|3⟩ ∧ returns ⟨2|3⟩, not ⟨2|0⟩.

Vectorization works relatively intuitively for dyads. If the left and right arguments are both single values, it just applies the function to the values. If one argument is a list and the other is a single value, it loops over the list side. For example, ⟨1|2|3⟩ 4 + gives ⟨5|6|7⟩ and 1 ⟨2|3|4⟩ + gives ⟨3|4|5⟩. If both arguments are lists, then it applies to each corresponding pair. if necessary, the shorter list is padded with zeroes on the end. For example, ⟨4|5|6⟩ ⟨2|3|4|5|6⟩ * gives ⟨8|15|24|0|0⟩.


link Structures

Vyxal has several structures that are very similar to features found in conventional / practical programming languages, which was part of its core design philosophy. We've already come across a structure, so let's start with that. Note that you don't have to close structures if it's at the end of the program.

  • ⟨...1 | ...2 | ...3 ...⟩ is a list. Formally, it runs each of its components (...1, ...2, etc.) with an initially empty stack and then joins the top of the stack of each item into a list.
    • Any expression can be contained in each section, so for example, ⟨1 2 + | 3 4 *⟩ returns ⟨3|12⟩. ⟨1 2 | 3 4⟩ will return ⟨2|4⟩ because only the top of the stack is preserved.
    • These can be nested too; ⟨⟨1 | 2⟩ | 3 | ⟨4 | 5⟩⟩ works as you would expect.
  • [...1 | ...2] is an if-statement. It pops an element off the stack; if it is truthy, it runs ...1 on a stack containing only that item and pushes back the top of the sub-stack. If it is falsy, it does the same with ...2 (if the second half is specified). For example, [1 2 + | 3 4] will push 3 if the TOS is truthy and 4 otherwise, and [1] will push 1 if the TOS is truthy and nothing otherwise.
  • (...1 | ...2) is a for-loop statement. It pops an element off the stack and then iterates through it each time. Here, ...1 is optional — if present, the result will be stored in the variable named ...1 each time. The context variable n lets you retrieve the current value regardless of if ...1 is specified.
    • For example, ⟨⟨1|2⟩|⟨3|4⟩⟩ (n(n,)) will output 1 through 4 line-by-line - the outer loop first pushes n ([1, 2] in the first run and [3, 4] in the second) and then loops through that, and the inner loop pushes the value and then uses , (Print) to output it.
    • ⟨⟨1|2⟩|⟨3|4⟩⟩ (a|n(←a,)) prints the following:
      ⟨1|2⟩
      ⟨1|2⟩
      ⟨3|4⟩
      ⟨3|4⟩
      Here, the outer for loop names the loop variablea, pushes the context (which is still available even if we specify a name), and runs an inner for loop, which pushes a (the outer sub-list, not the inner value) and prints that instead.
  • {...1 | ...2} is a while-loop statement. Here, ...1 is optional. It is the while loop's condition, and if it is absent, the condition is automatically true. So long as the result of ...1 is truthy, ...2 runs repeatedly.
  • @name:n|...; denotes a user-defined function. This feature is quite unique to golfing languages, and is part of Vyxal's design concept. The name of the function must be one complete word and not contain any @s. n is the arity of the function; that is, how many elements should be popped from the caller's stack and put into the function's own stack. If the arity is *, it will pop one element and that will be the arity of the function. Finally, ... is the body of the function. After the function is run, it pushes its entire stack back, not just the top value. Functions are called using the syntax @name;.
  • λn|code; is a user-defined lambda. Like lambdas / anonymous functions in other languages, this function does not have a name; rather, it pushes a function object onto the stack directly. n represents the arity and is 1 if not specified. You can apply a lambda with (Function Call), so 1 2 3 λ2|*; † results in 6 on the top of the stack and 1 underneath, whereas 1 2 3 λ3|*; † results in 2 as the only element of the stack.

link Context Variable

There is a special variable known as the context variable. More information is available on its element page here. Essentially, n pushes a value based on the current context. By default, its value is 0. Within a function or lambda, its value is the list of arguments. In a for-loop, it is the current iteration value. In a while-loop, it is the result of the conditional expression.


link Variables

Unlike most golfing languages, Vyxal supports variable-length, readable variable names. A variable name can contain uppercase and lowercase letters and underscores. They are set with (Variable Set) and retrieved with (Variable Get). For example:

`string a` →a   # a = "string a"
`string b` →b # b = "string b"
←a →temp # temp = a
←b →a # a = b
←temp →b # b = temp (swapping the values of a and b)

Notice from this example that Vyxal also supports comments - # will make the rest of the line (until the next newline) a comment.


link Further Resources

Congratulations! You've reached the end of the beginners' tutorial page. Hopefully, you should have a decent idea of what to expect going forward and the fundamentals of Vyxal's structure and functionality. At this point, practice and experience is the best teacher — you can only learn so much from reading. You can also try your hand at solving harder problems on Code Golf Stack Exchange. If you have any questions, feel free to ask in the Vyxal chat room.