Ans
Ans is an esoteric programming language invented on Saturday, April 19, 2008 by revcompgeek. Ans is a flexible language related to lisp, and is functional. Ans stands for Almost No Syntax.
Calling Functions
In Ans, all function names are either a single non-alphabetic character, or an upper-case letter optionally followed by any number of lower-case letters (e.g. Fibonacci). Non-alphabetic characters are not allowed in the names of user defined functions. No parentheses are needed as every function knows how many arguments it takes.
Variables
All variables in Ans start with an underscore(_), followed by any number of lower-case letters. Variables can either hold integers, lists or code blocks. Strings are represented as lists. In user defined functions, the _ variable is used as the return value and _a through _i are the parameters passed to the function. Command line arguments are also stored in _a through _i.
Numbers
Single digit numbers are the largest numbers that can be written into the language. You must use the math functions to produce higher numbers. For example, if you wanted to produce 42 in Ans you would have to add something like +*4*252 which is equivalent to (4*(2*5))+2 or simply *67.
Lists
Lists are simply arrays of values, which could be numbers, code blocks, or more lists. Lists are specified inside parenthesis (). Any code inside is executed and the results are placed into the list, unless the list is prefixed with a `, in which case it becomes a list of code blocks. Also, any strings in the program in the form "..." are converted into lists.
Built in functions
Name | Arguments | Description |
---|---|---|
Math Functions | ||
+ | number,number | add |
- | number,number | subtract |
* | number,number | multiply |
/ | number,number | divide |
^ | number,number | power function |
% | number,number | modulus or remainder |
~ | number | bitwise NOT |
& | number,number | bitwise AND |
| | number,number | bitwise OR |
Comparison Functions | ||
! | anything | logical NOT |
Or or O | anything,anything | logical OR |
And or A | anything,anything | logical AND |
< | number,number | less than |
> | number,number | greater than |
= | anything,anything | equal to |
I/O Functions | ||
$ | list or number | string print (ascii values) |
# | list or number | integer print |
N | print newline | |
' | string input | |
? | integer input | |
List Functions | ||
. | list,index | List Get |
, | list,index,value | List Set |
Slice or Sl | list,begin,end | List Slice |
Listappend or La | list,list | Append #2 to the end of #1 |
Listconcat or Lc | list,list | Concat #2 to the end of #1 |
List or L | Create empty list | |
Listsize or Ls | list | Size of list |
String Functions | ||
Format or Ft | list(string) | Format string: replace `var` with the value of var, `` with ` |
Escape or Es | list(string) | replace ~ with ~~ and " with ~" |
Replace or Rp | list(string),list(string),list(string) | replace all occurances of #2 with #3 in #1 |
Variable Functions | ||
Set or S | variable,value | Sets the variable to the value |
Exists or E | variable | Does the variable exist? |
Islist or Il | variable | Is the variable a list? |
Isnum or In | variable | Is the variable a number? |
Isblock or Ib | variable | Is the variable a block? |
Flow Control Functions | ||
If or I | value,code | execute code if value evaluates to true |
Ifelse or Ie | value,code,code | execute code if value evaluates to true else execute second code |
While or W | code,code | while code #1 evaluates to true, execute code #2 |
Do or D | code,code | execute #1, while code #2 evaluates to true, execute code #1 |
For or F | variable,number,code | move value of variable towards number by 1, executing code each time |
\ | break out of loop | |
@ | terminate program or function | |
Misc Functions | ||
` | code or variable | if variable, run the code inside, otherwise capture the code into a block |
B | anything,anything | evaluates both params in order |
Func or Fc | function name,number,code | defines a function that takes number params |
Load or L | list(string) | Loads a module into memory |
Explanations
While and Do loops
While and Do loops both need a code block passed as their first parameter because the expression will need to be evaluated multiple times. If and Ifelse do not need a block as their first parameter because it is evaluated once every time. See Code passing for more information.
For loop
The first parameter to a for loop must be a variable. This variable will be incremented or decremented after each run through the loop. The variable should already be initialized to the value that the loop should start with. The next parameter is the value that the for loop should loop to. This can be above or below the variable's value because the loop will adjust. The last parameter is the code that should be run. Example:
Set _num 0 For _num 10 `# _num
Code passing
Closures are used in many languages to pass a section of code to be used later. To do this in Ans you must prefix the block of code with a back quote(`). The code will be followed until all parameters are accounted for and then returned as a value. When that value is prefixed with a back quote, whether inside of a variable or not, the code will be executed. Note that the tree will be evaluated every time that it is used with a back quote and that it executes in the same scope that it was used in, so it can use the same variables. See 'Func' function for an example
'B' function
When creating functions, you may want to have multiple commands run at the top level. The solution is the 'B' function. There are only two parameters that are evaluated in order. Example:
If = _ 1 `B $"_ is 1" @
'Func' function
Using the 'Func' function is the way to define new functions. The first parameter is the capitalized function name. The second parameter is the number of parameters that the function takes. The last parameter is the code that is to be run when it is called. Example:
Func Fac 1 `BB If Or =_a 1 =_a 0 `B Set _ _a @ Set _ + 1 Fac - _a 1 @
See Examples section for an obfuscated version
'Listappend' and 'Listconcat'
'Listappend' and 'Listconcat' both do operations on the list in the first argument, but the difference is that 'La' can take a list or an integer as the second argument while 'Lc' takes only a list as the second argument. If both arguments are lists, then 'La' will put the second list inside the first as a nested list while 'Lc' will simply tack the second list to the end. Example:
_la is (1, 2, 3), _lb is (4, 5) La _la _lb returns (1, 2, 3, (4, 5)) Lc _la _lb returns (1, 2, 3, 4, 5)
Examples
Hello World
$"Hello, World!"
Cat
(assuming -1 is EOF)
S_v0S_eof-01While`!=_v_eof`BS_v'$_v
or a more obfuscated:
D`!=_-01`BS_'$_
Factorial
FuncFac1`BBIO=_a1=_a0`BS__a@S_+1Fac-_a1@
Called like this:
Fac 5
Quine
S_"S_q*2+98$`_q`S_`_q`$_q$_$_q$Ft_"S_q*2+98$"S_"$_q$_$_q$Ft_
Can anyone come up with a smaller one?
Bottles of Beer
S_b" bottles of beer" S_w_b S_wLc_w" on the wall." S_bLc_b"." S_t"Take one down, pass it around," S_*9+56S_n_ F_1 `BBB BB#_$_wN BB#_$_bN B$_tN BBB#-_1$_wNN $"No"$_wN $"No"$_bN $"Go to the store, buy some more,"N #_n$_wN
A smaller version based on this one:
FcU0`B$"on the wall"NFcZ1`BBB#_a$" bottle"I!=_a1`$"s"$" of beer "FcV1`BBBBBBBZ_aUZ_aN$"Take one down, pass it around"NZ-_a1US_*9+56F_1`V_
Interpreter
The interpreter is written in D, and uses the Tango library. It is likely very buggy but it has been tested with every example program listed on this page. See http://github.com/revcompgeek/ans/ (dead link) for the source and bug tracker. Please post issues on this website if you find anything wrong. NOTE: The interpreter does not currently have the list syntax implemented. I am currently working on a new implementation in Python that I'm hoping will be a little bit more powerful.