1 Welcome to PLT Scheme
2 Scheme Essentials
3 Built-In Datatypes
4 Expressions and Definitions
5 Programmer-Defined Datatypes
6 Modules
7 Input and Output
8 Contracts
9 Classes and Objects
10 Exceptions and Control
11 Iterations and Comprehensions
12 Regular-Expression Matching (Regexps)
13 Pattern Matching
14 Quasiquoting
15 Units (Higher-Order Modules)
16 Threads
17 Syntactic Extension (Macros)
18 Reflection and Dynamic Evaluation
19 Reader Extension
20 Security
21 Memory Management
22 Performance
23 Foreign-Function Interface (FFI)
24 Scripts
25 Graphical User Interfaces (GUIs)
26 More Tools
Index

contents

 index

← prev  up  next →

 

4.2 Identifiers and Binding

The context of an expression determines the meaning of identifiers that appear in the expression. In particular, starting a module with the language big, as in

  #module big

means that, within the module, the identifiers described in this guide start with the meaning described here: cons refers to the function that creates a pair, car refers to the function that extracts the first element of a pair, and so on.

Symbols introduces the syntax of identifiers.

Forms like define, lambda, and let associate a meaning with one or more identifiers; that is, they bind identifiers. The part of the program for which the binding applies is the scope of the binding. The set of bindings in effect for a given expression is the expression’s environment.

For example, in

  #module big

  

  (define f

    (lambda (x)

      (let ([y 5])

        (+ x y))))

  

  (f 10)

the define is a binding of f, the lambda has a binding for x, and the let has a binding for y. The scope of the binding for f is the entire module; the scope of the x binding is (let ([y 5]) (+ x y)); and the scope of the y binding is just (+ x y). The environment of (+ x y) includes bindings for y, x, and f, as well as everything in big.

A module-level define can bind only identifiers that are not already bound within the module. For example, (define cons 1) is a syntax error in a big module, since cons is provided by big. A local define or other binding forms, however, can give a new local binding for an identifier that already has a binding; such a binding shadows the existing binding.

Examples:

  (define f

    (lambda (append)

      (define cons (append "ugly" "confusing"))

      (let ([append 'this-was])

        (list append cons))))

  > (f list)

  (this-was ("ugly" "confusing"))

Even identifiers like define and lambda get their meanings from bindings, though they have transformer bindings (which means that they indicate syntactic forms) instead of value bindings. Since define has a transformer binding, the identifier define cannot be used by itself to get a value. However, the normal binding for define can be shadowed.

Examples:

  > define

  define: bad syntax in: define

  > (let ([define 5]) define)

  5

Shadowing standard bindings in this way is rarely a good idea, but the possibility is an inherent part of Scheme’s flexibility.

 

contents

 index

← prev  up  next →