Calico Scheme

From IPRE Wiki

Jump to: navigation, search

Here we will provide documentation for using Calico Scheme.

Calico Scheme is a new implementation of a Scheme-based language for Calico. It implements many core Scheme functions, but also adds some functionality to bring it into line with the other modern languages like Python and Ruby.

Contents

Example Code

  • Examples - these come with Calico in Calico/examples/scheme/

Scheme Extensions

  1. Exceptions - implements try/catch/finally
  2. Modules and namespaces - implements namespaces for imports and foreign objects
  3. DLLs - import libraries written for the CLR
  4. Interop - ways for Scheme to interop with other Calico languages

Exceptions

(raise <exp>)
(try <exp>...)
(try <exp>... (catch <sym> <exp>...))
(try <exp>... (finally <exp>...))
(try <exp>... (catch <sym> <exp>...) (finally <exp>...))

There are four main forms of try:

  1. try alone: has no effect---doesn't catch exceptions
  2. try with a catch-clause: if exception in try-body, catch-clause will catch and provide return value, otherwise body of try provides. If exception in catch-clause will simple raise it.
  3. try with a finally-clause: finally-clause will run if exception in try-body or not. If there is an exception in the finally, it will raise it.
  4. try with a catch-clause and finally-clause: if an exception in try-body, the catch-clause will run, followed by the finally-clause. If an exception is raised in the catch-clause too, then finally-clause will run, and then raise the catch-exception; if there is an exception raised in the

finally-clause, then it will raise.

The <sym> of the catch-clause will be bound to the expression raised.

Examples

==> 

> (try x)
(uncaught exception: "unbound variable x")
==> "(try x (catch e e))"
"unbound variable x"
==> "(try x (catch e (raise e)))"
(uncaught exception: "unbound variable x")
==> "(try x (finally 'hi))"
hi 
(uncaught exception: "unbound variable x")
==> "(try x (catch e 1 2 3 4 (finally 'hi))"
hi 
4

Modules

Modules provide an easy method for structuring hierarchies of libraries and code.

Import

(import <string-exp>)
(import <string-exp> '<symbol-exp>)

Examples

==> (import "my-file.ss")

my-file.ss is a Scheme program file, which itself could have imports.

==> (import "my-file.ss" 'my-stuff)

Loads the file, and puts it in the namespace "my-stuff" accessible through the lookup interface below.

Lookup

module.name
module.module.name
==> (import "my-file.ss" 'my-stuff)
==> my-stuff.x
5

Directory Listing

==> (dir)
(- * / + < = > and append apply caaaar caaadr caaar caadar caaddr caadr caar 
cadaar cadadr cadar caddar cadddr caddr cadr call/cc call-with-current-continuation 
car case cdaaar cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar cdddar 
cddddr cdddr cddr cdr cond cons current-time debug dir display env eq? equal? eval 
exit float for-each format get group help import int iter? length let let* letrec 
list list? list->vector list-head list-tail load map member memq newline not null? 
or pair? parse print printf procedure? property range record-case reverse set-car! 
set-cdr! sort sqrt string? string<? string->list string->symbol symbol symbol->string 
typeof using vector vector? vector->list vector-ref vector-set! vector-set!)
==> (dir my-stuff)
(x y z)

define-syntax

define-syntax is used to change the semantics of Scheme in a manner not possible with regular functions. For example, imagine that you wanted to time a particular function call. To time a function, you can do:

(let ((start (current-time)))
  (fact 5)
  (- (current-time) start))

If you tried to define a function time such that you could call it like:

(time (fact 5))

then, unfortunately, you would evaluate (fact 5) before you could do anything in the function time. You could call it like:

(time fact 5)

but that looks a bit strange. Perhaps a more natural way would be to just change the semantics of Scheme to allow (time (fact 5)). Scheme makes that easy with define-sytnax:

(define-syntax time 
  [(time ?exp) (let ((start (current-time)))
		 ?exp
		 (- (current-time) start))])

Now, you can call it like:

(time (fact 5))

and you get the correct answer.

define-syntax takes a list of two items: a template, and a response. If the template matches, then you evaluate the response. In this example, (time ?exp) matches, so the system will record the start time, evaluate the ?exp, and then return the time minus the start time.

Calico Scheme uses this simple, but powerful pattern matcher to implement define-case. Here is a more complex example: for.

(define-syntax for
  [(for ?exp times do . ?bodies)
   (for-repeat ?exp (lambda () . ?bodies))]
  [(for ?var in ?exp do . ?bodies)
   (for-iterate1 ?exp (lambda (?var) . ?bodies))]
  [(for ?var at (?i) in ?exp do . ?bodies)
   (for-iterate2 0 ?exp (lambda (?var ?i) . ?bodies))]
  [(for ?var at (?i ?j . ?rest) in ?exp do . ?bodies)
   (for ?var at (?i) in ?exp do
     (for ?var at (?j . ?rest) in ?var do . ?bodies))])

In this example, define-syntax creates a for function with 4 forms:

(for 4 times do (function ...))

(for x in '(1 2 3) do (function ...))

(for x at (0) in '(1 2 3) do (function ...))

(for x at (0 1 2) in (range 10) do (function ...))

DLLs

Use a DLL.

scheme> (using "DLLName")
scheme> (DLLName.Class arg1 arg2)

Interop

Use the define! to put a variable in the global Calico namespace.

scheme> (define! x 8)
python> x
8

Wrap a function for use by other Calico languages:

scheme> (func (lambda (a b) (+ a b)))

Combine for cross-language interoperation:

 scheme> (define fact (lambda (n) (if (= n 1) 1 (* n (fact (- n 1))))))
 scheme> (define! factorial (func fact))
 python> factorial(5)
 120

Be careful not to wrap the func around the part that is called recursively, or you will destroy the tail-call optimization.


Iterators

Strings, vectors, and lists all work with map and for-each.

==> (map display "123")
123(void void void)
==> (for-each (lambda (v) (printf "~a\n")) (vector 1 2 3))
1
2
3

Help/Doc System

When you define a variable, you can optionally add a doc-string:

==> (define x "This variable holds the sum" 0)
==> (define y 0)
==> (define function "This computes the polynomial..." (lambda (x) ...))

You can lookup the doc-string with:

==> (help 'x)
This variable holds the sum

Misc

get will lookup a symbol in the environment:

==> (get 'get)
#<procedure>

typeof will give you the .NET type of a value:

==> (typeof 1)
System.Int32
==> (typeof 238762372632732736)
Microsoft.Scripting.Math.BigInteger
==> (typeof 1/5)                
Rational

References

Calico

  1. CalicoDevelopment - plans and details for Calico development

For Developers

Personal tools