Encyclopedia > Scheme programming language

  Article Content

Scheme programming language

The Scheme programming language is a functional programming language which is a dialect of Lisp. It was developed by Guy L. Steele[?] and Gerald Jay Sussman in the 1970s and introduced to the academic world via a series of papers now referred to as Sussman and Steele's Lambda Papers.

Scheme's philosophy is unashamedly minimalist. Its goal is not to pile feature upon feature, but to remove weaknesses and restrictions that make new features appear necessary. Therefore, Scheme provides as few primitive notions as possible, and let everything else be implemented on top of them. For example, the main mechanism for governing control flow is tail recursion.

Scheme was the first variety of Lisp to use lexical variable scoping (as opposed to dynamic variable scoping) exclusively. Like Lisp, Scheme supports garbage collection of unreferenced data. It uses lists as the primary data structure, but also has good support for arrays. Owing to the minimalism of the specification, there is no standard syntax for creating structures with named fields, or for doing object oriented progamming, but many individual implementations have such features.

Why the curious name? Well, it was originally called "Schemer", in the tradition of the languages Planner[?] and Conniver[?], but its authors used the ITS operating system[?] which didn't allow filenames longer than 6 characters.

Table of contents

Advantages of Scheme Scheme has very little syntax compared to many other programming languages. It has no operator precedence rules because there are essentially no operators -- as in Lisp, prefix notation is used for all function calls.

Thanks to its macro facilities, Scheme can be adapted to any problem domain. They can even be used to add support for object-oriented programming. Scheme provides a hygienic macro[?] system, which while not quite as powerful as Common Lisp's macros, is much safer and often easier to work with.

Scheme encourages functional programming. Pure functional programs need no global variables and don't have side-effects, and are therefore automatically thread-safe, automatically verifiable and have more of these nice properties. However, Scheme also supports variable assignment[?] for those who want it.

In Scheme, functions are first class citizens. This means they can be passed as arguments to another function or stored in a variable and manipulated. This allows higher order functions that can further abstract program logic. Functions can also be created anonymously.

Disadvantages of Scheme Unlike scripting languages such as Perl or Python, Scheme is not standardized beyond its core. Functions that exist in one Scheme implementation do not need to exist in another or may have a completely different name and/or interface. The Scheme Requests for Implementation (SRFI) process tries to remedy this.

