\$\begingroup\$

1Lang

1Lang is a functional prefix language like LISP or Scheme but without parentheses that makes it a bit harder to read when all unnecessary white-space is removed. Parentheses can be removed since all functions and operators take a known number of parameters.

Braces are required to delimit function body and conditional consequence and alternate code blocks which can consist of a list of statements.

In LISP, Factorial might be defined like this:

(defun fact (x) (if (< x 2) 1 (* x (fact (- x 1))) ) )

in 1Lang this would be

@Fx{ ? < x 2 {1} {* x F -x1} }

which can be reduced to

@Fx{?<x2{1}{*xF-x1}}

1Lang currently supports no side-effects.

1Lang is written in bash so it currently shares some bash limitations such as integer range.

a-z are variables. Variable are either integers, strings, or lists.

NB: Lists are not fully implemented.

A-Z are functions

Integers are bash integers (up to -2^32 to 2^31-1 I think). Negative numbers can not be directly used. To enter a negative, subtract it from zero. eg. -5 would be entered as -0 5. This limitation is because 1Lang is a work in progress and negative numbers were not needed for this application. I am considering using ~ as a unary negative operator which would allow -5 to be input as ~5.

White-space is required to delineate integers. eg. +2 3

: means assign eg. :c34 to assign 34 to c +-*/% are binary integer operators eg. +12 34 &|^ are binary bit-wise operators ! is unary boolean not ~ is unary one's complement ? is a if-then-else function-like operator. eg. ?=x3{*xx}{0} is x=3 return x*x else 0 + is also a binary string concatenation operator eg. +99" bottles" * is also a string repetition operator eg. *5" hello" or *" hello"5 @ defines a function eg. @Fx{?<x1{1}{*xF-x1}}

Function parameter names may overload callers variables. All variables assigned within a function are local.

Printing is not necessary (although it could be useful) because like LISP every statement returns a value, and last value returned is printed.

eg. +2 3 prints 5

An unexpected behaviour of prefix notation without parentheses is that string concatenation can actually be easy to write. Say you want to concatenate "a" " quick" " brown" " fox" , one might write:

+++"a"" quick"" brown"" fox"

But a more readable and less error prone method is this:

+"a"+" quick"+" brown"" fox" (Note missing + between last terms)

or

+"a"+" quick"+" brown"+" fox"""

99 Bottles of beer code:

:b" of beer" :w" on the wall" :t"Take one down and pass it around, " :s"Go to the store and buy some more, " :c", " :n".

" @Bx{?=x0{+"No more bottles"b}{+x+" bottle"+?=x1{""}{"s"}b}} @Fx{?=x0{+B0+w+c+B0+n+s+B99+wn}{+Bx+w+c+Bx+n+t+B-x1+w+n+"

"F-x1}} F99

Function B returns "No more bottles" or "1 bottle" or " bottles" depending on x.

Function F returns normal verses or final verse. A normal verse is concatenated with following verse by recursively calling F with -x1. When x is 0, F returns final verse.

This generates (for F5 meaning start at 5 bottles of beer...):

> F5 5 bottles of beer on the wall, 5 bottles of beer. Take one down and pass it around, 4 bottles of beer on the wall. 4 bottles of beer on the wall, 4 bottles of beer. Take one down and pass it around, 3 bottles of beer on the wall. 3 bottles of beer on the wall, 3 bottles of beer. Take one down and pass it around, 2 bottles of beer on the wall. 2 bottles of beer on the wall, 2 bottles of beer. Take one down and pass it around, 1 bottle of beer on the wall. 1 bottle of beer on the wall, 1 bottle of beer. Take one down and pass it around, No more bottles of beer on the wall. No more bottles of beer on the wall, No more bottles of beer. Go to the store and buy some more, 99 bottles of beer on the wall. <End>

1Lang interpreter (written in bash) in under 500 lines.