About min

min is an concatenative, fully-homoiconic, functional, interpreted programming language.

This basically means that:

Why?

Because creating a programming language is something that every programmer needs to do, at some point in life. And also because there are way too few concatenative programming language out there – so people are likely to be less pissed off than if I made a yet another Lisp instead.

I always wanted to build a minimalist language, but that could also be used for real work and provided a standard library for common tasks and functionalities like regular expression support, cryptography, execution of external programs, shell-like operators and keywords to work with files, and more.

Also, I wanted it to be fully self-contained, cross platform, and tiny. About 1MB (depending on the platform) is not really tiny, but I feel it’s a good compromise compared to the alternatives out there, considering that you only need one file to run any min program.

I am currently building a static site generator called HastySite, that also powers https://min-lang.org. HastySite internally uses min as the language to write the rules to process the source files of the site, and also all its scripts.

Finally, I think more and more people should get to know concatenative programming languages, because concatenative programming matters.

How?

min is developed entirely in Nim – the name is (almost) entirely a coincidence. I wanted to call it minim but then shortened it for more… minimalism.

min’s parser started off as a fork of Nim’s JSON parser – adapted to process a concatenative programming language with less primitive types than JSON. It is interpreted in the traditional sense: no bytecode, no JIT, just plain read, parse and run.

Who?

min was created and implemented by Fabio Cevasco, with contributions by Peter Munch-Ellingsen.

When?

min source code repository was created on November 8th 2014. This only means that I’ve been very slowly developing something that was actually made public at the end of July 2017.

Getting Started

You can download one of the following pre-built min binaries:

Building from Source

Alternatively, you can build min from source as follows:

  1. Download and install nim.
  2. Download and build Nifty, and put the nifty executable somewhere in your $PATH.
  3. Clone the min repository.
  4. Navigate to the min repository local folder.
  5. Run nifty install to download min’s dependencies.
  6. Run nim c -d:release min.nim.

Running then min Shell

To start min shell, run min -i. You will be presented with a prompt displaying the path to the current directory:

[/Users/h3rald/test]$

You can type min code and press ENTER to evaluate it immediately:

[/Users/h3rald/test]$ 2 2 + {1} -> 4 [/Users/h3rald/test]$

The result of each operation will be placed on top of the stack, and it will be available to subsequent operation

[/Users/h3rald/test]$ dup * {1} -> 16 [/Users/h3rald/test]$

To exit min shell, press CTRL+C or type exit and press ENTER.

Executing a min Program

To execute a min script, you can:

min also supports running programs from standard input, so the following command can also be used (on Unix-like system) to run a program saved in myfile.min:

$ cat myfile.min | min

Learning the min Language

min is a stack-based, concatenative programming language that uses postfix notation. If you already know Forth, Factor or Joy, or if you ever used an RPN calculator, then min will look somewhat familiar to you.

If not, well, here’s how a short min program looks like:

; This is a comment
(1 2 3 4 5) (dup *) map

This program returns a list containing the square values of the first five integer numbers:

(1 4 9 16 25)

Let’s see how it works:

  1. First a list containing the first five integer is pushed on the stack.
  2. Then, another list containing two symbols (dup and *) is pushed on the stack. This constitutes a quoted program which, when executed duplicates (dup) the first element on the stack and then multiplies (*) the two elements together.
  3. Finally, the symbol map is pushed on the stack. Map takes a list of elements and a quoted program and applies the program to each element.

Note that:

Unlike more traditional programming languages, in a concatenative programming language there is no inherent need of variables or named parameters, as symbols acts as stack operators that consume elements that are placed in order on top of a stack.

Data Types

The type system of min is very simple – only the following data types are available:

integer
An integer number like 1, 27 or -15.
float
A floating-point number like 3.14 or -56.9876.
string
A series of characters wrapped in double quotes: “Hello, World!”.
quotation
A list of elements, which may also contain symbols. Quotations can be be used to create heterogenous lists of elements of any data type, and also to create a block of code that will be evaluated later on (quoted program).

Additionally, quotations structured in a particular way can be used as dictionaries, and a few operators are available to manage them more easily (dhas?, dget, ddel and dset). A dictionary is a quotation containing zero or more quotations of two elements, the first of which is a symbol that has not already be used in any of the other inner quotations.

The logic Module provides predicate operators to check if an element belong to a particular data type or pseudo-type (boolean?, number?, integer?, float?, string?, quotation?, dictionary?).

Note

Most of the operators defined in the num Module are able to operate on both integers and floats.

Quotations

Quotations are the most important thing to understand in min. Besides being the data type used for lists, they are also used to delimit blocks of min code that is not going to be immediately executed.

Consider for example the following min code which returns all the files present in the current folder sorted by name:

 . ls (ftype "file" ==) filter '> sort

The symbol filter takes two quotations as arguments – the first quotation on the stack is applied to all the elements of the second quotation on the stack, to determine which elements of the second quotation will be part of the resulting quotation. This is an example of how quotations can be used both as lists and programs.

