binding multiple values (Ex: Re: some small proposed changes to standard) 
Author Message
 binding multiple values (Ex: Re: some small proposed changes to standard)


Among other items:

  > 4. Add multiple-value-binding capability to LET, LET*, DO, DO*
  >
  > Multiple value binding is useful, but is poorly integrated syntactically
  > with the rest of Common Lisp.  In LET, LET*, DO, DO* binding forms
  > (var value) or (var value next-value), allow (var1 ... varn) instead
  > of var to bind multiple values returned by the value and next-value
  > forms.  Multiple value binding can be more succinctly expressed with
  > less indentation this way, e.g.,
  >   (let* ((x value1)
  >   ((u v) values2)
  >          (y value3))
  >     ...)
  > versus
  >   (let ((x value1))
  >     (multiple-value-bind (u v) values2
  >       (let ((y value3))
  >          ...)))
  > Moreover, binding in parallel becomes easy to specify, as in
  >   (let ((x value1)
  >         ((u v) values2)
  >         (y value3))
  >     ...)
  > Problem: this might be confused with destructuring in
  > destructuring-bind and macro argument lists that has similar
  > purpose and different behavior (e.g., what is done with
  > extra or unsupplied values).

If the syntax of binding forms is to be extended (which appears
a good idea to me), then perhaps it could be extended in another
way as well.  In a recent post, Fernando Mato Mira (I think)
suggested that the above syntax is incompatible with the
(hypothetical) desire to have the type alongside the variable:

  (let (((i integer) 0))
    ...)
  ->
  (let ((i 0))
    (declare (type integer i))
    ...)

I propose to have the two coexist with the syntax

  (LET ((({var [:TYPE type]}+) values-form))
    body)

e.g.

  (let (((q :type integer r :type integer) (floor a b)))
    ...)

This is similar to declaring the type of structure components.

As to the problem noted above---confusion with destructuring---
I think I can live with that because destructuring does not deal
with multiple values and I can keep the two cases distinct in
my head.

Vassil Nikolov

For more: http://www.*-*-*.com/
  Abaci lignei --- programmatici ferrei.



Mon, 07 Jan 2002 03:00:00 GMT  
 binding multiple values (Ex: Re: some small proposed changes to standard)

| If the syntax of binding forms is to be extended (which appears a good
| idea to me), then perhaps it could be extended in another way as well.
| In a recent post, Fernando Mato Mira (I think) suggested that the above
| syntax is incompatible with the (hypothetical) desire to have the type
| alongside the variable:

  since LET binding forms are to take a variable and a form, I don't see
  the need to stuff the type in with the variable.  since type information
  is optional, let's use the standard way to specify optional stuff: add it
  at the end:

(let ((i 0 integer)) ...)

(do ((i 0 (1+ i) integer)) ...)

  and with multiple-value extensions:

(let (((q r) (floor a b) (integer integer))) ...)

#:Erik
--
  suppose we blasted all politicians into space.
  would the SETI project find even one of them?



Wed, 09 Jan 2002 03:00:00 GMT  
 binding multiple values (Ex: Re: some small proposed changes to standard)

Quote:


> | If the syntax of binding forms is to be extended (which appears a good
> | idea to me), then perhaps it could be extended in another way as well.
> | In a recent post, Fernando Mato Mira (I think) suggested that the above
> | syntax is incompatible with the (hypothetical) desire to have the type
> | alongside the variable:

>   since LET binding forms are to take a variable and a form, I don't see
>   the need to stuff the type in with the variable.  since type information
>   is optional, let's use the standard way to specify optional stuff: add it
>   at the end:

> (let ((i 0 integer)) ...)

> (do ((i 0 (1+ i) integer)) ...)

>   and with multiple-value extensions:

> (let (((q r) (floor a b) (integer integer))) ...)

Because of the prevalance of variables named things like INTEGER, etc.
this is probably not adequately good for error checking.  The DO and
LET above might be typos for ill-formed lets that might not get caught.
Might be better to require a stronger boundary, like
(let ((i 0 :type integer)) ...)

Although there are other reasons why

(let (((the integer i) ...)) ...)

would be simplest.  Or

(let (((the (values integer integer) (values x y)) (window-pos))) ...)

I'm mostly not following this thread of the conversation, but figured
I'd peek in.  Sorry if someone's already suggested this.



Wed, 09 Jan 2002 03:00:00 GMT  
 binding multiple values (Ex: Re: some small proposed changes to standard)

| Because of the prevalance of variables named things like INTEGER, etc.
| this is probably not adequately good for error checking.  The DO and
| LET above might be typos for ill-formed lets that might not get caught.

  although I find the reasoning puzzling, using a keyword to specify type
  seems like a good idea to me because we might want to add other optional
  declarations, as in

(let ((foo () :type list :dynamic-extent t))
  ...)

| Although there are other reasons why
|
| (let (((the integer i) ...)) ...)
|
| would be simplest.

  the symmetry with how it would be written in the absence of declarations
  is appealing, but although I favored this form myself previously, they
  "bury" the variables that are being bound in a lot of clutter, making it
  hard to locate what is being bound.  if your reasoning above is valid, it
  appears to be more cause for concern for typos and problems with this
  approach than the one above.

#:Erik
--
  suppose we blasted all politicians into space.
  would the SETI project find even one of them?



Thu, 10 Jan 2002 03:00:00 GMT  
 binding multiple values (Ex: Re: some small proposed changes to standard)

Quote:


> | Because of the prevalance of variables named things like INTEGER, etc.
> | this is probably not adequately good for error checking.  The DO and
> | LET above might be typos for ill-formed lets that might not get caught.

