On this page:
1.1 hash-lambda
hash-lambda
hash-lambda/  match
1.2 args-hashes and apply/  hash
apply/  hash
args-hash?
make-args-hash
args-hash-first
args-hash-rest
args-hash-cons
args-hash-cons*
args-hash-append
args-hash->args-list
1.3 misc.
hash-has-key?/  c
match?/  c
make-hash-lambda-contract
7.7

1 hash-lambda

These forms and functions allow you to create a "rest argument" that includes keyword arguments. see Declaring a Rest Argument
Instead of storing the arguments in a list, hash-lambda stores them in a hash table, where you can use (hash-ref args-hash 0), etc. to access by-position arguments, and (hash-ref args-hash '#:<kw>), etc. to access keyword arguments, or you can use hash-lambda/match and use match patterns for the arguments or use apply/hash to apply an args-hash to a function.

Examples:
> (define my+
    (hash-lambda/match
     [(hash-table [0 a] [1 b])
      (+ a b)]))
> (my+ 1 2)

3

> (define/contract kinetic-energy (#:mass number? #:velocity number? . -> . number?)
    (hash-lambda/match
     [(hash-table ['#:mass mass] ['#:velocity velocity])
      (* 1/2 mass (sqr velocity))]))
> (kinetic-energy #:mass 2 #:velocity 1)

1

1.1 hash-lambda

syntax

(hash-lambda args-hash-id body ...+)

(hash-lambda [args-hash-id args-hash-contract] body ...+)
like (lambda args-list-id body ...+), except that it takes all keywords, and it puts its arguments into a hash table instead of a list.

In the hash table, the by-position arguments have their position as the key, and the keyword arguments have the (quoted) keyword as the key.

The second form is like the first form except that it applies args-hash-contract to args-hash-id.

Examples:
> (define return-args-hash
    (hash-lambda args-hash
                 args-hash))
> (return-args-hash "0" "1" #:keyword "keyword-argument" "2")

'#hash((1 . "1") (0 . "0") (2 . "2") (#:keyword . "keyword-argument"))

> (define my+
    (hash-lambda args-hash
                 (+ (hash-ref args-hash 0)
                    (hash-ref args-hash 1))))
> (my+ 1 2)

3

> (define/contract kinetic-energy (#:mass number? #:velocity number? . -> . number?)
    (hash-lambda args-hash
                 (let ([mass     (hash-ref args-hash '#:mass)]
                       [velocity (hash-ref args-hash '#:velocity)])
                   (* 1/2 mass (sqr velocity)))))
> (kinetic-energy #:mass 2 #:velocity 1)

1

syntax

(hash-lambda/match match-clause ...)

 
match-clause = [pat body ...+]
  | [pat (=> id) body ...+]
  | [pat #:when cond-expr body ...+]
allows you to use pattern matching instead of putting lots of hash-refs everywhere, and allows the procedure to do different things based on which of the pats match, whether the the #:when test passes, and whether (=> id) or (failure-cont) is used.

Equivalent to:
(hash-lambda args-hash
  (match args-hash
    match-clause ...))

Examples:
> (define my+
    (hash-lambda/match
     [(hash-table [0 a] [1 b])
      (+ a b)]))
> (my+ 1 2)

3

> (define/contract kinetic-energy (#:mass number? #:velocity number? . -> . number?)
    (hash-lambda/match
     [(hash-table ['#:mass mass] ['#:velocity velocity])
      (* 1/2 mass (sqr velocity))]))
> (kinetic-energy #:mass 2 #:velocity 1)

1

1.2 args-hashes and apply/hash

procedure

(apply/hash proc args-hash #:<kw> kw-arg ...)  any

  proc : procedure?
  args-hash : args-hash?
  kw-arg : any/c
like apply, except that it takes an args-hash? instead of a list, and it doesn’t take by-position arguments before the last argument like apply does.

Examples:
> (apply/hash list (hash 0 "0" 1 "1"))

'("0" "1")

> (apply/hash list (hash 1 "1" 0 "0"))

'("0" "1")

> (define (kinetic-energy #:mass m #:velocity v)
    (* 1/2 m (sqr v)))
> (apply/hash kinetic-energy (hash '#:mass 2 '#:velocity 1))

1

procedure

(args-hash? x)  boolean?

  x : any/c
determines whether x is a valid args-hash for use in apply/hash

procedure

(make-args-hash stuff    
  ...    
  #:<kw> more-stuff ...)  args-hash?
  stuff : any/c
  more-stuff : any/c
equivalent to (hash-lambda args-hash args-hash).

Example:
> (make-args-hash 1 2 3 #:kw-1 'kw-arg-1 #:kw-2 'kw-arg-2)

'#hash((1 . 2) (0 . 1) (#:kw-1 . kw-arg-1) (2 . 3) (#:kw-2 . kw-arg-2))

make-args-hash is also bound as a match expander to be used with match.

Example:
> (match (make-args-hash 1 2 3 #:kw-1 'kw-arg-1 #:kw-2 'kw-arg-2)
    [(make-args-hash one two three #:kw-1 kw-arg-one #:kw-2 kw-arg-two)
     (list one two three kw-arg-one kw-arg-two)])

'(1 2 3 kw-arg-1 kw-arg-2)

procedure

(args-hash-first args-hash)  any/c

  args-hash : (and/c args-hash? (hash-has-key?/c 0))
equivalent to (hash-ref args-hash 0)

procedure

(args-hash-rest args-hash)  args-hash?

  args-hash : (and/c args-hash? (hash-has-key?/c 0))
returns an args-hash without the 0 key (with (hash-remove args-hash 0)) and with all of the number-keys reduced by one.

Example:
> (args-hash-rest (hash 0 "0" 1 "1" 2 "2" '#:kw "kw-arg"))

'#hash((1 . "2") (0 . "1") (#:kw . "kw-arg"))

procedure

(args-hash-cons val args-hash)  args-hash?

  val : any/c
  args-hash : args-hash?
returns args-hash with the number keys increased by one and with val added with a key of 0.

Example:
> (args-hash-cons "thing" (hash 0 "0" 1 "1" 2 "2" '#:kw "kw-arg"))

'#hash((1 . "0") (3 . "2") (0 . "thing") (2 . "1") (#:kw . "kw-arg"))

args-hash-cons is also bound as a match expander to be used with match.

Example:
> (match (args-hash-cons "thing" (hash 0 "0" 1 "1" 2 "2" '#:kw "kw-arg"))
    [(args-hash-cons val hash)
     (cons val hash)])

'("thing"       . #hash((1 . "1") (0 . "0") (2 . "2") (#:kw . "kw-arg")))

procedure

(args-hash-cons* val ... args-hash)  args-hash?

  val : any/c
  args-hash : args-hash?
returns args-hash with the vals all args-hash-consed onto it, analogous to list*.

Example:
> (args-hash-cons* "thing" "other-thing" (hash 0 "0" 1 "1" 2 "2" '#:kw "kw-arg"))

'#hash((1 . "other-thing") (3 . "1") (0 . "thing") (2 . "0") (#:kw . "kw-arg") (4 . "2"))

args-hash-cons* is also bound as a match expander to be used with match.

Example:
> (match (args-hash-cons* "thing" "other-thing" (hash 0 "0" 1 "1" 2 "2" '#:kw "kw-arg"))
    [(args-hash-cons* val other-val hash)
     (list val other-val hash)])

'("thing" "other-thing"       #hash((1 . "1") (0 . "0") (2 . "2") (#:kw . "kw-arg")))

procedure

(args-hash-append args-hash ...)  args-hash?

  args-hash : args-hash?
appends the args-hashes together, with the number keys of the later args-hashes increased.

Example:
> (args-hash-append (hash 0 "0" 1 "1" 2 "2" '#:kw "kw-arg")
                    (hash 0 "other-0" 1 "other-1" 2 "other-2" '#:other-kw "other-kw-arg"))

'#hash((1 . "1") (5 . "other-2") (3 . "other-0") (0 . "0") (#:other-kw . "other-kw-arg") (2 . "2") (#:kw . "kw-arg") (4 . "other-1"))

procedure

(args-hash->args-list args-hash)  (or/c list? #f)

  args-hash : any/c
equivalent to (apply/hash list args-hash), except that if args-hash either isn’t an args-hash or contains any keywords, then it returns #false instead of raising an exeption.

1.3 misc.

procedure

(hash-has-key?/c key)  flat-contract?

  key : any/c
makes a contract that accepts hash tables that have the given key

Examples:
> (define return-first-arg
    (hash-lambda [args-hash (hash-has-key?/c 0)]
                 (hash-ref args-hash 0)))
> (return-first-arg "first arg" "other-arg" #:kw "other-arg")

"first arg"

> (return-first-arg)

return-first-arg: contract violation

  expected: (hash-has-key?/c (quote 0))

  given: '#hash()

  in: the args-hash of

      (make-hash-lambda-contract

       (hash-has-key?/c '0)

       any)

  contract from: (definition return-first-arg)

  blaming: top-level

   (assuming the contract is correct)

  at: eval:1.0

syntax

(match?/c pat)

(match?/c pat #:when pred)
creates a flat-contract that accepts values that match the given pattern.

Examples:
> (define return-first-arg
    (hash-lambda [args-hash (match?/c (hash-table [0 0-val] [keys vals] ...))]
                 (hash-ref args-hash 0)))
> (return-first-arg "first arg" "other-arg" #:kw "other-arg")

"first arg"

> (return-first-arg)

return-first-arg: contract violation

  expected: (match?/c (hash-table (0 0-val) (keys vals)

...))

  given: '#hash()

  in: the args-hash of

      (make-hash-lambda-contract

       (match?/c

        (hash-table (0 0-val) (keys vals) ...))

       any)

  contract from: (definition return-first-arg)

  blaming: top-level

   (assuming the contract is correct)

  at: eval:1.0

procedure

(make-hash-lambda-contract args-hash-contract    
  [range-contract])  contract?
  args-hash-contract : (or/c contract? 'any)
  range-contract : (or/c contract? 'any) = 'any
creats a contract for a function that takes an args-hash that matches args-hash-contract, and produces something that matches range-contract.

Examples:
> (define/contract kinetic-energy
    (make-hash-lambda-contract
     (match?/c (hash-table ['#:mass (? number? m)] ['#:velocity (? number? v)]))
     number?)
    (hash-lambda/match [(hash-table ['#:mass (? number? m)] ['#:velocity (? number? v)])
                        (* 1/2 m (sqr v))]))
> (kinetic-energy #:mass 2 #:velocity 1)

1

> (kinetic-energy)

kinetic-energy: contract violation

  expected: (match?/c (hash-table ((quote #:mass) (? number?

m)) ((quote #:velocity) (? number? v))))

  given: '#hash()

  in: the args-hash of

      (make-hash-lambda-contract

       (match?/c

        (hash-table

         ('#:mass (? number? m))

         ('#:velocity (? number? v))))

       number?)

  contract from: (definition kinetic-energy)

  blaming: top-level

   (assuming the contract is correct)

  at: eval:1.0