Let’s examine this program step-by-step:

  1. The . symbol is pushed on the stack, and it is immediately evaluated to the full path to the current directory.
  2. The ls symbol is pushed on the stack, it consumes the string already on the stack and returns a quotation containing all files and directories within the current directory.
  3. The quotation (ftype 'file ==) is pushed on the stack. It is treated exactly like a list of data and it is not evaluated.
  4. The filter symbol is pushed on the stack. This symbol takes two quotations as input, and applies the result of the first quotation on the stack ((ftype "file" ==)) to all elements of the second quotation of the stack (the list of files and directories), returning a new quotation containing only those elements of the second quotation on the stack that satisfy the result of the first quotation. In this case, it returns a new quotation containing only files.
  5. '> is pushed on the stack. The ' sigil can be used instead of the quote symbol to quote a single symbol, < in this case. In other words, it is instantly evaluated to the quotation (>).
  6. The symbol sort is pushed on the stack. This symbol, like filter, takes two quotations as input, and applies the first quotation to each element of the second quotation, effectively sorting each element of the second quotation using the predicate expressed by the first quotation. In this case, all files are sorted by name in ascending order.

Tip

The {seq Module} provides several symbols to work with quotations in a functional way.

Quoting, dequoting, and applying

When a quotation is created, it is treated as data, no matter what it contains: it is placed on the stack, like an integer or a string would. However, unlike other data types, a quotation can be evaluated in certain situations and when it happens its contents are pushed on the stack.

Consider the following program:

 (1 2 3 4 5 6 7) (odd?) filter

This programs returns a new quotation containing all odd numbers contained in quotation (1 2 3 4 5 6 7).

In this case, the second quotation is used to quote the symbol odd? so that instead of being executed immediately, it will be executed by the symbol filter on each element of the first quotation. In this way, we may say that (odd?) is dequoted by the symbol filter.

The synbol dequote or its alias -> can be used to dequote a quotation by pushing all its element on the main stack, while the symbol apply can be used to dequote a quotation by pushing its element on a separate stack.

Operators

Every min program needs operators to:

There are two types of operators: symbols and sigils.

Symbols are the most common type of operator. A min symbol is a single word that is either provided by one of the predefined min modules like dup or . or defined by the user. User-defined symbols must:

It is possible to define symbols using the define symbol. The following min program defines a new symbol called square that duplicates the first element on the stack and multiplies the two elements:

 (dup *) "square" define

Besides symbols, min provides a set of predefined sigils for commonly-used symbols. For example, the previous definition could be rewritten as follows using sigils:

 (dup *) :square

A sigil like : can be prepended to a single-word string instead of using the corresponding symbol. Essentially, sigils are nothing more than syntactic sugar. Currently min provides the following sigils:

+
Alias for module.
~
Alias for delete.
'
Alias for quote.
:
Alias for define.
^
Alias for call.
@
Alias for bind.
>
Alias for save-symbol.
<
Alias for load-symbol.
=
Alias for quote-bind.
#
Alias for quote-define.
/
Alias for dget.
%
Alias for dset.
?
Alias for dhas?.
!
Alias for system.
&
Alias for run.
$
Alias for get-env.

{#link-learn||quotations||Quotations#}

Definitions

Being a concatenative language, min does not really need named parameters or variables: simbols just pop elements off the main stack in order, and that’s normally enough. There is however one small problem witht the traditional concatenative paradigm; consider the following program for example:

 dup dup
 "\.zip$" match 
 swap fsize 1000000 > and 
 swap mtime now 3600 - >

This program takes a single string corresponding to a file path and returns true if it’s a .zip file bigger than 1MB that was modified in the last how. Sure, it is remarkable that no variables are needed for such a program, but it is not very readable: because no variables are used, it is often necessary to make copies of elements and push them to the end of the stack – that’s what the dup and {#link-operator||stack||swap#} are used for.

The good news is that you can use the define operator and the : sigil to define new symbols, and symbols can also be set to literals of course.

Consider the following program:

 :filepath
 filepath "\.zip$" match
 filepath fsize 1000000 >
 filepath mtime now 3600 - >
 and and

In this case, the filepath symbol is defined and then used on the following three lines, each of which defines a condition to be evaluated. The last line contains just two and symbols necessary to compare the three conditions.

Lexical scoping and binding

min, like many other programming languages, uses lexical scoping#Lexical_scope_vs._dynamic_scope) to resolve symbols.

Consider the following program:

 4 :a
 ( 
   a 3 + :a
   (
      a 1 + :a
      (a dup * :a) dequote
   ) dequote
 ) dequote

…What is the value of the symbol a after executing it?

Simple: 4. Every quotation defines its own scope, and in each scope a new variable called a is defined. In the innermost scope containing the quotation (a dup * :a) the value of a is set to 64, but this value is not propagated to the outer scopes. Note also that the value of a in the innermost scope is first retrieved from the outer scope (8).

If we want to change the value of the original a symbol defined in the outermost scope, we have to use the bind or its shorthand sigil @, so that the programs becomes the following:

 4 :a ;First definition of the symbol a
 (
   a 3 + @a ;The value of a is updated to 7.
   (
     a 1 + @a ;The value of a is updated to 8
     (a dup * @a) dequote ;The value of a is now 64
   ) dequote
 ) dequote

quote-define and quote-bind

So far, we saw how to use the define and bind operator (or better, their shorthand sigils : and @) to define new symbols or bind values to existing ones.

Consider the following example:

 (1 2 3 4 5) :my-list
 my-list (dup *) map

If run the program above in min shell by pasting the first and then the second line in it, you’ll get an error similar to the following:

 (!) <repl>(1,19) [map]: Incorrect values found on the stack:
 - expected: {top} quot quot {bottom}
 - got:      {top} quot int {bottom}
     <repl>(1,19) in symbol: map

This error says that when the map operator was evaluated, there were incorrect values on the stack. Two quotations were expected, but instead a quotation and an integer were found. How did this happen?

Basically, when my-list was pushed on the stack, it pushed all its item on top of the stack. If you run get-stack, it will return the following list:

 (1 2 3 4 5 (dup *))

This happens because by default min assumes that when you define a quotation you want to define a new operator rather than a list. The following program works as expected, and it returns a list containing the squares of the first five integer numbers:

 (dup *) :square
 (1 2 3 4 5) (square) map

To avoid this behavior – i.e. whenever you want to define a list of items rather than an operator that will be immediately evaluated when pushed on the stack, you have to use the quote-define and the quote-bind or their respective sigils # and =:

 (1 2 3 4 5) #my-list
 my-list (dup *) map ;Returns (1 4 9 16 25) 

Sealing symbols

Finally, symbols can be sealed to pervent accidental updates or deletions. By default, all symbols defined in the core min modules are sealed, so the following code if run in min shell will result in an error:

 5 :quote

…because the symbol quote is already defned in the root scope. However, note that the folliwng code will not return an error:

 (5 :quote quote dup *) -> ;returns 25

…because the quote symbol is only defined in the root scope and can therefore be redefined in child scopes.

If you want, you can seal your own symbols so that they may not be redefined using the bind operator or deleted using the delete.

Note

The unseal operator can be used to effectively un-seal a previously-sealed symbol. Use with caution!

Control Flow

The lang Module provide some symbols that can be used for the most common control flow statements. Unlike most programming language, min does not differentiate between functions and statements – control flow statements are just ordinary symbols that manipulate the main stack.

Conditionals

The following symbols provide ways to implement common conditional statements:

For example, consider the following program:

 (
   (  
     "" :type
     (("\.(md|markdown)$") ("markdown" @type))
     (("\.txt$") ("text" @type))
     (("\.min$") ("min" @type))
     (("\.html?$") ("HTML" @type))
     ((true) ("unknown" @type))
   ) case 
   "This is a $1 file." (type) % echo
 ) :display-file-info

This program defines a symbol display-file-info that takes a file name and outputs a message displaying its type, if known.

Loops

The following symbols provide ways to implement common loops:

For example, consider the following program:

 (
   :n
   1 :i
   1 :f
   (i n <=)
   (
     f i * @f 
     i succ @i
   ) while
   f
 ) :factorial

This program defines a symbol factorial that calculates the factorial of an integer iteratively using the symbol while.

Error handling

The following symbols provide ways to manage errors in min:

For example, consider the following program:

 . ls
 (
   (
     (fsize) 
     (pop 0)
   ) try
 ) map 
 1 (+) reduce

This program calculates the size in bytes of all files included in the current directory. Because the fsize symbol throws an error if the argument provided is not a file (for example if it is a directory), the try symbol is used to remove the error from the stack and push 0 on the stack instead.

Using the min Shell

The min executable also provide an interactive REPL (Read-Eval-Print Loop) when launched with the -i flag:

$ min -i [/Users/h3rald/Development/min]$

Although not as advanced, the min REPL is not dissimilar from an OS system shell like Bash, and as a matter of fact it provides many functionalities that are found in other shells or command prompts, such as:

…plus in can obviously leverage the entire min language for complex scripting.

Autocompletion and shortcuts

The min shell features smart tab autocompletion and keyboard shortcut implemented using the nimline library.

The following behaviors are implemented when pressing the TAB key within:

Context Result
…a string Auto-completes the current word using file and directory names.
…a word starting with ! or & Auto-completes the current word using executable file names.
…a word starting with $ Auto-completes the current word using environment variable names.
…a word starting with ', ~, @, #, >, <, *, ( Auto-completes the current word using symbol names.

Additionally, at least some of the following systems should also be available, depending on your operating system:

Key Effect
INSERT Switches between insert and replace mode.
UP Displays the previous history entry.
DOWN Displays the next history entry.
CTRL+c Terminates min shell.
CTRL+x Clears the current line.
CTRL+b Goes to the beginning of the line.
CTRL+e Goes to the end of the line.

Shell configuration files

When the min interpreter is first launched, the following files are created automatically in the $HOME directory (%HOMEPROFILE% on Windows).

.minrc

This file is interpreted first every time min is run. By default it is empty, but it can be used to define code to execute at startup.

.min_history

This file is used to persist all commands entered in the min shell, and it is loaded in memory at startup to provide line history support.

.min_symbols

This files contains all symbol definitions in JSON format that were previously-saved using the save-symbol symbol. Symbols can be loaded using the load-symbol symbol.

Extending min

min provides a fairly complete standard library with many useful modules. However, you may feel the need to extend min in order to perform more specialized tasks.

In such situations, you basically have three options:

Implementing new min modules using min itself

When you just want to create more high-level min operator using functionalities that are already available in min, the easiest way is to create your own reusable min modules.

The module (and the + sigil) allows you to create a new min module:

(
  (dup *)             :pow2

  (dup dup * *)       :pow3

  (dup dup dup * * *) :pow4

) +quickpows

Save your code to a file (e.g. quickpows.min) and you can use it in other nim files using the load operator and the import:

'quickpows load
'quickpows import

2 pow3 pow2 puts ;prints 64

Embedding min in your Nim program

If you’d like to use min as a scripting language within your own program, and maybe extend it by implementing additional operators, you can use min as a Nim library.

To do so:

  1. Install min sources using Nifty as explained in the Download section.
  2. Import it in your Nim file.
  3. Implement a new proc to define the module.

The following code is taken from HastySite and shows how to define a new hastysite module containing some symbols (preprocess, postprocess, process-rules, …):

import packages/min/min

proc hastysite_module*(i: In, hs1: HastySite) =
  var hs = hs1
  let def = i.define()

  def.symbol("preprocess") do (i: In):
    hs.preprocess()

   def.symbol("postprocess") do (i: In):
    hs.postprocess()

  def.symbol("process-rules") do (i: In):
    hs.interpret(hs.files.rules)

  # ...

  def.finalize("hastysite")

Then you need to:

  1. Instantiate a new min interpreter using the newMinInterpreter proc.
  2. Run the proc used to define the module.
  3. Call the interpret method to interpret a min file or string:
proc interpret(hs: HastySite, file: string) =
  var i = newMinInterpreter(file, file.parentDir)
  i.hastysite_module(hs)
  i.interpret(newFileStream(file, fmRead))

Tip

For more information on how to create new modules with Nim, have a look in the lib folder of the min repository, which contains all the min modules included in the standard library.

Implementing min modules as dynamic libraries

Warning

This technique is currently experimental, it has not been tested extensively and it may not even work on Windows.

If you just want to add a new module to min providing functinalities that cannot be built natively with min operators, you can also implement a min module in Nim and compile it to a dynamic library which can be linked dynamically when min is started.

In order to do this, you don’t even need to download the whole min source code, you just need to download the mindyn.nim file and import it in your Nim program.

The following code shows how to create a simple min module called dyntest containing only a single operator dynplus, which essentially returns the sum of two numbers:

import mindyn

proc dyntest*(i: In) {.dynlib, exportc.} =

  let def = i.define()

  def.symbol("dynplus") do (i: In):
    let vals = i.expect("num", "num")
    let a = vals[0]
    let b = vals[1]
    if a.isInt:
      if b.isInt:
        i.push newVal(a.intVal + b.intVal)
      else:
        i.push newVal(a.intVal.float + b.floatVal)
    else:
      if b.isFloat:
        i.push newVal(a.floatVal + b.floatVal)
      else:
        i.push newVal(a.floatVal + b.intVal.float)

  def.finalize("dyntest")

Note that the mindym.nim file contains the signatures of all the procs that are commonly used to define min modules, but not their implementation. Such procs will become available at run time when the dynamic library is linked to the min executable.

You can compile the following library by running the following command:

$ nim c –app:lib -d:release –noMain dyntest.nim

If you are using clang to compile Nim code, you may need to run the following command instead:

$ nim c –app:lib -d:release –noMain -l:“-undefined dynamic_lookup” dyntest.nim

Now you should have a libdyntest.so|dyn|dll file. To make min load it and link it automatically when it starts, just run:

$ min –install:libdyntest.dyn

This command will copy the library file to $HOME/.minlibs/ (%HOMEPATH%\.minlibs\ on Windows). min looks for dynamic libraries in this folder when it starts.

Notes

  • The dynamic library file must have the same name as the module it defines (dyntest in this case).
  • At startup, min links all your installed dynamic libraries but does not import the modules automatically.

If you wish to uninstall the library, run the following command instead:

$ min –uninstall:libdyntest.dyn

Reference

min includes a small but powerful standard library organized into the following modules:

lang Module
Defines the basic language constructs, such as control flow, type conversions, symbol definition and binding, exception handling, etc.
stack Module
Defines combinators and stack-shufflers like dip, dup, swap, cons, etc.
seq Module
Defines operators for quotations and dictionaries, like map, filter, reduce, etc.
io Module
Provides operators for reading and writing files as well as printing to STDOUT and reading from STDIN.
fs Module
Provides operators for accessing file information and properties.
logic Module
Provides comparison operators for all min data types and other boolean logic operators.
str Module
Provides operators to perform operations on strings, use regular expressions, interpolation, etc..
sys Module
Provides operators to use as basic shell commands, access environment variables, and execute external commands.
num Module
Provides operators to perform simple mathematical operations on integer and floating point numbers.
time Module
Provides a few basic operators to manage dates, times, and timestamps.
crypto Module
Provides operators to compute hashes (MD5, SHA1, SHA224, SHA256, SHA384, sha512), base64 encoding/decoding, and AES encryption/decryption.
math Module
Provides many mathematical operators and constants such as trigonometric functions, square root, logarithms, etc.

Notation

The following notation is used in the signature of all min operators:

Types and Values

No value.
a
A value of any type.
bool
A boolean value
int
An integer value.
float
A float value.
num
A numeric (integer or float) value.
string
A string value.
'sym
A string-like value (string or quoted symbol).
quot
A quotation (also expressed as parenthesis enclosing other values).
dict
A dictionary value.
tinfo
A timeinfo dictionary:
(
  (“year” 2017)
  (“month” 7)
  (“day” 8)
  (“weekday” 6)
  (“yearday” 188)
  (“hour” 15)
  (“minute” 16)
  (“second” 25)
  (“dst” true)
  (“timezone” -3600)
)
err
An error dictionary:
(
  (“error” “MyError”)
  (“message” “An error occurred”)
  (“symbol” “symbol1”)
  (“filename” “dir1/file1.min”)
  (“line” 3)
  (“column” 13)
)
true
true (boolean type).
false
false (boolean type)

Suffixes

The following suffixes can be placed at the end of a value or type to indicate ordering or quantities.

1
The first value of the specified type.
2
The second value of the specified type.
3
The third value of the specified type.
4
The fourth value of the specified type.
?
Zero or one.
*
Zero or more.
+
One or more

lang Module

'

'string string quote

See quote.

'

' quote

See quote.

:

:string string define

See define.

:

: define

See define.

~

~string string delete

See delete.

+

+string string module

See module.

^

^string string call

See call.

^

^ call

See call.

@

@string string bind

See bind.

@

@ bind

See bind.

>

>string string save-symbol

See save-symbol.

<

<string string load-symbol

See load-symbol.

->

-> dequote

See dequote.

=>

=> apply

See apply.

#

#string string quote-define

See quote-define.

=

=string string quote-bind

See quote-bind.

apply

quot (a*)

Returns a new quotation quot obtained by evaluating each element of quot in a separate stack.

args

quot

Returns a list of all arguments passed to the current program.

bind

a 'sym

Binds the specified value (auto-quoted) to an existing symbol 'sym.

bool

a bool

Converts a to a boolean value based on the following rules:

  • If a is a boolean value, no conversion is performed.
  • If a is a non-zero numeric value, it is converted to true, otherwise it is converted to false.
  • If a is a non-empty quotation, it is converted to true, otherwise it is converted to false.
  • If a is a non-empty string or not "false", it is converted to true, otherwise it is converted to false.

call

quot 'sym a*

Calls operator 'sym defined in scope quot.

case

((quot1 quot2)*) a*

This operator takes a quotation containing n different conditional branches.

Each branch must be a quotation containing two quotations, and it is processed as follows:

  • if quot1 evaluates to true, then the quot2 is executed.
  • if quot1 evaluates to false, then the following branch is processed (if any).

debug

Toggles debug mode.

debug?

bool

Returns true if debug mode is on, false otherwise.

define

a 'sym

Defines a new symbol 'sym, containing the specified value (auto-quoted if not already a quotation).

defined?

'sym bool

Returns true if 'sym is defined, false otherwise.

delete

'sym

Deletes the specified symbol 'sym.

dequote

quot a*

Pushes the contents of quotation quot on the stack.

eval

string a*

Parses and interprets string.

exit

int

Exits the program or shell with int as return code.

expect

quot1 quot2

Validates the first n elements of the stack against the type descriptions specified in quot1 (n is quot1’s length) and if all the elements are valid returns them wrapped in quot2 (in reverse order).

float

a float

Converts a to an integer value based on the following rules:

  • If a is true, it is converted to 1.0.
  • If a is false, it is converted to 0.0.
  • If a is a integer, it is converted to float value.
  • If a is a float, no conversion is performed.
  • If a is a string, it is parsed as a float value.

foreach

quot1 quot2 a*

Applies the quotation quot2 to each element of quot1.

format-error

err string

Formats the error err as a string.

from-json

string a*

Converts a JSON string into min data.

if

quot1 quot2 quot3 a*

If quot1 evaluates to true then evaluates quot2, otherwise evaluates quot3.

import

'sym

Imports the a previously-loaded module 'sym, defining all its symbols in the current scope.

int

a int

Converts a to an integer value based on the following rules:

  • If a is true, it is converted to 1.
  • If a is false, it is converted to 0.
  • If a is an integer, no conversion is performed.
  • If a is a float, it is converted to an integer value by truncating its decimal part.
  • If a is a string, it is parsed as an integer value.

linrec

quot1 quot2 quot3 quot4 a*

Implements linear recursions as follows:

  1. Evaluates quot1.
    • If quot1 evaluates to true, then it evaluates quot2.
    • Otherwises it executes quot3 and recurses using the same four quotations.
  2. Finally, it executes quot4.

load

'sym a*

Parses and interprets the specified min file, adding .min if not specified.

load-symbol

'sym a*

Loads the contents of symbol 'sym from the .min_symbols file.

loglevel

'sym

Sets the current logging level to 'sym. 'sym must be one of the following strings or quoted symbols:

  • debug
  • info
  • notice
  • warn
  • error
  • fatal

Note

The default logging level is notice.

module

quot 'sym

Creates a new module 'sym based on quotation quot.

module-sigils

quot (string*)

Returns a list of all sigils defined in module quot.

module-symbols

quot (string*)

Returns a list of all symbols defined in module quot.

opts

dict

Returns a dictionary of all options passed to the current program, with their respective values.

prompt

string

This symbol is used to configure the prompt of the min shell. By default, it is set to the following quotation:

([$1]$$ " (.) => %)

Unlike other predefined symbols, this symbol is unsealed, which means it can be modified.

publish

'sym quot

Publishes symbol 'sym to the scope of quot.

quote

a (a)

Wraps a in a quotation.

quote-bind

a 'sym

Quotes a and binds the quotation to the existing symbol 'sym.

quote-define

a 'sym

Quotes a and assigns the quotation to the symbol 'sym, creating it if not already defined.

raise

err

Raises the error specified via the dictionary err.

remove-symbol

'sym

Removes the symbol 'sym from the .min_symbols file.

save-symbol

'sym

Saves the contents of symbol 'sym to the .min_symbols file.

seal

'sym

Seals symbol 'sym, so that it cannot be re-assigned.

sigils

(string*)

Returns a list of all sigils defined in the ROOT scope.

source

'sym quot

Display the source code of symbol 'sym (if it has been implemented a min quotation).

stored-symbols

(string*)

Returns a quotation containing all symbols stored in the .min_symbols file.

string

a string

Converts a to its string representation.

symbols

(string*)

Returns a list of all symbols defined in the ROOT scope.

tap

a quot a

Performs the following operations:

  1. Removes a from the stack.
  2. For each quotation defined in quot (which is a quotation of quotations each requiring one argument and returning one argument):
    1. Pushes a back to the stack.
    2. Dequotes the quotation and saves the result as a.
  3. Push the resulting a back on the stack.

tap!

a quot a

Performs the following operations:

  1. Removes a from the stack.
  2. For each quotation defined in quot (which is a quotation of quotations each requiring one argument and returning one argument):
    1. Pushes a back to the stack.
    2. Dequotes the quotation and saves the result as a.

times

quot int a*

Applies the quotation quot int times.

to-json

quot string

Converts quot into a JSON string string.

try

(quot1 quot2? quot3?) a*

Evaluates a quotation as a try/catch/finally block.

The must contain the following elements:

  1. A quotation quot1 containing the code to be evaluated (try block).
  2. (optional) A quotation quot2 containing the code to execute in case of error (catch block).
  3. (optional) A quotation quot3 containing the code to execute after the code has been evaluated, whether an error occurred or not (finally block).

unless

quot1 quot2 a*

If 1 evaluates to false then evaluates 2.

unseal

'sym

Unseals symbol 'sym, so that it can be re-assigned.

version

string

Returns the current min version number.

when

quot1 quot2 a*

If quot1 evaluates to true then evaluates quot2.

while

quot1 quot2 a*

Executes quot2 while quot1 evaluates to true.

with

quot1 quot2 a*

Applies quotation quot1 within the scope of quot2.

stack Module

clear-stack

Empties the stack.

cleave

a1 (quot*) a*

Applies each quotation contained in the first element to the second element a1.

cons

a1 (a*) (a1 a*)

Prepends a1 to the quotation on top of the stack.

dip

a1 (a2) a* a1

Removes the first and second element from the stack, dequotes the first element, and restores the second element.

dup

a1 a1 a1

Duplicates the first element on the stack.

get-stack

(a*)

Returns a quotation containing the contents of the stack.

id

Does nothing.

keep

a1 quot a* a1

Applies each quotation contained in the first element to each subsequent corresponding element.

nip

a1 a2 a2

Removes the second element from the stack.

over

a1 a2 a1 a2 a1

Pushes a copy of the second element on top of the stack.

pick

a1 a2 a3 a1 a2 a3 a1

Pushes a copy of the third element on top of the stack.

pop

a

Removes the first element from the stack.

rolldown

a1 a2 a3 a2 a3 a1

Moves the third element in first position, the second in third position and the the first in second position.

rollup

a1 a2 a3 a3 a2 a1

Moves the third and second element into second and third position and moves the first element into third position.

set-stack

quot a*

Substitute the existing stack with the contents of quot.

sip

a1 (a2) a* a1

Saves the a1, dequotes a2, and restores a1.

spread

a* (quot*) a*

Applies each quotation contained in the first element to each subsequent corresponding element.

swap

a1 a2 a2 a1

Swaps the first two elements on the stack.

swons

(a*) a1 (a1 a*)

Prepends a1 to the quotation that follows it.

seq Module

/

/string string dget

See dget.

?

?string string dhas?

See dhas?.

%

%string string dset

See dset.

all?

quot1 quot2 bool

Applies predicate quot2 to each element of quot1 and returns true if all elements of quot1 satisfy predicate quot2, false otherwise.

any?

quot1 quot2 bool

Applies predicate quot2 to each element of quot1 and returns true if at least one element of quot1 satisfies predicate quot2, false otherwise.

append

a quot (a* a)

Returns a new quotation containing the contents of quot with a appended.

get

quot int a

Returns the nth element of quot (zero-based).

concat

quot1 quot2 quot3

Concatenates quot1 with quot2.

ddel

dict1 'sym dict2

Returns a copy of dict1 without the element with key 'sym.

dget

dict 'sym a

Returns the value of key 'sym from dictionary dict.

dhas?

dict 'sym bool

Returns true if dictionary dict contains the key 'sym, false otherwise.

dkeys

dict (string*)

Returns a quotation containing all the keys of dictionary dict.

dpick

dict1 quot dict2

Returns a new dictionary dict2 containing the elements of dict1 whose keys are included in quot.

dset

dict1 a 'sym dict2

Sets the value of the 'sym of dict1 to a, and returns the modified copy of the dictionary dict2.

dsort

dict1 dict2

Returns a new dictionary dict2 containing all elements of dict1 sorted by key in ascending order.

dvalues

dict (a*)

Returns a quotation containing all the values of dictionary dict.

filter

quot1 quot2 quot3

Returns a new quotation quot3 containing all elements of quot1 that satisfy predicate quot2.

find

quot1 quot2 int

Returns the index of the first element within quot1 that satisfies predicate quot2.

first

quot a

Returns the first element of quot.

flatten

quot1 quot2

Flattens all quotations within quot1 and returns the resulting sequence quot2.

harvest

quot1 quot2

Creates a new quotation quot2 containing all elements of quot1 except for empty quotations.

in?

quot a bool

Returns true if a is contained in quot, false otherwise.

insert

quot1 a int quot2

Inserts a as the value of the nth element quot1 (zero-based), and returns the modified copy of the quotation quot2.

last

quot a

Returns the last element of quot.

map

quot1 quot2 quot3

Returns a new quotation quot3 obtained by applying quot2 to each element of quot1.

map-reduce

quot1 quot2 quot3 int

Applies quot2 (map) to each element of quot1 and then applies quot3 (reduce) to each successive element of quot1. quot1 must have at least one element.

partition

quot1 quot2 quot3 quot4

Partitions quot1 into two quotations: quot3 contains all elements of quot1 that satisfy predicate quot2, quot4 all the others.

prepend

a quot (a a*)

Returns a new quotation containing the contents of quot with a prepended.

reduce

quot1 a quot2 int

Combines each successive element of quot1 using quot2. On the first iteration, the first two inputs processed by quot2 are a and the first element of quot1.

reject

quot1 quot2 quot3

Returns a new quotatios quot3 including all elements of quot1 that do not satisfy predicate quot2 (i.e. the opposite of filter)

remove

quot1 int quot2

Returns the nth element of quot1 (zero-based), and returns the modified copy of the quotation quot2.

rest

quot1 quot2

Returns a new quotation quot2 containing all elements of quot1 quotation except for the first.

reverse

quot1 quot2

Returns a new quotation quot2 containing all elements of quot1 in reverse order.

set

quot1 a int quot2

Sets the value of the nth element quot1 (zero-based) to a, and returns the modified copy of the quotation quot2.

shorten

quot1 int quot2

Returns a quotation quot2 containing the first n values of the input quotation quot1.

size

quot int

Returns the length of quot.

slice

quot1 a1 a2 quot2

Creates a new quotation quot2 obtaining by selecting all elements of quot1 between indexes a1 and a2.

sort

quot1 quot2 quot3

Sorts all elements of quot1 according to predicate quot2.

io Module

ask

string1 string2

Prints string1 (prompt), reads a line from STDIN and places it on top of the stack as a string.

choose

((string1 quot1)+) string2 a*

Prints string2, then prints all string1 included in the quotation prepended with a number, and waits from valid input from the user.

If the user enters a number that matches one of the choices, then the corresponding quotation quot1 is executed, otherwise the choice menu is displayed again until a valid choice is made.

column-print

quot int a

Prints all elements of quot to STDOUT, in int columns.

confirm

string bool

Prints string (prompt) appending " [yes/no]: ", reads a line from STDIN and:

  • if it matches /^y(es)$/i, puts true on the stack.
  • if it matches /^no?$/i, puts false on the stack.
  • Otherwise, it prints Invalid answer. Please enter 'yes' or 'no': and waits for a new answer.

debug

a a

Prints a and a new line to STDOUT, if logging level is set to debug or lower.

error

a a

Prints a and a new line to STDERR, if logging level is set to error or lower.

fappend

string1 string2

Appends string1 to the end of file string2.

fatal

a a

Prints a and a new line to STDERR, and exists the program with error code 100.

fread

string string

Reads the file string and puts its contents on the top of the stack as a string.

fwrite

string1 string2

Writes string1 to the file string2, erasing all its contents first.

gets

string

Reads a line from STDIN and places it on top of the stack as a string.

info

a a

Prints a and a new line to STDOUT, if logging level is set to info or lower.

newline

Prints a new line to STDOUT.

notice

a a

Prints a and a new line to STDOUT, if logging level is set to notice (default) or lower.

password

string

Reads a line from STDIN displaying * for each typed character, and places it on top of the stack as a string.

print

a a

Prints a to STDOUT.

print!

a

Prints a to STDOUT and removes a from the stack.

puts

a a

Prints a and a new line to STDOUT.

puts!

a

Prints a and a new line to STDOUT, removing a from the stack.

warning

a a

Prints a and a new line to STDERR, if logging level is set to warning or lower.

fs Module

atime

'sym float

Returns a timestamp corresponding to the time that file/directory 'sym was last accessed.

ctime

'sym float

Returns a timestamp corresponding to the time that file/directory 'sym was created.

fperms

'sym int

Returns the Unix permissions (expressed as a three-digit number) of file/directory 'sym.

fsize

'sym int

Returns the size in bytes of file/directory 'sym.

fstats

'sym dict

Returns a dictionary dict containing information on file/directory 'sym.

ftype

'sym string

Returns the type of file/directory 'sym ("file" or "dir").

hidden?

'sym bool

Returns true if file/directory 'sym is hidden, false otherwise.

mtime

'sym float

Returns a timestamp corresponding to the time that file/directory 'sym was last modified.

logic Module

>

a1 a2 bool

Returns true if a1 is greater than a2, false otherwise.

Note

Only comparisons among two numbers or two strings are supported.

>=

a1 a2 bool

Returns true if a1 is greater than or equal to a2, false otherwise.

Note

Only comparisons among two numbers or two strings are supported.

<

a1 a2 bool

Returns true if a1 is smaller than a2, false otherwise.

Note

Only comparisons among two numbers or two strings are supported.

<=

a1 a2 bool

Returns true if a1 is smaller than or equal to a2, false otherwise.

Note

Only comparisons among two numbers or two strings are supported.

==

a1 a2 bool

Returns true if a1 is equal to a2, false otherwise.

!=

a1 a2 bool

Returns true if a1 is not equal to a2, false otherwise.

and

bool1 bool2 bool3

Returns true if bool1 is equal to bool2, false otherwise.

boolean?

a bool

Returns true if a is a boolean, false otherwise.

dictionary?

a bool

Returns true if a is a dictionary, false otherwise.

float?

a bool

Returns true if a is a float, false otherwise.

or

bool1 bool2 bool3

Returns true if bool1 or bool2 is true, false otherwise.

integer?

a bool

Returns true if a is an integer, false otherwise.

not

bool1 bool2

Negates bool1.

number?

a bool

Returns true if a is a number, false otherwise.

quotation?

a bool

Returns true if a is a quotation, false otherwise.

xor

bool1 bool2 bool3

Returns true if bool1 and bool2 are different, false otherwise.

str Module

%

% interpolate

See interpolate.

=~

=~ regex

See regex.

capitalize

'sym string

Returns a copy of 'sym with the first character capitalized.

indent

'sym int string

Returns string containing 'sym indented with int spaces.

indexof

string1 string2 int

If string2 is contained in string1, returns the index of the first match or -1 if no match is found.

interpolate

string quot string

Substitutes the placeholders included in string with the values in quot.

Note

If quot contains symbols or quotations, they are not interpreted. To do so, call apply before interpolating.

join

quot 'sym string

Joins the elements of quot using separator 'sym, producing string.

length

'sym int

Returns the length of 'sym.

lowercase

'sym string

Returns a copy of 'sym converted to lowercase.

match

string1 string2 bool

Returns true if string2 matches string1, false otherwise.

Tip

string2 can be a sgregex.-compatible regular expression.

repeat

'sym int string

Returns string containing 'sym repeated int times.

replace

string1 string2 string3 string4

Returns a copy of string1 containing all occurrences of string2 replaced by string3

Tip

string2 can be a sgregex.-compatible regular expression.

regex

string1 string2 quot

Performs a search and/or a search-and-replace operation using pattern string2.

string2 can be one of the following patterns:

  • /search-regex/modifiers
  • s/search-regex/replacemenet/modifiers

quot is always a quotation containing:

  • One or more strings containing the first match and captures (if any), like for the search operator.
  • A string containing the resuling string after the search-and-replace operation.

Tip

  • search-regex can be a sgregex.-compatible regular expression.
  • modifiers are optionals can contain one or more of the following characters, in any order:
    • i: case-insensitive match.
    • m: multi-line match.
    • s: dot character includes newlines.

search

string1 string2 quot

Returns a quotation containing the first occurrence of string2 within string2. Note that:

  • The first element of quot is the matching substring.
  • Other elements (if any) contain captured substrings.

Tip

string2 can be a sgregex.-compatible regular expression.

split

'sym1 'sym2 quot

Splits 'sym1 using separator 'sym2 and returns the resulting strings within the quotation quot.

strip

'sym string

Returns string, which is set to 'sym with leading and trailing spaces removed.

titleize

'sym string

Returns a copy of 'sym in which the first character of each word is capitalized.

uppercase

'sym1 'sym2

Returns a copy of 'sym converted to uppercase.

sys Module

$

$string string get-env

See get-env.

$

$ get-env

See get-env.

!

!string string system

See system.

!

! system

See system.

&

&string string run

See run.

&

& run

See run.

.

string

Returns the full path to the current directory.

..

string

Returns the full path to the parent directory.

chmod

'sym int

Sets the permissions of file or directory 'sym to int. int is a three-digit representation of user, group and other permissions. See the Unix Permissions Calculator for examples and conversions.

cd

'sym

Change the current directory to {'sym.

cp

'sym1 'sym2

Copies the file or directory 'sym1 to 'sym2.

cpu

string

Returns the host CPU. It can be one of the following strings i386, alpha, powerpc, powerpc64, powerpc64el, sparc, amd64, mips, mipsel, arm, arm64.

env?

'sym bool

Returns true if environment variable 'sym exists, false otherwise.

dir?

'sym bool

Returns true if the specified path 'sym exists and is a directory.

dirname

'sym string

Returns the path of the directory containing path 'sym.

exists?

'sym bool

Returns true if the specified file or directory 'sym exists.

file?

'sym bool

Returns true if the specified path 'sym exists and is a file.

filename

'sym string

Returns the file name of path 'sym.

get-env

'sym string

Returns environment variable 'sym.

hardlink

'sym1 'sym2

Creates hardlink 'sym2 for file or directory 'sym1.

ls

'sym quot

Returns a quotation quot containing all children (files and directories) of the directory 'sym.

ls-r

'sym quot

Returns a quotation quot containing all children (files and directories) of the directory 'sym, recursively.

mkdir

'sym

Creates the specified directory 'sym.

mv

'sym1 'sym2

Moves the file or directory 'sym1 to 'sym2.

os

string

Returns the host operating system. It can be one of the following strings: windows, macosx, linux, netbsd, freebsd, openbsd, solaris, aix, standalone.

put-env

'sym1 'sym2 string

Sets environment variable 'sym2 to 'sym1.

rm

'sym

Deletes the specified file 'sym.

rmdir

'sym

Deletes the specified directory 'sym and all its subdirectories recursively.

run

'sym dict

Executes the external command 'sym in the current directory without displaying its output. Returns a dictionary containing the command output and return code (in keys output and code respectively).

sleep

int

Halts program execution for int milliseconds.

symlink

'sym1 'sym2

Creates symlink 'sym2 for file or directory 'sym1.

symlink?

'sym bool

Returns true if the specified path 'sym exists and is a symbolic link.

system

'sym

Executes the external command 'sym in the current directory.

unzip

'sym

Decompresses zip file 'sym.

which

'sym string

Returns the full path to the directory containing executable 'sym, or an empty string if the executable is not found in $PATH.

zip

'sym quot

Compresses files included in quotation quot into zip file 'sym.

num Module

+

num1 num2 num3

Sums num1 and num2.

-

num1 num2 num3

Subtracts num2 from num1.

-inf

num

Returns negative infinity.

*

num1 num2 num3

Multiplies num1 by num2.

/

num1 num2 num3

Divides num1 by num2.

even?

int bool

Returns true if int is even, false otherwise.

div

a1 a2 a3

Divides a1 by a2 (integer division).

inf

num

Returns infinity.

mod

a1 a2 a3

Returns the integer module of a1 divided by a2.

nan

nan

Returns NaN (not a number).

odd?

int bool

Returns true if int is odd, false otherwise.

pred

a1 a2

Returns the predecessor of a1.

random

a1 a2

Returns a random number a2 between 0 and a1-1.

succ

a1 a2

Returns the successor of a1.

sum

quot int

Returns the sum of all items of quot. quot is a quotation of integers.

time Module

now

float

Returns the current time as Unix timestamp with microseconds.

timestamp

int

Returns the current time as Unix timestamp.

timeinfo

int tinfo

Returns a timeinfo dictionary from timestamp int.

to-timestamp

tinfo int

Converts the timeinfo dictionary tinfo to the corresponding Unix timestamp.

datetime

int string

Returns an ISO 8601 string representing the combined date and time in UTC of timestamp int.

tformat

int string string

Formats timestamp int using string string.

Tip

For information on special characters in the format string, see the format nim method.

crypto Module

md5

'sym string

Returns the MD5 hash of 'sym.

sha1

'sym string

Returns the SHA1 hash of 'sym.

sha224

'sym string

Returns the SHA224 hash of 'sym.

sha256

'sym string

Returns the SHA256 hash of 'sym.

sha384

'sym string

Returns the SHA384 hash of 'sym.

sha512

'sym string

Returns the SHA512 hash of 'sym.

encode

'sym string

Base64-encodes 'sym.

encode

'sym string

Decodes the Base64-encoded string 'sym.

aes

'sym1 'sym2 string

Encrypts or decrypts 'sym1 using the Advanced Encryption Standard (AES), using 'sym2 as password.

math Module

acos

num1 num2

Calculates the arc cosine of num1 (in radians).

asin

num1 num2

Calculates the arc sine of num1 (in radians).

atan

num1 num2

Calculates the arc tangent of num1 (in radians).

ceil

num int

Returns the smallest integer int that is not smaller than num.

cos

num1 num2

Calculates the cosine of num1 (in radians).

cosh

num1 num2

Calculates the hyperbolic cosine of num1 (in radians).

d2r

num1 num2

Converts num1 from degrees to radians.

e

num

Returns the value of the e constant (Euler’s number).

floor

num int

Returns the largest integer int that is not greater than num.

ln

num1 num2

Calculates the natural logarithm of num1.

log10

num1 num2

Calculates the common logarithm of num1.

log2

num1 num2

Calculates the binary logarithm of num1.

pi

num

Returns the value of the π constant.

pow

num1 num2 num3

Computes num1 to power raised of num2.

r2d

num1 num2

Converts num1 from radians to degrees.

round

num1 int num2

Rounds num1 to the intth decimal place.

sin

num1 num2

Calculates the sine of num1 (in radians).

sinh

num1 num2

Calculates the hyperbolic sine of num1 (in radians).

sqrt

num1 num2

Returns square root of num1.

tan

num1 num2

Calculates the tangent of num1 (in radians).

tanh

num1 num2

Calculates the hyperbolic tangent of num1 (in radians).

tau

num

Returns the value of the τ constant (2π).

trunc

num1 num2

Truncates num to the decimal point.