>   although I find the reasoning puzzling, using a keyword to specify type
>   seems like a good idea to me because we might want to add other optional
>   declarations, as in

If the aim is to get rid of DECLARES, one might as well go the whole way,
and avoid all that keywordy stuff (my yuck).

After all that LETBIND discussion, I've personally came to the conclusion
that the best way is (regardless  of whether there's only one form, LET,
or two, LET and MULTIPLE-VALUE-LET).

Remember, CMUCL will give you an error if a declared numeric variable
has not initializer, so not being able to specify the type of an uninitialized
variable is not a big loss in my opinion (use 0s or NILs).
[
(MULTIPLE-VALUE-LET
     ( var | varlist | ({var | varlist} [initializer decls*])*)
   ...)

where decls will just expand to (DECLARE decls*) except for the following
conveniences:

if a decl is a symbol, it will apply to all variables in varlist.

Otherwise, if decl does not contain at least one of the variables in varlist,
it
is also applies to all variables in varlist
[for type declarations, one could add `that have no type specifically
assigned']

decls that do not start with one of the declaration identifiers
[
declaration     ignore     special
dynamic-extent  inline     type
ftype           notinline
ignorable       optimize
]
will be assumed to be type declarations.

Also, if initializer is an atom, it applies to all the variables in varlist.

So, for example:

(MULTIPLE-VALUE-LET
  (((x y) 0.0 double-float)
   ((u v) #(1 0) ((vector fixnum)))
   ((o p) NIL standard-object dynamic-extent)
   ((a l w) (foo) (float a) ((vector single-float) w) (dynamic-extent l))
  ...)

If you want to have a type called `DYNAMIC-EXTENT' or something like that,
use DECLARE, that's your fault.



Thu, 10 Jan 2002 03:00:00 GMT  
 binding multiple values (Ex: Re: some small proposed changes to standard)

Quote:

> If you want to have a type called `DYNAMIC-EXTENT' or something like that,
> use DECLARE, that's your fault.

OK. I'll let you do:

((genius nil (type dynamic-extent))

;-)



Thu, 10 Jan 2002 03:00:00 GMT  
 binding multiple values (Ex: Re: some small proposed changes to standard)

Quote:

> | Although there are other reasons why
> |
> | (let (((the integer i) ...)) ...)
> |
> | would be simplest.

>   the symmetry with how it would be written in the absence of declarations
>   is appealing, but although I favored this form myself previously, they
>   "bury" the variables that are being bound in a lot of clutter, making it
>   hard to locate what is being bound.  if your reasoning above is valid, it
>   appears to be more cause for concern for typos and problems with this
>   approach than the one above.

We talked about this long ago
in the destructuring discussion.  The key reason to have
 (letbind (((values x y) (values 3 4)) ..))
instead of
 (letbind (((x y) (values 3 4))) ...)
is to allow things other than VALUES to be used.  e.g., constructors.
And once you allow
 (letbind (((cons a b) (cons 3 4))) ...)
then you might also want abstractions like
 (letbind (((make-instance 'foo :a 3 :b 4) (current-foo))) ...)
and you might want that to be implemented by macroexpansion so that
 (macrolet ((xcons (x y) `(cons ,x ,y)))
   (letbind (((xcons a b) (cons 1 2))) ...))
 ==>
 (letbind (((cons b a) (cons 1 2))) ...)
 ==>
 (let ((b 1) (a 2)) ...)
And if that can be the case, then you might want just
 (macrolet ((ivalue (x) `(the integer ,x)))
   (letbind (((ivalue z) 3)) ...))
or
 (macrolet ((sizes (x y) `(the (values integer integer) (values ,x ,y))))
   (letbind (((sizes width height) (window-size foo)))
     ...))
So burying the type in the part to bind might be useful if the purpose
is to let it ride around invisibly.  

I do agree with you the macroexpanded part is cumbersome,
but then so is a LET macroexpanded into a LAMBDA.
Sometimes you put things in the language just to support
nice composition, and I was thinking this might be a good such place.

Before anyone flags me on the issue of macroexpanding here, though,
let me be sure to do some disclaiming right up front:
I admit it's a little weird to say that LET might macroexpand in a
context where the variables are imminently-to-be-bound.  That is, in:
 (defmacro foo (x) `(the float ,x))
 (let ((a 3))
   (declare (fixnum a))
   (letbind (((foo a) z)) ...))
where A while FOO is playing with it is{*filter*} delicately perched between
two universes.  I can't see a "screw case" to this, but I smell one close by.



Thu, 10 Jan 2002 03:00:00 GMT  
 binding multiple values (Ex: Re: some small proposed changes to standard)

Quote:

> (MULTIPLE-VALUE-LET
>      ( var | varlist | ({var | varlist} [initializer decls*])*)
>    ...)

                 ^^^^^

(MULTIPLE-VALUE-LET
     ( var | ({var | varlist} [initializer decls*])*)
   ...)

duh.



Thu, 10 Jan 2002 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. returning from a function (Ex: Re: some small proposed changes to standard)

2. EXIT (Ex: Re: some small proposed changes to standard)

3. bigger FIXNUMs (Ex: Re: some small proposed changes to standard)

4. Find the smallest value of standard logic vector (7 downto 0)

5. __len__ and boolean values - small language change

6. Final SRFI 8: RECEIVE: Binding to multiple values

7. SRFI 8: RECEIVE: Binding to multiple values

8. Defining multiple-values binding forms

9. MULTIPLE-VALUE-BIND question

10. multiple-value binding let and let*

11. lambda list in MULTIPLE-VALUE-BIND?

12. with-slots and multiple-value-bind

 

 
Powered by phpBB® Forum Software