Core Language

This chapter presents the Bigloo basics. It presents the elements that compose the body of a module (see Modules).

Syntax

The syntax of Bigloo is that of Scheme (a parenthesis based one) with two exceptions: type information and multi-line comments. Type information is supplied when identifiers are introduced (via lambda, let, define, ...) and those identifiers holding type information are referred to as typed identifiers.

They are defined by the following grammar:

<ident>        ⇒ <r5rs-ident> | <typed-ident>
<typed-ident>  ⇒ <r5rs-ident>::<r5rs-ident>
<r5rs-ident>   ⇒ the standard Scheme identifiers
For details of the standard Scheme identifiers, see Lexical structure, token,,r5rs.info,R5RS.

Multi-lines comments (see http://srfi.schemers.org/srfi-30/) are defined as:

<ident>        ⇒ <r5rs-ident> | <typed-ident>
<comment>      ⇒ ;<all subsequent characters up to a line break>
       	       | #| <comment-text> (<comment> <comment-text>)* |#
<comment-text> ⇒ <character sequence not containing #| or |#>

Comments

Comments and whitespaces are the same as in Whitespace and comments,,r5rs.info,R5RS.

;;; The FACT procedure computes the factorial
;;; of a non-negative integer.
(define fact
  (lambda (n)
    (if (= n 0)
        1        ;; Base case: return 1
        (* n (fact (- n 1))))))
In addition, Bigloo supports s-expressions comments. These are introduced with the #; syntax:

;;; The FACT procedure computes the factorial
;;; of a non-negative integer.
(define fact
  (lambda (n)
    #;(if (&lt; n 2) 1 (* #;n (fact (- n 1))))
    (if (= n 0)
        1
        (* n (fact (- n 1))))))

Expressions

Bigloo expressions are the same as in Expressions, , r5rs.info, R5RS. Bigloo has more syntactic keywords than Scheme. The Bigloo syntactic keywords are:

=>                      do                    or
and                     else                  quasiquote
begin                   if                    quote
case                    lambda                set!
cond                    let                   unquote
unquote-splicing        define                let*
delay                   letrec                module
labels                  try                   define-struct
unwind-protect          bind-exit             define-inline
regular-grammar         lalr-grammar          regular-search
define-expander         define-macro          match-case
match-lambda            pragma                failure
assert                  define-generic        define-method
instantiate             duplicate             with-access
widen!                  shrink!               multiple-value-bind
let-syntax              letrec-syntax         define-syntax
cond-expand             receive               args-parse
define-record-type      and-let*              letrec*
All other non atomic Bigloo forms are evaluated as functioncalls or macro class.

<variable>syntax

quote datumsyntax

'datumsyntax

<constant>syntax

(define x 28)                          
x                                       28
(quote a)                               A
(quote #(a b c))                        #(A B C)
(quote (+ 1 2))                         (+ 1 2)
'a                                      A
'#(a b c)                               #(A B C)
'()                                     ()
'(+ 1 2)                                (+ 1 2)
'(quote a)                              (QUOTE A)
'"abc"                                  "abc"
"abc"                                   "abc"
'145932                                 145932
145932                                  145932
'#t                                     t                                      #t
.keep

operator operand ...syntax

(+ 3 4)                                 7
((if #f + *) 3 4)                       12
((lambda (x) (+ 1 x)) 5)                6
.keep

lambda formals bodysyntax

(lambda (x) (+ x x))                    a procedure
((lambda (x) (+ x x)) 4)                8

(define reverse-subtract
  (lambda (x y) (- y x)))
(reverse-subtract 7 10)                 3

(define add4
  (let ((x 4))
    (lambda (y) (+ x y))))
(add4 6)                                10

((lambda x x) 3 4 5 6)                  (3 4 5 6)
((lambda (x y . z) z)
 3 4 5 6)                               (5 6)
.keep

if test consequent [alternate]syntax

(if (> 3 2) 'yes 'no)                   yes
(if (> 2 3) 'yes 'no)                   no
(if (> 3 2)
    (- 3 2)
    (+ 3 2))                            1
.keep

set! variable expressionsyntax

(define x 2)
(+ x 1)                                 3
(set! x 4)                              unspecified
(+ x 1)                                 5
.keep

cond clause clause ...library syntax

Bigloo considers else as a keyword. It thus ignores clauses following an else-clause.

(cond ((> 3 2) 'greater)
      ((< 3 2) 'less))                  greater

(cond ((> 3 3) 'greater)
      ((< 3 3) 'less)
      (else 'equal))                    equal

(cond ((assv 'b '((a 1) (b 2))) => cadr)
      (else #f))                        2
.keep

case key clause clause ...library syntax

(case (* 2 3)
  ((2 3 5 7) 'prime)
  ((1 4 6 8 9) 'composite))             composite
(case (car '(c d))
  ((a) 'a)
  ((b) 'b))                             unspecified
(case (car '(c d))
  ((a e i o u) 'vowel)
  ((w y) 'semivowel)
  (else 'consonant))                    consonant
.keep

and test ...library syntax

(and (= 2 2) (> 2 1))                   #t
(and (= 2 2) (< 2 1))                   #f
(and 1 2 'c '(f g))                     (f g)
(and)                                   #t
.keep

and-let* test ...bigloo syntax

(and-let* ((x 1) (y 2)) (cons x y))     (1 . 2)
(and-let* ((x 1) (z #f)) x)             #f

(and-let* ((my-list (compute-list)) ((not (null? my-list))))
          (do-something my-list))

(define (look-up key alist)
  (and-let* ((x (assq key alist))) (cdr x)))

(or (and-let* ((c (read-char))
               ((not (eof-object? c))))
              (string-set! some-str i c)  
              (set! i (+ 1 i)))
.keep

or test ...library syntax

(or (= 2 2) (> 2 1))                    #t
(or (= 2 2) (< 2 1))                    #t
(or #f #f #f)                           #f
(or (memq 'b '(a b c)) 
    (/ 3 0))                            (b c)
.keep

let [name] (binding ...) bodylibrary syntax

(let ((x 2) (y 3))
  (* x y))                              6

(let ((x 2) (y 3))
  (let ((x 7)
        (z (+ x y)))
    (* z x)))                           35

(let loop ((l '(1 2 3)))
   (if (null? l)
       '()
       (cons (+ 1 (car l)) 
             (loop (cdr l)))))          (2 3 4)
If a binding is a symbol, then, it introduces a variable bound to the #unspecified value.

(let (x)
   x)                                  #unspecified
Bigloo's named let differs from R5Rs named let because name is bound in binding. That is,

(let ((l 'a-symbol))
  (let l ((x l))
     x))                                #<procedure>
while R5Rs states that,

(let ((l 'a-symbol))
  (let l ((x l))
     x))                                a-symbol
.keep

let* (binding ...) bodylibrary syntax

(let ((x 2) (y 3))
  (let* ((x 7)
         (z (+ x y)))
    (* z x)))                           70
.keep

letrec (binding ...) bodylibrary syntax

(letrec ((even?
          (lambda (n)
            (if (zero? n)
                #t
                (odd? (- n 1)))))
         (odd?
          (lambda (n)
            (if (zero? n)
                #f
                (even? (- n 1))))))
  (even? 88))   
                                        #t
.keep

letrec* (binding ...) bodybigloo syntax

Each binding has the form

((&lt;variable1&gt; &lt;init1&gt;) ...)
Each <init> is an expression.Any variable must not appear more than once in the <variable>s.

The <variable>s are bound to fresh locations, each <variable> is assigned in left-to-right order to the result of evaluating the corresponding <init>, the <body> is evaluated in the resulting environment, and the values of the last expression in <body> are returned. Despite the left-to-right evaluation and assignment order, each binding of a <variable> has the entire letrec* expression as its region, making it possible to define mutually recursive procedures.

Examples:

(letrec* ((x 1)
          (f (lambda (y) (+ x y))))
   (f 3))
                                        4
(letrec* ((p (lambda (x)
                (+ 1 (q (- x 1)))))
          (q (lambda (y)
                (if (zero? y)
                    0
                    (+ 1 (p (- y 1))))))
          (x (p 5))
          (y x))
  y)
                                        5
It must be possible to evaluate each <init> without assigning or referring to the value of the corresponding <variable> or the <variable> of any of the bindings that follow it in <bindings>. Another restriction is that the continuation of each <init> should not be invoked more than once.

.keep

labels ((name (arg ...) body) ...) bodybigloo syntax

The syntax is similar to the Common Lisp one [Steele90], where created bindings are immutable.

(labels ((loop (f l acc)
               (if (null? l) 
                   (reverse! acc) 
                   (loop f (cdr l) (cons (f (car l)) acc)))))
   (loop (lambda (x) (+ 1 x)) (list 1 2 3) '()))
    (2 3 4)
.keep

begin expression expression ...library syntax

(define x 0)

(begin (set! x 5)
       (+ x 1))                         6

(begin (display "4 plus 1 equals ")
       (display (+ 4 1)))               unspecified
                                        4 plus 1 equals 5
.keep

do ((variable init step) ...) (test expression ...) bodylibrary syntax

(do ((vec (make-vector 5))
     (i 0 (+ i 1)))
    ((= i 5) vec)
  (vector-set! vec i i))                #(0 1 2 3 4)

(let ((x '(1 3 5 7 9)))
  (do ((x x (cdr x))
       (sum 0 (+ sum (car x))))
      ((null? x) sum)))                 25
.keep

delay expressionlibrary syntax

.keep

quasiquote templatesyntax

` templatesyntax

`(list ,(+ 1 2) 4)                      (list 3 4)
(let ((name 'a)) `(list ,name ',name))           
           (list a (quote a))
`(a ,(+ 1 2) ,@(map abs '(4 -5 6)) b)           
           (a 3 4 5 6 b)
`((__samp__foo ,(- 10 3)) ,@(cdr '(c)) . ,(car '(cons)))           
           ((foo 7) . cons)
`#(10 5 ,(sqrt 4) ,@(map sqrt '(16 9)) 8)           
           #(10 5 2 4 3 8)
`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)           
           (a `(b ,(+ 1 2) ,(foo 4 d) e) f)
(let ((name1 'x)
      (name2 'y))
  `(a `(b ,,name1 ,',name2 d) e))           
           (a `(b ,x ,'y d) e)
(quasiquote (list (unquote (+ 1 2)) 4))           
           (list 3 4)
'(quasiquote (list (unquote (+ 1 2)) 4))           
           `(list ,(+ 1 2) 4)
     i.e., (quasiquote (list (unquote (+ 1 2)) 4))
.keep

Definitions

Global bindings are introduced by the define form:

define variable expressionsyntax

define (variable arg ...) bodysyntax

(define add3
  (lambda (x) (+ x 3)))
(add3 3)                                6
(define first car)
(first '(1 2))                          1
.keep
r5rs.info, for more details. The Bigloo module language (See Module Declaration) enables exports and imports of global definitions.