Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Please explain lisp's multiple-value-bind

I've read the docs (several different versions!) but I can't quite get my head wrapped around multiple-value-bind.

Here's what I (think I) know:

  • The first parameter is a list of variables that are going to get bound.
  • The next parameter is a list of values that get bound to the variables.
    • Am I right that these 2 lists have to be the same length?
  • The last parameter (is it optional?) is a body of code that can act on the variables with their newly-bound values.

That sure seems to be how the docs read, and it fits with code I'm reading but not-quite following. I get into trouble when I try to create a multiple-value-bind statement from scratch, as a test. I end up with results like this:

? (mulitple-value-bind (x y z) (values 11 22 33) (+ x y z)) ;; EDIT: contains typo
> Error: Unbound variable: Y
> While executing: CCL::CHEAP-EVAL-IN-ENVIRONMENT, in process Listener(7).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Retry getting the value of Y.
> Type :? for other options.
1 > 

(I was sort of hoping for output along the lines of 66.) (I'm using Clozure-CL if it matters, though I don't think it should.)

Also, I'm looking at some sample code (trying to understand Project Euler Problem 24) that reads like this:

(multiple-value-bind
    (q r)
    (floor n m)
    (cons (nth q lst) (permute-b r (remove-nth q lst)))
)

(NOTE: I may have mis-indented it, which may be affecting my lack of understanding)

What I don't get about this is it looks to me as if there are 2 variables being multiply-bound (q & r), but only one value (floor n m). Or is the other value the cons statement, and there is no body?!

As you can see, I completely don't get multiple-value-bind; please enlighten me.

Thanks!

like image 478
Olie Avatar asked Jul 27 '13 18:07

Olie


1 Answers

Your first example with the "unbound variable" is due to your misspelling multiple-value-bind. Try fixing the spelling; you should see a different result.

As to your second question, floor returns two values, the floor and the remainder. Remember that values is not the only function that returns multiple values!


So, basically, the multiple-value-bind form looks like this:

(multiple-value-bind (var-1 .. var-n) expr
  body)

where expr is an expression that returns multiple values, which are bound to the variable names given in var-1 .. var-n; those variables are available for use in body. It is okay for expr to return more or fewer values than are given as variables; nil is used as the default value for any absent values, and any excess values are discarded.

like image 56
Chris Jester-Young Avatar answered Oct 19 '22 07:10

Chris Jester-Young