match

From Esolang
Jump to navigation Jump to search

match is an esoteric programming language created by User:Japi. It follows a functional programming paradigm.

Basic Features

Functions

Every program is made up of functions. They are defined by their name, pattern branches, and expressions to evaluate. Each branch is terminated by a semicolon, and the whole function is terminated by another semicolon.

name:
    pattern1 -> expr1;
    pattern2 -> expr2;
    ...
    patternN -> exprN;;

For example, here is a function that adds one to the argument.

add_one:
    number -> number + 1;;

Expressions and Patterns

Parentheses can be used in both patterns and expressions. There are only a few literals:

 'a'   | character literal
 "Hi"  | string literal
 1.3   | number literal
 false | boolean literal
 nil   | nil literal, marks the end of a cons list

String literals can only be used in expressions, everything else can be used in both patterns and expressions. There are some basic binary operators:

 +    | Adds two numbers
 -    | Subtract two numbers
 *    | Multiplies two numbers
 /    | Divides two numbers
 ,    | Makes a pair, usually called cons (right-assoc)
 %    | Modulus operator
 <    | Less than operator
 >    | Greater than operator
 =    | Equality check
 then | Returns the result of the right hand side

In patterns, you can match on literals, deconstruct pairs, and bind results to values. To call a function, you can use the C-style syntax.

print("Hello, world!")

Although, commas will be treated as part of the expression and not separation between arguments because every function takes one argument.

Pairs

Because there is no easy way to curry functions, multiple arguments are usually passed via a cons list, or just a pair. String literals are actually just a cons list of characters. Both of these expressions evaluate to the same thing.

'h', 'i', nil
"hi"

This is also the reason why they can't be used in patterns, you'll have to use the character literals directly for matching on strings.

Command line arguments

The main function accepts an argument, that argument is usually thrown away with a wildcard pattern but it represents the command line arguments for the program. They are given via a cons list, where if there were no arguments given it would be nil.

main: args -> println(args);;

Guards

Guards can be added to patterns after a colon. The guard's value must be a boolean, and only one guard can be supplied to a pattern. The filter function is a good example of this, it takes a list and a predicate, and filters the list to a list only containing the values that follow that predicate.

filter:
    nil, _ -> nil;
    (x, xs), pred: pred(x) -> x, filter(xs, pred);
    (x, xs), pred -> filter(xs, pred);;

Includes

You can also include a specific file in your code like this:

include "other_file.match"

It'll import all the definitions of the functions in that file and the includes int that file, and allow you to use it in your code. You can do multiple includes from anywhere in the program, and any include from a specific file will only be included once. So if a file predicates.match looked like this:

even: n -> n % 2 == 0;;

Then a file main.match could look like this:

include "predicates.match"

main: _ -> println(even(2));;

Examples

Hello, world!

main: _ -> println("Hello, world!");;

truth-machine

truth:
    '0', nil -> println(0);
    '1', nil -> print(1) then truth("1");
    _ -> error("Please type a '0' or '1'.");;
main:
    _ -> print("Type a '0' or '1': ") then truth(readln(nil));;

Sum of list

sum:
    nil -> 0;
    x, xs -> x + sum(xs);;
main:
   _ -> println(sum(1, 2, 3, 4, nil));;

This should output 10.

External resources