compile/define

Symbol: compile/define

define is the Scheme-layer spelling. Koskari code binds a value with var and a function with def; see Bindings and refs.

Syntax:

  • Function: (define [NAME FORMALS ...] BODY ...) or (define (NAME FORMALS ...) BODY ...)

  • Typed function: (define [(NAME :: TYPE) FORMALS ...] BODY ...) or (define [(NAME type: TYPE) FORMALS ...] BODY ...), the return type bundled with the name as a typed formal bundles, (n :: int)

  • Declaration only: (define NAME), (define NAME :: TYPE), or (define NAME type: TYPE)

  • Declare and store: (define NAME VALUE), (define NAME :: TYPE VALUE), or (define NAME type: TYPE VALUE)

The form of the first operand selects the arm. A pair, [ ] or ( ), is a function head: its first element is the name and the rest are the formals, in every shape lambda accepts. A symbol is a value binding.

The name takes the first slot of the head, so its return type bundles with it as a typed formal does, [(f :: int) x], never inline. An inline [f :: int x] is rejected as a bare :: in the formals, and [f type: 1 x] is a keyword formal named type defaulting to 1.

In block form the function head is followed by a colon and an indented body:

define [NAME FORMALS ...]:
  BODY ...

Use-case: Scheme-style definitions. (define [f x] body) reads as Scheme’s (define (f x) body); (define x v) is (var x v).

Behaviour: A function head declares NAME in the current scope and stores (function NAME FORMALS ... BODY ...) into it, as (def NAME [FORMALS ...] BODY ...) does. The function needs at least one body form. A recursive call to NAME inside the body reads the binding in the enclosing scope.

A symbol in the name position behaves as var: NAME is declared in the current scope, VALUE, when present, is evaluated and stored, and without a value the slot is left empty, so reading it before a store raises. The form’s value is None.

A pair in the name position whose first element is not a symbol, and the pre-Scheme shorthand (define NAME [FORMALS ...] BODY ...), match no rule and raise SyntaxMatchError; move the name inside the pair.

Pitfall: (define [a b] x) is not an unpacking. It defines a function named a with one formal b whose body is x, and binds nothing named b:

(define [a b] #(1 2))
(a "ignored")          ;; (1, 2)

Unpack with var over a pattern, or with define-values:

(var [a b] #(1 2))
(define-values [a b] #(1 2))

A decorator line above a function define decorates the function and binds the result; see decorate.

Examples:

;; Declaration only; assign later with set!
(define x)
(set! x 42)

;; Typed declaration and value
(define port :: int)
(define host type: str "localhost")

;; Declare and store
(define y 99)

;; Function, with ( ) or [ ] around the head
(define (square x) (* x x))
(define [double x] (* x 2))
(define [fact n]
  (cond [(== n 0) 1]
        [else: (* n (fact (- n 1)))]))

;; Typed function
(define [(half :: float) x] (/ x 2))

In block form, with a decorator:

define [twice f]:
  (lambda [x] (* 2 (f x)))

@twice
define [inc x]:
  (+ x 1)

(inc 4)    ;; 10

See also: compile/define-global, compile/var, def, compile/function, compile/define-values.