From: Bruno Haible
Subject: homogenous syntax for type declarations
Date: 
Message-ID: <cenvi7$5oq$1@laposte.ilog.fr>
Common Lisp supports typed variables in various situations, but the
syntax to declare a typed variable is different each time:

- In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
    (lambda (x ...) (declare (integer x)) ...)
    (lambda (x ...) (declare (type integer x)) ...)
    (let ((x ...)) (declare (integer x)) ...)
    (let ((x ...)) (declare (type integer x)) ...)

- In DEFMETHOD, DEFGENERIC:
    (defmethod foo ((x integer) ...) ...)

- In LOOP:
    (loop for x integer across v ...)
    (loop for x of-type integer across v ...)

- Type declarations in function returns:
    (declaim (ftype (function (t) integer) foo))
    (defun foo (x) ...)

A typed variable is a variable whose value at any time is guaranteed
by the programmer to belong to a given type. It is assumed that the
type's semantics doesn't change during the dynamic extent of the
variable.

The new module 'typedvar' in CLOCC [1] supports typed variables and typed
function returns through a simple common syntax: [variable type] and [type].
Examples:

- In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
    (lambda ([x integer] ...) ...)
    (let (([x integer] ...) ...)

- In DEFMETHOD, DEFGENERIC:
    (defmethod foo ([x integer] ...) ...)

- In LOOP:
    (loop for [x integer] across v ...)

- Type declarations in function returns:
    (defun foo (x) [integer] ...)

The variable name always comes before the type, because (assuming decent
coding style) it carries more information than the type.

Example:
   (defun scale-long-float (x exp)
     (declare (long-float x) (fixnum exp))
     ...)
->
   (defun scale-long-float ([x long-float] [exp fixnum])
     ...)

Example:
   (labels ((test (df) df))
     (declare (ftype (function (double-float) double-float) test))
     (test 1))
->
   (labels ((test ([df double-float]) [double-float] df))
     (test 1))

Note: Specialized lambda lists in DEFMETHOD, DEFGENERIC can contain an
an evaluated form, whereas type specifiers cannot. Therefore
  (defmethod foo ([x (eql a)]) ...)
is equivalent to
  (defmethod foo ((x (eql 'a))) ...),
and there is no typed-variable syntax for
  (defmethod foo ((x (eql a))) ...).

Note: Another difference with specialized lambda lists in DEFMETHOD is
that the typed variable syntax not only defines a specializer, but
also
a declaration for the entire scope of variable. I.e.
  (defmethod foo ([x integer]) ...)
is equivalent to
  (defmethod foo ((x integer)) (declare (type integer x)) ...)
It would be bad style anyway to assign a non-integer value to x inside
the method.

Would you like to use this syntax extension? If not, why not?

                         Bruno


[1] http://clocc.sourceforge.net/
    in the CVS under clocc/src/syntax/typedecl/typedvar.lisp

From: Ron Garret
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <ronNOSPAM-4BB651.08055904082004@nntp1.jpl.nasa.gov>
In article <············@laposte.ilog.fr>,
 Bruno Haible <·····@clisp.org> wrote:

> - Type declarations in function returns:
>     (defun foo (x) [integer] ...)

Why not (defun [foo integer] (x) ...) instead?  That would be more 
uniform.

That would also indicate the following extensions:

(defvar [*x* integer] ...)
(defconstant [+x+ integer] ...)


> Would you like to use this syntax extension? If not, why not?

I like it, but I'm not wild about the square brackets.  In general I 
feel that special punctuation should not be used unless it's necessary 
to disambiguate the semantics, and in this case I don't believe that's 
the case (with one possible exception being extending the return type 
specification to the DEFMETHOD macro).

An alternative syntax that I once saw used that I found aesthetically 
pleasing was preceding type declarations with a dash, i.e.:

(defun foo - integer (x - float
                      y - symbol) ...)

This gets a little harder to parse but is IMO easier to read, which 
(again IMO) ought to be an overriding consideration.
From: Bruno Haible
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <cetsib$fdh$1@laposte.ilog.fr>
>> - Type declarations in function returns:
>>     (defun foo (x) [integer] ...)
>
> Why not (defun [foo integer] (x) ...) instead?  That would be more 
> uniform.

Well, foo is not a variable (in a Lisp-2 it's in the function namespace),
and what you specify is the _return_ type of foo, not the type of #'foo.

> That would also indicate the following extensions:
>
> (defvar [*x* integer] ...)
> (defconstant [+x+ integer] ...)

These are already implemented in typedvar.lisp.

> An alternative syntax that I once saw used that I found aesthetically 
> pleasing was preceding type declarations with a dash, i.e.:
>
> (defun foo - integer (x - float
>                       y - symbol) ...)
>
> This gets a little harder to parse

Yes, and the things that are hard to parse for a machine are also hard
to parse to a human. Cf. the LOOP macro syntax or the keyword argument
list syntax that often appears badly indented by automatic "pretty"-printers:

    (loop for x from
          2 below
          5 do (print x))
    (make-instance point :x
                   3 :y 4)

Bruno
From: Ron Garret
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <ronNOSPAM-92BF55.12231005082004@nntp1.jpl.nasa.gov>
In article <············@laposte.ilog.fr>,
 Bruno Haible <·····@clisp.org> wrote:

> >> - Type declarations in function returns:
> >>     (defun foo (x) [integer] ...)
> >
> > Why not (defun [foo integer] (x) ...) instead?  That would be more 
> > uniform.
> 
> Well, foo is not a variable (in a Lisp-2 it's in the function namespace),
> and what you specify is the _return_ type of foo, not the type of #'foo.

True, but these are consequences of CL's non-uniform (some might say 
"broken") function definition syntax.  If you wanted to be really pure 
you'd have to do something like:

(defun [foo (x) integer] ...)

or, even "better":

(define [(foo x) integer] ...

but I think (defun [foo integer] (x) ...) is a good compromise.  I find 
it more aesthetic than (defun foo (x) [integer] ...), which breaks the 
(apparent) convention that square brackets enclose the thing being typed 
followed by the type.

An alternative fix would be:

(defun foo (x [integer]) [integer] ...)

where the convention would be that types are denoted by square brackets, 
and they always follow the thing being typed.  If you were to do that 
I'd recommend using angle brackets instead:

(defun foo (x <integer>) <integer> ...)

as a nod to Dylan.

But these are very minor aesthetic quibbles.

> > An alternative syntax that I once saw used that I found aesthetically 
> > pleasing was preceding type declarations with a dash, i.e.:
> >
> > (defun foo - integer (x - float
> >                       y - symbol) ...)
> >
> > This gets a little harder to parse
> 
> Yes, and the things that are hard to parse for a machine are also hard
> to parse to a human. Cf. the LOOP macro syntax or the keyword argument
> list syntax that often appears badly indented by automatic "pretty"-printers:
> 
>     (loop for x from
>           2 below
>           5 do (print x))
>     (make-instance point :x
>                    3 :y 4)

Yeah.  Personally, I like LOOP, but I know that a lot of people don't 
for this very reason.

I'll note in passing that most CL pretty printers will probably not do 
the right thing with (defun foo (x) [integer] ...) without some tweaking 
either.
From: Sam Steingold
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <uacx9uxec.fsf@gnu.org>
> * Bruno Haible <·····@pyvfc.bet> [2004-08-05 17:59:39 +0000]:
>
>>> - Type declarations in function returns:
>>>     (defun foo (x) [integer] ...)
>>
>> Why not (defun [foo integer] (x) ...) instead?  That would be more
>> uniform.
>
> Well, foo is not a variable (in a Lisp-2 it's in the function namespace),
> and what you specify is the _return_ type of foo, not the type of #'foo.

so? we write
    (defun foo (...) ...)
not
    (defun (foo ...) ...)
or
    (defun (function foo) (...) ...)
and there is no ambiguity.

the two things after defun name a function and its arguments, and
writing
        (defun [foo integer] ([bar string]) ...)
is clear and unambiguous.

--
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Ernqvat guvf ivbyngrf QZPN.
From: Ron Garret
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <ronNOSPAM-5FB399.13591805082004@nntp1.jpl.nasa.gov>
In article <·············@gnu.org>, Sam Steingold <···@gnu.org> wrote:

> > * Bruno Haible <·····@pyvfc.bet> [2004-08-05 17:59:39 +0000]:
> >
> >>> - Type declarations in function returns:
> >>>     (defun foo (x) [integer] ...)
> >>
> >> Why not (defun [foo integer] (x) ...) instead?  That would be more
> >> uniform.
> >
> > Well, foo is not a variable (in a Lisp-2 it's in the function namespace),
> > and what you specify is the _return_ type of foo, not the type of #'foo.
> 
> so? we write
>     (defun foo (...) ...)
> not
>     (defun (foo ...) ...)
> or
>     (defun (function foo) (...) ...)
> and there is no ambiguity.
> 
> the two things after defun name a function and its arguments, and
> writing
>         (defun [foo integer] ([bar string]) ...)
> is clear and unambiguous.

It also just occurred to me that having a uniform convention has the 
added advantage that code written in this style will actually compile in 
stock CL with simple read macros on #\[ and #\].
From: Christophe Turle
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <ceqv9n$u9m$1@amma.irisa.fr>
Bruno Haible wrote:
> Common Lisp supports typed variables in various situations, but the
> syntax to declare a typed variable is different each time:
> 
> - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
>     (lambda (x ...) (declare (integer x)) ...)
>     (lambda (x ...) (declare (type integer x)) ...)
>     (let ((x ...)) (declare (integer x)) ...)
>     (let ((x ...)) (declare (type integer x)) ...)
> 
> - In DEFMETHOD, DEFGENERIC:
>     (defmethod foo ((x integer) ...) ...)
> 
> - In LOOP:
>     (loop for x integer across v ...)
>     (loop for x of-type integer across v ...)
> 
> - Type declarations in function returns:
>     (declaim (ftype (function (t) integer) foo))
>     (defun foo (x) ...)
> 
> A typed variable is a variable whose value at any time is guaranteed
> by the programmer to belong to a given type. It is assumed that the
> type's semantics doesn't change during the dynamic extent of the
> variable.
> 
> The new module 'typedvar' in CLOCC [1] supports typed variables and typed
> function returns through a simple common syntax: [variable type] and [type].
> Examples:
> 
> - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
>     (lambda ([x integer] ...) ...)
>     (let (([x integer] ...) ...)
> 
> - In DEFMETHOD, DEFGENERIC:
>     (defmethod foo ([x integer] ...) ...)
> 
> - In LOOP:
>     (loop for [x integer] across v ...)
> 
> - Type declarations in function returns:
>     (defun foo (x) [integer] ...)

I'm happy with the idea but not with the '[' ']'. Generating or parsing such code becomes more complicated.
Using only '(' and ')' perhaps with keywords should be better imho.


i should have check in the sources, but ... do you redefine lambda, defmethod to implement this ?


ctu.
From: Bruno Haible
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <cetsq7$fdh$2@laposte.ilog.fr>
> I'm happy with the idea but not with the '[' ']'. Generating or parsing
> such code becomes more complicated.
> Using only '(' and ')' perhaps with keywords should be better imho.

Do you have a concrete suggestion, instead of   [var type] ?

> i should have check in the sources, but ... do you redefine lambda,
> defmethod to implement this ?

Sure, lambda, function, let, defmethod, etc. are all overridden - all
special operators and macros that allow to specify variable bindings.


Bruno
From: Christophe Rhodes
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <sqsmb1icxw.fsf@cam.ac.uk>
Bruno Haible <·····@clisp.org> writes:

>> i should have check in the sources, but ... do you redefine lambda,
>> defmethod to implement this ?
>
> Sure, lambda, function, let, defmethod, etc. are all overridden - all
> special operators and macros that allow to specify variable bindings.

How does this interact with other packages which also want to override
such operators?

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Aleksandr Skobelev
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <m1wu0cd53t.fsf@askomac.add.com>
> > I'm happy with the idea but not with the '[' ']'. Generating or parsing
> > such code becomes more complicated.
> > Using only '(' and ')' perhaps with keywords should be better imho.
> 
> Do you have a concrete suggestion, instead of   [var type] ?
> 

What about the THE form but with only argument? Something like follows
(it is the modified proposals from your original message):

- In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
    (lambda ((x (the integer)) ...) ...)
    (let (((x (the integer) ...) ...)

- In DEFMETHOD, DEFGENERIC:
    (defmethod foo ((x (the integer)) ...) ...)

- In LOOP:
    (loop for (x (the integer)) across v ...)

- Type declarations in function returns:
    (defun (foo (the integer)) (x)  ...)

Aleksandr
From: Aleksandr Skobelev
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <m1smb0d4ew.fsf@askomac.add.com>
> - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
>     (lambda ((x (the integer)) ...) ...)
>     (let (((x (the integer) ...) ...)

      (let (((x (the integer)) ...) ...)
                             ^
From: Christophe Turle
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <cevsqh$951$1@amma.irisa.fr>
Aleksandr Skobelev wrote:
>>>I'm happy with the idea but not with the '[' ']'. Generating or parsing
>>>such code becomes more complicated.
>>>Using only '(' and ')' perhaps with keywords should be better imho.
>>
>>Do you have a concrete suggestion, instead of   [var type] ?
>>
> 
> 
> What about the THE form but with only argument? Something like follows
> (it is the modified proposals from your original message):
> 
> - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
>     (lambda ((x (the integer)) ...) ...)
>     (let (((x (the integer) ...) ...)
> 
> - In DEFMETHOD, DEFGENERIC:
>     (defmethod foo ((x (the integer)) ...) ...)
> 
> - In LOOP:
>     (loop for (x (the integer)) across v ...)
> 
> - Type declarations in function returns:
>     (defun (foo (the integer)) (x)  ...)
> 
> Aleksandr

instead of (x (the integer)) why not 

1- (x the integer) :

 - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
     (lambda ((x the integer) ...) ...)
     (let (((x the integer)) ...) ...)
 
 - In DEFMETHOD, DEFGENERIC:
     (defmethod foo ((x the integer) ...) ...)
 
 - In LOOP:
     (loop for (x the integer) across v ...)
 
 - Type declarations in function returns:
     (defun (foo the integer) (x)  ...)


2- or better => (the integer x)

 - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
     (lambda ((the integer x) ...) ...)
     (let (((the integer x)) ...) ...)
 
 - In DEFMETHOD, DEFGENERIC:
     (defmethod foo ((the integer x) ...) ...)
 
 - In LOOP:
     (loop for (the integer x) across v ...)
 
 - Type declarations in function returns:
     (defun (the integer foo) (x)  ...)


ctu
From: Peter Herth
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <ceqvvg$53a$1@newsreader2.netcologne.de>
Bruno Haible wrote:

> 
> Would you like to use this syntax extension? If not, why not?
> 

Yes, looks like a good idea in my eyes :).
While CL has type definition mechanisms, I found them very 
ununiform and sometimes cumbersome to use. 

Peter

-- 
pet project: http://dawn.netcologne.de
homepage:    http://www.peter-herth.de
lisp stuff:  http://www.peter-herth.de/lisp.html
get Ltk here: http://www.peter-herth.de/ltk/
From: Marco Antoniotti
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <J5sQc.34$Vn5.12006@typhoon.nyu.edu>
Peter Herth wrote:

> Bruno Haible wrote:
> 
> 
>>Would you like to use this syntax extension? If not, why not?
>>
> 
> 
> Yes, looks like a good idea in my eyes :).
> While CL has type definition mechanisms, I found them very 
> ununiform and sometimes cumbersome to use. 

Time for a shameless plug. :)

Check out the DEFINER project http://www.common-lisp.net/project/definer/

Cheers
--
Marco
From: Christophe Turle
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <cevif4$6gf$1@amma.irisa.fr>
Marco Antoniotti wrote:
> Check out the DEFINER project http://www.common-lisp.net/project/definer/

cool, i like it : simple, clear, great !

ctu
From: Kalle Olavi Niemitalo
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <87d626hq9u.fsf@Astalo.kon.iki.fi>
Bruno Haible <·····@clisp.org> writes:

>     (lambda ([x integer] ...) ...)

Does this mean lambda forms cannot be used?
If so, should the standard be amended to allow something like:

  (define-lambda-macro typedvar-common-lisp:lambda (lambda-expr &rest args)
    `(funcall ,lambda-expr ,@args))

It seems to me you should also do:

  (setf (find-class 'typedvar-common-lisp:function)
        (find-class 'cl:function))
  (deftype typedvar-common-lisp:function (&rest args)
    `(cl:function ,@args))
  (defmethod documentation (x (doc-type (eql 'typedvar-common-lisp:function)))
    (documentation x 'cl:function))
  (defmethod (setf documentation)
      (new-value x (doc-type (eql 'typedvar-common-lisp:function)))
    (setf (documentation x 'cl:function) new-value))

and change the #' reader macro.

> - In DEFMETHOD, DEFGENERIC:
>     (defmethod foo ([x integer] ...) ...)

I don't like this.  What if I want to declare the type of a
parameter without specializing on it?

> - Type declarations in function returns:
>     (defun foo (x) [integer] ...)

This seems nasty: the type is declared within the DEFUN form,
but it also affects calls from elsewhere, even if the function
is later redefined.

Please document that the documentation string cannot precede the
return type specification.
From: Bruno Haible
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <cettco$fdh$3@laposte.ilog.fr>
Kalle Olavi Niemitalo <···@iki.fi> wrote:
> It seems to me you should also do:
>
>  (setf (find-class 'typedvar-common-lisp:function)
>        (find-class 'cl:function))
>  (deftype typedvar-common-lisp:function (&rest args)
>    `(cl:function ,@args))
>  (defmethod documentation (x (doc-type (eql 'typedvar-common-lisp:function)))
>    (documentation x 'cl:function))
>  (defmethod (setf documentation)
>      (new-value x (doc-type (eql 'typedvar-common-lisp:function)))
>    (setf (documentation x 'cl:function) new-value))
>
> and change the #' reader macro.

You're right. Thanks!

        Bruno
From: Kalle Olavi Niemitalo
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <87zn58ri4y.fsf@Astalo.kon.iki.fi>
Bruno Haible <·····@clisp.org> writes:

> Kalle Olavi Niemitalo <···@iki.fi> wrote:
>> It seems to me you should also do:

>>  (defmethod (setf documentation)
>>      (new-value x (doc-type (eql 'typedvar-common-lisp:function)))
>>    (setf (documentation x 'cl:function) new-value))

> You're right. Thanks!

In CVS revision 1.2 of typedvar.lisp, you do this instead:

  (cl:defmethod (setf documentation) (new-value x (doc-type (eql 'function))
    ((setf documentation) new-value x 'cl:function))

That setf syntax does not work in CMUCL nor SBCL.
(funcall #'(setf documentation) ...) would, though.
From: Marco Antoniotti
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <LSLQc.36$Vn5.12928@typhoon.nyu.edu>
Kalle Olavi Niemitalo wrote:

> Bruno Haible <·····@clisp.org> writes:
> 
> 
>>Kalle Olavi Niemitalo <···@iki.fi> wrote:
>>
>>>It seems to me you should also do:
> 
> 
>>> (defmethod (setf documentation)
>>>     (new-value x (doc-type (eql 'typedvar-common-lisp:function)))
>>>   (setf (documentation x 'cl:function) new-value))
> 
> 
>>You're right. Thanks!
> 
> 
> In CVS revision 1.2 of typedvar.lisp, you do this instead:
> 
>   (cl:defmethod (setf documentation) (new-value x (doc-type (eql 'function))
>     ((setf documentation) new-value x 'cl:function))
> 
> That setf syntax does not work in CMUCL nor SBCL.
> (funcall #'(setf documentation) ...) would, though.

But why would you want to do that since

	(setf (documentation x 'cl:function) new-value)

is perfectly good CL?

Cheers
--
Marco
From: Kalle Olavi Niemitalo
Subject: lambda macros (was: homogenous syntax for type declarations)
Date: 
Message-ID: <87zn2c6yy6.fsf_-_@Astalo.kon.iki.fi>
Back in August, I wrote on shadowing LAMBDA in a package:

> Does this mean lambda forms cannot be used?
> If so, should the standard be amended to allow something like:
>
>   (define-lambda-macro typedvar-common-lisp:lambda (lambda-expr &rest args)
>     `(funcall ,lambda-expr ,@args))

According to <························@thor.oar.net>, Howard
I. Cannon proposed a similar feature (lambda macros) to the
designers of Common Lisp already in 1982.  The proposal was voted
down because it would have required changes in *MACROEXPAND-HOOK*
and was not considered useful enough.

The primary difference between Cannon's proposal and my
DEFINE-LAMBDA-MACRO is that his lambda macros expanded lambda
expressions, whereas mine would have expanded lambda forms.
Thus, Cannon's lambda macros would support (function
(typedvar-common-lisp:lambda ([x integer] ...) ...)) without
shadowing CL:FUNCTION.

This difference also means that Cannon's lambda macros cannot
manipulate the arguments in a lambda form: in ((my-lambda ...) x),
the lambda macro for MY-LAMBDA does not see X at all.  I'm not
sure this feature would even be useful, but in any case, it
could be still be implemented by allowing anonymous macros:

  ((nlambda (a b c) (list a b c))
   x y z)

could then expand to

  ((macro lambda (#:g1 #:g2 #:g2)
     `((lambda (a b c) (list a b c))
       ',#:g1 ',#:g2 ',#:g3)
   x y z)

, which would in turn expand to

  ((lambda (a b c) (list a b c))
   'x 'y 'z)

.  (I don't know if that's the way the Lisp Machine did NLAMBDA.)
Of course, lambda macros that expanded to anonymous macro
expressions would not be usable with FUNCTION.

Cannon also proposed a DEFFUNCTION operator that generalized
DEFUN for arbitrary lambda macros.  With this,
TYPEDVAR-COMMON-LISP:DEFUN could almost be defined as follows:

  (defmacro typedvar-common-lisp:defun (name lambda-list &body body)
    `(deffunction ,name typedvar-common-lisp:lambda ,lambda-list
       ,@body))

However, this would not generate an FTYPE declaration outside
the function.  It could still wrap the body of the function in a
THE form; I actually prefer this mapping as it does not prevent
changing the type if the function is later redefined.

How should *MACROEXPAND-HOOK* be changed to make it applicable to
lambda macros?  My first guess would be to call *MACROEXPAND-HOOK*
as usual but with the extended lambda form (my-lambda ...) taking
the place of the macro form.  However, I am afraid this might not
be safe: the behavior of *MACROEXPAND-HOOK* seems inadequately
specified, and a hook function might assume that the result is an
evaluatable form and e.g. wrap a PROGN around it, which would of
course wreck lambda macros completely.  I suppose there are a few
ways to fix this:

(a) Constrain the behavior of *MACROEXPAND-HOOK* so that the hook
    must always call the expander with the original parameters
    and return its (multiple?) values unchanged; only the side
    effects may differ.  However, the article mentioned above
    includes a DISPLACING-MACROEXPAND-HOOK function (by David
    A. Moon) that does not follow this rule; thus I presume there
    is other code that breaks it too.

(b) Like (a), but if the result is a list, then the top-level
    cons cells may differ (as in COPY-LIST).  Full COPY-TREE
    would not be permitted as it can break sharing of literals.

(c) Specify that *MACROEXPAND-HOOK* is only used with macros that
    expand to evaluatable forms.  All macros are expanded via the
    new variable *HAIRY-MACROEXPAND-HOOK*, whose value must be a
    function of four arguments.  The first indicates the intended
    syntax of the result (e.g. :FORM or :LAMBDA-EXPRESSION), and
    the remaining three are the same as in *MACROEXPAND-HOOK*.
    The initial value of *HAIRY-MACROEXPAND-HOOK* is a function
    equivalent to

      (defun initial-hairy-macroexpand-hook (syntax macro-function
                                             object environment)
        (if (eq syntax ':form)
          (funcall *macroexpand-hook* macro-function object environment)
          (funcall macro-function object environment)))

    apart from implementation-defined side effects.  If user code
    defines and expands macros for other purposes, then it should
    use other (non-keyword) symbols as the SYNTAX argument.  If a
    function installed as *HAIRY-MACROEXPAND-HOOK* recognizes the
    syntax, then it may alter the OBJECT argument and the result
    in any way that makes sense with that syntax; otherwise, it
    must pass the arguments and results through unchanged.

There also ought to be ways to define local lambda macros
(LAMBDA-MACROLET) and access the lambda macro functions
(LAMBDA-MACRO-FUNCTION or a flag to MACRO-FUNCTION).
From: Antonio Menezes Leitao
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <87hdrikbjo.fsf@evaluator.pt>
Bruno Haible <·····@clisp.org> writes:

> Common Lisp supports typed variables in various situations, but the
> syntax to declare a typed variable is different each time:
>
> - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
>     (lambda (x ...) (declare (integer x)) ...)
>     (lambda (x ...) (declare (type integer x)) ...)
>     (let ((x ...)) (declare (integer x)) ...)
>     (let ((x ...)) (declare (type integer x)) ...)
>
> - In DEFMETHOD, DEFGENERIC:
>     (defmethod foo ((x integer) ...) ...)
>
> - In LOOP:
>     (loop for x integer across v ...)
>     (loop for x of-type integer across v ...)
>
> - Type declarations in function returns:
>     (declaim (ftype (function (t) integer) foo))
>     (defun foo (x) ...)
>
> A typed variable is a variable whose value at any time is guaranteed
> by the programmer to belong to a given type. It is assumed that the
> type's semantics doesn't change during the dynamic extent of the
> variable.
>
> The new module 'typedvar' in CLOCC [1] supports typed variables and typed
> function returns through a simple common syntax: [variable type] and [type].
> Examples:
>
> - In LAMBDA, LET, LET*, MULTIPLE-VALUE-BIND:
>     (lambda ([x integer] ...) ...)
>     (let (([x integer] ...) ...)
>
> - In DEFMETHOD, DEFGENERIC:
>     (defmethod foo ([x integer] ...) ...)
>
> - In LOOP:
>     (loop for [x integer] across v ...)
>
> - Type declarations in function returns:
>     (defun foo (x) [integer] ...)
>
> The variable name always comes before the type, because (assuming decent
> coding style) it carries more information than the type.
>
> Example:
>    (defun scale-long-float (x exp)
>      (declare (long-float x) (fixnum exp))
>      ...)
> ->
>    (defun scale-long-float ([x long-float] [exp fixnum])
>      ...)
>
> Example:
>    (labels ((test (df) df))
>      (declare (ftype (function (double-float) double-float) test))
>      (test 1))
> ->
>    (labels ((test ([df double-float]) [double-float] df))
>      (test 1))
>
> Note: Specialized lambda lists in DEFMETHOD, DEFGENERIC can contain an
> an evaluated form, whereas type specifiers cannot. Therefore
>   (defmethod foo ([x (eql a)]) ...)
> is equivalent to
>   (defmethod foo ((x (eql 'a))) ...),
> and there is no typed-variable syntax for
>   (defmethod foo ((x (eql a))) ...).
>
> Note: Another difference with specialized lambda lists in DEFMETHOD is
> that the typed variable syntax not only defines a specializer, but
> also
> a declaration for the entire scope of variable. I.e.
>   (defmethod foo ([x integer]) ...)
> is equivalent to
>   (defmethod foo ((x integer)) (declare (type integer x)) ...)
> It would be bad style anyway to assign a non-integer value to x inside
> the method.

What is the new syntax for the following (old-syntax) method
declaration?

(defmethod foo ((x integer) y)
  (declare (integer y))
  ...)

Ant�nio Leit�o.
From: Bruno Haible
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <cettm7$fdh$4@laposte.ilog.fr>
Antonio Menezes Leitao <··············@evaluator.pt> wrote:

> What is the new syntax for the following (old-syntax) method
> declaration?
>
> (defmethod foo ((x integer) y)
>   (declare (integer y))
>   ...)

You can use

  (defmethod foo ([x integer] [y integer])
    ...)

without any loss of functionality.

             Bruno
From: Sam Steingold
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <u7jsduxds.fsf@gnu.org>
> * Bruno Haible <·····@pyvfc.bet> [2004-08-05 18:18:47 +0000]:
>
> Antonio Menezes Leitao <··············@evaluator.pt> wrote:
>
>> What is the new syntax for the following (old-syntax) method
>> declaration?
>>
>> (defmethod foo ((x integer) y)
>>   (declare (integer y))
>>   ...)
>
> You can use
>
>   (defmethod foo ([x integer] [y integer])
>     ...)
>
> without any loss of functionality.

Note however that

 (defmethod foo ((x integer) y)
   (declare (integer y))
   ...)

and

 (defmethod foo ((x integer) (y integer))
   ...)

are not the same!


--
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
will write code that writes code that writes code for food
From: Christophe Rhodes
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <sqoelpi9ko.fsf@cam.ac.uk>
Bruno Haible <·····@clisp.org> writes:

> Antonio Menezes Leitao <··············@evaluator.pt> wrote:
>
>> What is the new syntax for the following (old-syntax) method
>> declaration?
>>
>> (defmethod foo ((x integer) y)
>>   (declare (integer y))
>>   ...)
>
> You can use
>
>   (defmethod foo ([x integer] [y integer])
>     ...)
>
> without any loss of functionality.

Even if the FOO generic function has :argument-precedence-order (y x)?
I don't think so.

Even in the case above
  (defmethod foo ((x integer) y)
    (declare (integer y))
    (+ x y))
  (defmethod foo ((x integer) (y integer))
    (1+ (call-next-method)))
would seem to be unreproduceable using your syntax.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: Antonio Menezes Leitao
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <87brhpz08g.fsf@evaluator.pt>
Bruno Haible <·····@clisp.org> writes:

> Antonio Menezes Leitao <··············@evaluator.pt> wrote:
>
>> What is the new syntax for the following (old-syntax) method
>> declaration?
>>
>> (defmethod foo ((x integer) y)
>>   (declare (integer y))
>>   ...)
>
> You can use
>
>   (defmethod foo ([x integer] [y integer])
>     ...)
>
> without any loss of functionality.
>

I will not repeat the examples that others have presented.

The main consideration, IMHO, is that parameter specializers and type
declaration are orthogonal concepts.  They have a lot of similarities
but they are orthogonal.  If you mix them, you will loose big.  For
example, let's imagine a situation where I defined the method

(defmethod foo ((x integer) y)
  (declare (integer y))
  ...)

and then I discovered that I made a mistake: the type declaration was
wrong.  I didn't mean integer but cons:

(defmethod foo ((x integer) y)
  (declare (cons y))
  ...)

Using the old syntax, no problem, I just recompile the method.  Using
your new syntax, the old method is still active.

I consider that a loss of functionality.


Let's consider another example: CMUCL and SBCL treat type declaration
as assertions.  Here is an example using "old" syntax:

(defmethod foo ((x integer) y)
  1)

(defmethod foo :before ((x integer) y)
  (declare (integer y)))

CL-USER> (foo 5 1)
1
CL-USER> (foo 5 'a)
debugger invoked on a TYPE-ERROR in thread 3202:
  The value A is not of type INTEGER.


Now, if we convert the example to use your "new" syntax, you will get
different behavior (and you will not get the error).

I consider that a loss of functionality.


I'm sure we can find a lot more examples where things work
differently.  However, I think it is easy to solve all these problems.
Just avoid using your new syntax for parameter specializers:

(defmethod foo ([x integer])
  ...)

should be the same as 

(defmethod foo ((x t))
  (declare (integer x))
  ...)

Ant�nio Leit�o.

--------------------------------

PS: I also come across this in the context of the Linj language where
type declarations are much more important than in Common Lisp.  In the
beginning I explored something similar to what you did.  In the end, I
decided to use a unique symbol to encode a name and its type
declaration: name/type.

Using Linj syntax, the example that specializes the first parameter
and type-declares the second becomes:

(defmethod foo ((x integer) y/integer)
  ...)

PPS: Although I was almost sure about my CMUCL/SBCL example, I tried
it on the last CMUCL available on debian and noticed that it does not
work as expected in CMU Common Lisp CVS release-19a + minimal debian
patches.  It still works in SBCL 0.8.13.19.  Go figure.
From: Rahul Jain
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <871xie1jsl.fsf@nyct.net>
Antonio Menezes Leitao <··············@evaluator.pt> writes:

> The main consideration, IMHO, is that parameter specializers and type
> declaration are orthogonal concepts.  They have a lot of similarities
> but they are orthogonal.

They are so orthogonal that one only works with a subset of the types
that the other works with. It is essential to distinguish between these
situations, because otherwise you will get errors.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Fred Gilham
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <u74qnhhfx5.fsf@snapdragon.csl.sri.com>
Bruno Haible asks:
> Would you like to use this syntax extension? If not, why not?

1) I don't like things that give Lisp syntax.  They open the door to
other things that give lisp syntax.  Then eventually you wind up with
some C++-like notation.  Note: this is a slippery-slope argument.
Slippery-slope arguments are a higher form of argument and are always
true.  :-)

2) Right now declarations are forms.  They can be treated
independently, added and removed with little fuss.  But [x integer] is
a "thingy".  I don't know what you'd call it.  If you want to remove
the declaration for some reason, what do you do?  Write "[x]"?  Write
"(x)"?  Inconvenient.

3) It hurts my eyes.

-- 
Fred Gilham                                         ······@csl.sri.com
Central bankers don't trust each other. They know how easy it is to
create money out of nothing. They hold dollar-denominated assets, such
as U.S. Treasury-bills, because they can earn interest --- not much
these days --- but they settle their final accounts with each other in
gold.                                                   --- Gary North
From: ·········@random-state.net
Subject: Re: homogenous syntax for type declarations
Date: 
Message-ID: <cetfbk$4su4o$2@midnight.cs.hut.fi>
Bruno Haible <·····@clisp.org> wrote:

> Would you like to use this syntax extension? If not, why not?

I share Fred Gilham's sentiment re. slippery slope letting syntax in, and
his aesthetic view on the ugliness. On an admittedly quick read of the
proposal I didn't find it particularly more homogenous then the standard
syntax -- some, but not enough to justify the extra syntax.

On the other hand, I've nothing against a uniform syntax for declaratios
in principle, but I'd rather see what could be done to unify the current
declaration syntax, and even if DECLARE &co were to go away I'd hope to
stay with parens.

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java.
                             An elegant weapon for a more civilized time."