Everything in Primal is a function, which can be combined to create more complex functions. Functions cannot be overloaded (i.e. only one function with a given name can exist in a program). The language includes a comprehensive set of over 200 core functions, providing developers with a wide range of useful tools. The full list can be found in the reference page.
Being a functional language, Primal does not have loop constructions. Instead, it uses recursion to perform repetitive tasks, allowing for a more declarative style of programming.
The syntax is designed to be simple and easy to read and consists of function declarations that are evaluated to produce a result.
A function declaration is composed of:
Here is an example of a function with parameters:
And here is an example of a function without parameters:
There is a special function in the language called main, which serves as the entry point of a program when it is run. The main function is optional and can be declared with any number of parameters, including none. If present, it can call other functions and perform computations to produce a result.
If the main function is not present, the program will still run, but no computations will be performed. In this case, the program will run in interactive mode, where the user can enter expressions and see the results of their evaluation.
Primal has a dynamic runtime type checking. This means that users cannot explicitly declare types for parameters or return values in the code. Instead, the system performs type checks during execution to ensure that values match the expected types when passed to functions.
This approach offers flexibility and ease of use but relies on runtime checks to catch type-related issues, which can lead to errors that are only caught during execution.
These are the available types at runtime:
Primal is an interpreted language. The compiler translates the source code into an intermediate representation that is then executed by the interpreter. The interpreter is responsible for executing the intermediate representation and producing the output of the program.
This allows for fast development and testing cycles since changes to the source code can be quickly compiled and executed without the need for a separate build step.