A++

Appeared in:
2002
Influenced by:
Paradigm:
Typing discipline:
File extensions:
.app
Versions and implementations (Collapse all | Expand all):
Programming language

A++ (for “abstraction + reference + synthesis”) is an educational programming language based on lambda calculus.

A++ was created in 2002 by Georg P. Loczewski. It was meant to be an efficient learning tool; to solve practical problems one could use ARS++ interpreter which extends A++ with real-world concepts to a Scheme-like language.

ARS

Lambda calculus in its pure form is applicable only to functional programming, but it can be generalized to three main ARS principles which are present in all programming languages (in one form or another). These principles are abstraction (naming an entity), reference (referencing an abstraction using its symbolic name) and synthesis (combining several abstractions into new entities). These principles allow to follow several paradigms when programming in A++: functional, structured, object-oriented (using message passing) and logical (rule-based).

The syntax of A++ in extended Backus-Naur form follows:

expression = abstraction | reference | synthesis.
abstraction = "(define" variable expression ")" | "(lambda(" { variable } ")" expression { expression } ")".
reference = variable.
synthesis = "(" expression { expression } ")".
variable = symbol.

A++ contains a minimal set of primitives necessary for program interaction with the environment: numeric and logical constants, output functions etc. A small library extends this set to a more convenient one, which includes data structures, flow control routines, object-oriented tools etc. Extending the language even further brings us to ARS++.

Examples:

Hello, World!:

Example for versions A++ Interpreter

The program output looks as follows:

-->Hello, World!  
void
(print "Hello, World!")

Factorial:

Example for versions A++ Interpreter

The first expression loads init library which contains all main language constructs (loops, conditional jumps, comparisons etc.). All of them are not included in language core but instead are defined via a limited set of primitives; thus, for example, if construct is defined as follows::

(define true   (lambda (x y) 
               x))
(define false  (lambda (x y) 
               y))
(define if     (lambda (b t f) 
               (b t f)))

The second example defines factorial as a recursive function. Note that the language standard defines two kinds of numbers — regular integers with typical arithmetical operations on them and “nominal” zero, one, two, ..., ten with specific operations. Numbers of different types can’t be decoded one into another and are to be used separately; in this case we use regular integers.

The third expression is the main loop, and the fourth one just calls it. print command ends the output with line feed, so overall program output looks as follows:

-->0
-->! = 
-->1
-->1
-->! = 
-->1
-->2
-->! = 
-->2
-->3
-->! = 
-->6
-->4
-->! = 
-->24
-->5
-->! = 
-->120
...

Factorial values are calculated correctly up to 12!, after that they overflow and are printed as -1.

(load "app/init.app")

(define factorial (lambda(n)
  (if (equal n 0)
    1
    (* n (factorial (- n 1))))))

(define main
  (lambda(n)
    (while (not (equal n 17))
      (lambda()
        (print n)
        (print "! = ")
        (print (factorial n))
        (define n (+ n 1))))))

(main 0)

Fibonacci numbers:

Example for versions A++ Interpreter

This example uses tail recursion.

(load "app/init.app")

(define fibonacci (lambda(f1 f2 n)
  (if (equal n 0)
    f1
    (fibonacci f2 (+ f1 f2) (- n 1)))
))

(define main
  (lambda(n)
    (while (not (equal n 16))
      (lambda()
        (print (fibonacci 1 1 n))
        (define n (+ n 1))))))

(main 0)