On this page:
1.1 Definitions
=
1.2 Patterns and Matching
1.2.1 Pattern Matching
match
match*
1.3 Procedures
λ
1.4 Local Binding
let
1.5 Conditional Forms
if
cond
when
unless
1.6 Defining New Types
1.6.1 Algebraic Data Types
define-type
1.6.2 Wrapper Types
define-wrapper-type
1.6.3 Object Types
define-object-type
8.12

1 Core Syntactic Forms🔗ℹ

Elle differs from other Lisps in that it uses several delimiters, each having a different meaning. Elle recognizes parentheses (), brackets [], and braces {} as delimiters. A syntactic form may assign arbitrary meaning to the delimiters, but each has an independent meaning, when used as part of a standalone expression:

1.1 Definitions🔗ℹ

Unlike most (if not all) Lisps, Elle does not have a parenthesized, prefix form for value definitions. Instead, Elle has an unparenthesized, infix form, similar to some languages outside the Lisp family.

syntax

val-pat = expr

proc-header  expr
 
proc-header = (name args)
  | (proc-header args)
     
args = mandatory-args maybe-optional-args maybe-rest
     
mandatory-args = val-pat ... #:<kw> val-pat ... ...
     
maybe-optional-args = 
  | [val-pat ... #:<kw> val-pat ... ...]
     
maybe-rest = 
  | id ...
The first form binds the identifiers in the val-pat to the corresponding values from the destructured result from the expr.

The second form binds name to a procedure formed by unfolding the proc-header into a “curried λ”.

syntax

=

Used as an infix token to separate binding patterns from expressions in a definition form.

syntax

Used as an infix token in certain forms.

1.2 Patterns and Matching🔗ℹ

syntax

literal

id
{derived stx ...}
 
  derived : match-expander?
There is currently not a good story on patterns and their grammar.

syntax

(values pat ...)

pat
The first form matches a multiple-values return and destructures the values using the provided pats.

The second form is equivalent to (values pat).

1.2.1 Pattern Matching🔗ℹ

syntax

{match expr match-clause ...+}

 
match-clause = pat  result-expr
  | pat #:guarded [guard-clause ...+]
     
guard-clause = test-expr  result-expr
 
  test-expr : boolean?

syntax

{match* [expr ...+] match*-clause ...+}

 
match*-clause = [pat ...+]  result-expr
  | [pat ...+] #:guarded [guard-clause ...+]

1.3 Procedures🔗ℹ

syntax

{λ args  expr}

{λ args  λ args  ... ... ... expr}
The first form creates an anonymous procedure that is closed over its lexical environment.

The second form is syntactic sugar for nested λ forms, yielding a, “curried λ”.

syntax

(proc-expr arg ... maybe-rest)

 
arg = expr
  | #:<kw> expr
     
maybe-rest = 
  | rest-expr ...
 
  proc-expr : procedure?
  rest-expr : list?
As a standalone expression, a parenthesized form always refers to procedure application.

1.4 Local Binding🔗ℹ

syntax

{let definition ...+ #:in expr}

Performs the given definitions and makes available their bindings in the body of expr, which is evaluated in tail position, with respect to the let form.

1.5 Conditional Forms🔗ℹ

syntax

{if test-expr then-expr else-expr}

 
  test-expr : boolean?
Evaluates test-expr; if the result is #true, the then-expr is evaluated; if the result is #false, the else-expr is evaluated. Note that, unlike Scheme and Racket, Elle’s if requires that the test expression be a boolean value.

syntax

{cond cond-clause ...+ maybe-else}

 
cond-clause = test-expr  then-expr
     
maybe-else = 
  | #:else else-expr
 
  test-expr : boolean?
Evaluates each test-expr, in order; at the first to return #true, the associated then-expr is evaluated in tail position, with respect to the cond form. If no test-expr is #true, then the else-expr, if present, is evaluated in tail position, with respect to the cond form. If no test-expr is #true, and there is no else-expr, an exception will be thrown.

syntax

{when test-expr result-expr}

 
  test-expr : boolean?
Evaluates test-expr, and if the value is #true, then result-expr is evaluated in tail position, with respect to the when form. If test-expr is #false, the result of the when form is an zero-value return.

syntax

{unless test-expr result-expr}

 
  test-expr : boolean?
Equivalent to {when (not test-expr) result-expr}.

1.6 Defining New Types🔗ℹ

1.6.1 Algebraic Data Types🔗ℹ

syntax

{define-type name type-case ...+ type-option ...}

 
type-case = enum-id
  | (tuple-id field-id ...)
  | (record-id #:field-kw ...)
     
type-option = #:inspector inspector
  | #:property property expr
 
  inspector : inspector?
  property : struct-type-property?
Defines a new algebraic data type and binds the following names:

1.6.2 Wrapper Types🔗ℹ

syntax

{define-wrapper-type name type-option ...}

 
type-option = #:inspector inspector
     
code:line = #:property
  | property
  | expr
 
  inspector : inspector?
  property : struct-type-property?
1.6.3 Object Types🔗ℹ

syntax

{define-object-type name (#:field-kw ...) type-option}

 
type-option = #:inspector inspector
  | #:property property expr
 
  inspector : inspector?
  property : struct-type-property?