Penguin

GCBot is an IRC bot and a ProgrammingLanguage by PerryLorier made to see what happens if you give a bunch of programmers a shared programming environment, ie IRC.

The language is trivial. Everything is either a symbol, a function call, a list, a string or a number. The grammar is very simple:

<literal>::= "string"
           | 'string'
           | [0-9]\.[0-9]

<symbol> ::= [^,()\[\]]

<comma-expression> ::= <expression>
                     | <expression> ',' <comma-expression>

<symbol-or-literal> ::= <symbol>
                      | <literal>

<term> ::= '[' <comma-expression> ']'
         | <symbol-or-literal>

<expression> ::= <term>
               | <term> '(' <comma-expression ')'

Strings, lists and numbers can be called without arguments and evaluate to themselves. Everything is prefix notation, eg: to add four numbers, you need +(1,2,3,4).

Builtins:

+(arguments...)
Returns the sum of all of its arguments.
/(arguments...)
Returns the first argument divided by the second etc.
<(a,b)
Returns non-zero if a is less than b, 0 otherwise.
->string(arg)
Returns the string representation of arg. Beware, this does not evaluate arg.
apply(expression,arguments...)

Calls expression with arguments. Eg:

apply(+,[1,2,3])
at(list,expression)
Returns the item at position expression in the list.
catch(expression,exceptionhandler)
Calls expression, then calls exceptionhandler (passing it the exception) if one was raised.
decompose(functioncall)

Decomposes functioncall into a list with the function as head and the list of the arguments as tail. Eg:

decompose(+(1,2,3)) => [+,[1,2,3]]
define(name,vars,expression)

This works like lambda(), but also binds the resulting anonymous function to a name.

In effect it is the same as

set(define,lambda([name,vars,expression],set(name,lambda(vars,expression))))
head(list)
Returns the first item of list.
ifelse(cond,true-expr,false-expr)
This function evaluates cond to decide whether to evaluate true-expr or false-expr. Any result from evaluating cond other than 0 is considered true.
lambda(vars,expression)

Given a list of vars, replaces each variable with its corresponding positional argument everywhere in expression. Beware that the bindings of the lambda's variables can be cached, so if a function's return value may vary across calls with identical arguments, you are likely to end up with unexpected results.

As an example you could create an anonymous function that takes two arguments (a and b) and returns their sum:

lambda([a,b],+(a,b))

Then call it:

lambda([a,b],+(a,b))(1,2) => 3
now()
Returns the number of seconds since 1970-01-01. This function is not cachable; pay attention if you use it in lambda constructs.
say(channel,expression)
Evaluates expression and says the result in channel.
set(name,expression)
Binds expression to name.
syms()
Returns the list of all symbols that are currently defined in the symbol table.
tail(list)
Returns everything but the first item of list.
throw(string)
Throws an exception given by string.
undef(name)

Unbinds name, returning the previous expression that name was bound to, eg:

define(rename,[old,new],set(new,undef(old)))

Part of CategoryProgrammingLanguages, CategoryFunctionalProgrammingLanguages