Standards There are two standards that define the Scheme language: the official IEEE standard, and a de facto standard called the Revisedn-th Report on the Algorithmic Language Scheme, nearly always abbreviated RnRS, where n is the number of the revision. The latest RnRS version is R5RS, also available online (http://www.schemers.org/Documents/Standards/R5RS/).

Language Elements

Comments

Comments are preceded by a semi-colon (;) and continue for the rest of the line.

Variables

Variables are dynamically typed. Variables are defined by either a define or a let statement. Variables declared outside of any function are in "global" scope.

  (define var1 value)

  (let ((var2 value))
    ...)

Functions

Functions are first-class objects in Scheme. They can be assigned to variables. For example a function with two arguments arg1 and arg2 can be defined as

  (define fun
    (lambda (arg1 arg2)
       ...))

which can be abbreviated as follows:

  (define (fun arg1 arg2)
    ...)

Functions can be called with the following syntax:

  (fun value1 value2)

Note that the function being called is in the first position of the list while the rest of the list contain the arguments. The apply function will take the first argument and apply the rest of the arguments to the first argument, so the previous function call can also be written as

  (apply fun (list value1 value2))

Lists

Some consider the list Scheme's fundamental data type. A list can be constructed by consing elements together. The empty list is denoted as '(). As an example a list containing 1, 2, 3, 4 can be constructed as

  (cons 1 (cons 2 (cons 3 (cons 4 '()))))

which can be abbreviated as

  (list 1 2 3 4)

or as

  '(1 2 3 4)

Note the quote ('), this tells Scheme to not interpret the expression that follows the quote.

Data Types

Other common data types in Scheme besides functions and lists are: integer, rational, real, complex numbers, symbols, strings, ports. Most Scheme systems also offer association lists[?], hash tables, vectors, arrays and structures.

Most Scheme systems offer a full numerical tower[?] as well as exact[?] and inexact arithmetic[?].

True and false are represented by the symbols #t and #f. Actually only #f is really false when a Boolean type is required, everything else will be interpreted by Scheme as #t including the empty list. This is in contrast with LISP where the empty list is also interpreted as representing false.

Symbols can be defined in at least the following ways:

  'symbol
  (string->symbol "symbol")

Equality

Scheme has three different types of equality.

eqv?
Returns #t if two objects can be considered the same object.
eq?
Returns #t in mostly the same situations as eqv? but uses some finer distinctions.
equal?
Compares the content of data structures such as lists, vectors and strings to determine if they are the same.

Type dependent equivalence operations also exist in Scheme:

string=?
To compare two strings
char=?
To compare characters
=
To compare numbers

Control Structures

Conditional evaluation

  (cond (test1 expr1)
        (test2 expr2)
        ...
        (else exprn))

The first expression for which the test evaluates to true (anything other than #f counts as true) will be evaluated. If all test result in #f, the else clause is evaluated.

A variant of the cond clause is

  (cond ...
        (test => expr)
        ...)

In this case, expr should evaluate to a function that takes one argument. If test evaluates to true, the function is called with the return value of test.

Scheme also has

  (if then-expr else-expr)

but it is used much less because cond is both more general and has overall better readability.

Loops

Loops in Scheme usually take the form of tail recursion. A classical example is the factorial function, which can be defined non-tail-recursively:

  (define (factorial n)
    (cond ((= n 0) 1)
          (else (* n (factorial (- n 1))))))

  (factorial 5)
  ;; => 120

or a higher order function like map which applies a function to every element of a list, and can be defined non-tail-recursively:

  (define (map f lst)
    (cond ((null? lst) lst)
          (else (cons (f (car lst))
                      (map f (cdr lst))))))

  (map (lambda (x) (* x x)) '(1 2 3 4))
  ;;  => (1 4 9 16)

We can define both of these tail-recursively as follows. The named let statement and the do statement are syntactic sugar which simpify tail-recursive definitions. To use factorial and map again to illustrate both forms:

  (define (factorial n)
    (let loop ((fact 1)
               (n n))
      (cond ((= n 0) fact)
            (else (loop (* n fact) (- n 1))))))

  (factorial 5)
  ;; => 120

  (define (map f lst)
    (do ((lst lst (cdr lst))
         (res '() (cons (f (car lst)) res)))
        ((null? lst) (reverse res))))

  (map (lambda (x) (* x x)) '(1 2 3 4))
  ;; => (1 4 9 16)

Please note that in both cases, the tail-recursive version is preferrable due to its decreased use of space.

Input/output

Scheme has the concept of ports to read from or to write to. Scheme defines three default ports, accessible with the functions: current-input-port, current-output-port and current-error-port.

Examples Scheme code can be found in at least the following Wikipedia articles:

Implementations

  • Chez Scheme (http://www.scheme.com/), a proprietary freeware Scheme interpreter and commercial Scheme compiler for Microsoft Windows and several UNIX systems
  • Chicken is a Scheme-to-C compiler. It can be found here (http://www.call-with-current-continuation.org/chicken).
  • Guile is the GNU project's official extension language. The Scheme interpreter is packaged as a library to provide scripting to applications. It can be found here (http://www.gnu.org/software/guile/).
  • The PLT Scheme suite (http://www.plt-scheme.org/), a suite of Scheme programs for Windows, Mac, and Unix platforms including an interpreter (MzScheme), a graphical toolkit (MrEd), a pedagogically-oriented graphical editor (DrScheme), and various other components including Component object model and ODBC libraries.
  • Gauche is an R5RS Scheme implementation developed to be a handy script interpreter, which allows programmers and system administrators to write small to large scripts for their daily chores. Quick startup, built-in system interface, native multilingual support are some of my goals. Gauche is being developed by Shiro Kawai and is BSD licensed. It can be found at this site (http://www.shiro.dreamhost.com/scheme/gauche/index).
  • Bigloo (http://www-sop.inria.fr/mimosa/fp/Bigloo/) is a Scheme-to-C and Scheme-to-Java compiler which produces small, fast executables. It focuses on being a practical tool for real-world tasks, and there is a relatively large number of useful libraries available for it.
  • The Gimp has a scheme interpeter built into it for scripted image manipulation.
  • There are many, many, many more implementations listed in the schemers.org FAQ (http://www.schemers.org/Documents/FAQ/).

Additional Resources



All Wikipedia text is available under the terms of the GNU Free Documentation License

 
  Search Encyclopedia

Search over one million articles, find something about almost anything!
 
 
  
  Featured Article
Dennis Gabor

...     Contents Dennis Gabor Dennis Gabor (Gábor Dénes) (1900-1979) was a Hungarian physicist. He invented holography in 1947, for ...

 
 
 
This page was created in 37.8 ms