🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

5 total messages Started by Len Charest Fri, 20 Nov 1992 22:12
Extending syntax/semantics of method specializers
#552
Author: Len Charest
Date: Fri, 20 Nov 1992 22:12
86 lines
5533 bytes
Is there a (generic) function that when given a parameter-specializer-name will
return the corresponding specializer object? How about a function that returns a
form that when evaluated will return the specializer.?

I want to extend the syntax of DEFMETHOD and other method defining forms in one
of the following ways:

1. A list of the form (SATISFIES <symbol>) is a valid parameter-specializer-name.
The <symbol> would name a function of exactly one argument.
2. A function of exactly one argument is a valid parameter-specializer-name.

In either case, the parameter-specializer-name would resolve to a specializer
object that held a function of exactly one argument. Semantics: at method
dispatch time, the function would be called as a predicate with the corresponding
value of the specialized method argument. If the predicate were to return NIL and
the method were otherwise applicable (e.g., as determined by
COMPUTE-APPLICABLE-METHODS) then the method would no longer be applicable. This 
approach would faciliate dispatch based on, for example, the run-time (or GF 
call-time) value of global variables, user-defined types, etc.

After consulting AMOP, I believe I'll need to do the following to implement such
'satisfies-specializers': define specialized metaobject classes based on
STANDARD-GENERIC-FUNCTION and STANDARD-METHOD; define methods on
COMPUTE-APPLICABLE-METHODS and COMPUTE-APPLICABLE-METHODS-USING-CLASSES; define
methods on SPECIALIZER-DIRECT-GENERIC-FUNCTIONS and SPECIALIZER-DIRECT-METHODS; 
define a class of satisfies-specializers to support everything else. All of this
is no big deal.

However, there seems to be no protocol for converting specializer-names into
specializer objects. AMOP defines an abstract class called SPECIALIZER and a
direct subclass called EQL-SPECIALIZER (table 5.1, p 141), but there is no 
supporting protocol for creating/using such objects. What I need to implement 
satisfies-specializers is a set of functions for generically generating 
specializer objects from a given specializer-name. These functions would
form a 'specializer initialization protocol'. These functions then need to
become a part of the initialization protocol for method objects.

Proposal: I propose the following additions to the MOP (as described in AMOP). 
If the processing of DEFMETHOD (as described on p 149-150 in AMOP) were 
revised to include use of these functions then I'd have a portable way of 
writing satisfies-specializers.

SPECIALIZER-OBJECT (specializer-name)                       [Generic Function]
  This generic function returns the specializer object associated with
specializer-name. 
SPECIALIZER-OBJECT ((specializer-name symbol)                         [Method]
  This method calls (FIND-CLASS specializer-name).
SPECIALIZER-OBJECT ((specializer-name list))                          [Method]
  This method calls (TYPE-SPECIALIZER-OBJECT (CAR specializer-name) (CDR
specializer-name)). The value returned by TYPE-SPECIALIZER-OBJECT is the value
returned by this function.

TYPE-SPECIALIZER-OBJECT (type-specifier subsidiary-info)    [Generic Function]
  This generic function returns the specializer object associated with the
given type-specifier and its subsidiary-info.
TYPE-SPECIALIZER-OBJECT ((type-specifier (eql 'eql)) subsidiary-info  [Method]
  This method calls (INTERN-EQL-SPECIALIZER (CAR subsidiary-info)).
TYPE-SPECIALIZER-OBJECT ((type-specifier (eql 'satisfies))            [Method]
                         subsidiary-info)
  This method computes the satisfies-specializer object associated with the 
given subsidiary-info.

Notes: As implied by the above, any specializer-name that is a list is 
interpreted to be a 'type-specializer-name'. Thus, eql-specializer-names are
no longer unique in their role as list-valued specializer-names. This approach
opens up the possibility of a wide range of method specialization strategies. 
This is also the approach necessary to support extension 1 above. 

If the role of eql-specializers is not to be changed, then we could fall back
on the syntax of extension 2, thereby obviating the need for 
TYPE-SPECIALIZER-OBJECT. The methods on SPECIALIZER-OBJECT would be ammended 
as follows:

SPECIALIZER-OBJECT ((specializer-name symbol)                         [Method]
  This method calls (FIND-CLASS specializer-name).
SPECIALIZER-OBJECT ((specializer-name list))                          [Method]
  This method calls (INTERN-EQL-SPECIALIZER specializer-name).
SPECIALIZER-OBJECT ((specializer-name function))                      [Method]
  This method computes the satisfies-specializer object associated with 
specializer-name.

Comments?
..................................................
                                  Len Charest, Jr.
                 JPL Artificial Intelligence Group
                          charest@aig.jpl.nasa.gov
Extending syntax/semantics of method specializers
#553
Author: Eric Peterson x7644
Date: Sat, 21 Nov 1992 04:25
61 lines
3462 bytes
>>>>> On Fri, 20 Nov 1992 22:12:51 GMT, charest@Aig.Jpl.Nasa.Gov (Len
Charest) said:
Proposal: I propose the following additions to the MOP (as described in AMOP). 
If the processing of DEFMETHOD (as described on p 149-150 in AMOP) were 
revised to include use of these functions then I'd have a portable way of 
writing satisfies-specializers.

SPECIALIZER-OBJECT (specializer-name)                       [Generic Function]
  This generic function returns the specializer object associated with
specializer-name. 
SPECIALIZER-OBJECT ((specializer-name symbol)                         [Method]
  This method calls (FIND-CLASS specializer-name).
SPECIALIZER-OBJECT ((specializer-name list))                          [Method]
  This method calls (TYPE-SPECIALIZER-OBJECT (CAR specializer-name) (CDR
specializer-name)). The value returned by TYPE-SPECIALIZER-OBJECT is the value
returned by this function.

TYPE-SPECIALIZER-OBJECT (type-specifier subsidiary-info)    [Generic Function]
  This generic function returns the specializer object associated with the
given type-specifier and its subsidiary-info.
TYPE-SPECIALIZER-OBJECT ((type-specifier (eql 'eql)) subsidiary-info  [Method]
  This method calls (INTERN-EQL-SPECIALIZER (CAR subsidiary-info)).
TYPE-SPECIALIZER-OBJECT ((type-specifier (eql 'satisfies))            [Method]
                         subsidiary-info)
  This method computes the satisfies-specializer object associated with the 
given subsidiary-info.
<<<<<<<<<[end of cite]


Hi Len;

   I think you've hit on a good area in which specialization could be
beefed up.  One thought occurred to me when wishing for more
specialization power of this sort a while back:

   Since the EQL specializer has its roots in the EQL type specifier,
why not allow specialization using any type specifier such as MEMBER,
OR, (INTEGER 5 10), etc.  EQL would become just one of many type
checking specializers which would conceivably even share the same
specializer metaobject.  This specializer might be named something
like TYPE-SPECIFIER-SPECIALIZER and would replace and subsume
EQL-SPECIALIZER.

   The implementation would simply call
(TYPEP <gen-fun-arg> <type-specifier>) during generic dispatch.  This
approach would eliminate the need for the TYPE-SPECIALIZER-OBJECT
generic function.

   Any further thoughts?  Perhaps I'm unaware of reasons for allowing
EQL-SPECIALIZER to be its own metaobject or any number of other things
;^>.


                                   Eric Peterson (speaking for myself)
                                   Systems Research and Applications
                                   2000 15th Street North
                                   Arlington, VA 22201
                                   USA
                                   peterson@sra.com
                                   (703) 558-7644
                                   Fax:  (703) 558-4723
Re: Extending syntax/semantics of method specializers
#554
Author: Fernando Mato Mira
Date: Mon, 23 Nov 1992 10:35
797 lines
26598 bytes
Here is a transcript of the suggestions related to the subject that I sent to the X3 committee.
Comments and corrections will be appreciated (especially on (3)). Tell me if you need more info.

Contents:
  (1) DEFCLASS-GENERIC-CLASSES (Necessary to understand (2))
  (2) DEFMETHOD-GENERIC-CLASSES (To the point)
  (3) TYPE-SPECIFIER-BY-ASSOCIATION (To the point, but inmature)

Appendixes:
  (4) TYPE-OF-FUNCTION
  (5) TYPE-FOR-METHODS

==============================================================================
Forum:	Objects
Issue:  DEFCLASS-GENERIC-CLASSES

References:   Draft 12.24: 7-61..65;50;1..11;30..34;88..89
              CLtL2: 822..826;775,781 

Related issues: TYPE-SPECIFIER-BY-ASSOCIATION
                DEFMETHOD-GENERIC-CLASSES

Category: ADDITION

Edit history: Mato Mira -- 19 Nov 1992
              

Problem description:

The current implemention of CLOS does not allow for the creation of generic
classes, that is, classes where slot types are determined by type parameters.
Under the current implementation, this inhibits the creation of type 
specifiers in the style of "(list integer)" for user-defined classes.

Proposal (DEFCLASS-GENERIC-CLASSES:EXTEND): 

ALTERNATIVE-1 : (DEFCLASS-GENERIC-CLASSES:EXTEND-FOR-TYPE-GENERICITY)
                Type genericity only (other parameters,e.g. size, not allowed)

DEFCLASS class-name ({superclass-spec}*) 				[Macro]
         ({slot-specifier}*) [[class-option]]

DEFCLASS class-name specialized-lambda-list ({superclass-spec}*) 	[Macro]
         ({slot-specifier}*) [[class-option]]

superclass-spec ::= restricted-class-spec
restricted-class-spec ::= class-spec\built-in-class-spec     
class-spec      ::= class-name | type-specifier
specialized-lambda-list ::= ({var|specialized-parameter}*)
specialized-parameter   ::= (var type-specifier)

Where the nonterminals not specified above are those found in CLtL2 822..826;839.
The addition of an optional parameter in a non-standard position enables 
backward compatibility of the extension with current programs. The semantics 
do not change in that case.

The new form creates a list type specifier for the class, according to the 
lambda list provided in the definition.

Class metaobjects should be created with an additional initialization argument:
:direct-lambda-list. 
A new generic function: class-direct-lambda-list should be implemented to 
access this information in class metaobjects.

MAKE-INSTANCE class &rest initargs	   	     	     [Generic function]
MAKE-INSTANCE (class standard-class) &rest initargs	       [Primary method]
MAKE-INSTANCE (class symbol) &rest initargs	               [Primary method]

The definition of MAKE-INSTANCE stays unchanged, except for the fact that the 
first initarg can be a list of arguments which must be congruent with the 
lambda list of the corresponding DEFCLASS, and where each element must be a 
type specifier denoting a subtype of the corresponding parameter of the 
previously mentioned lambda list.
Instance allocation functions should be recoded to enforce the bindings.
The bindings could be accesible in initialization functions in one of four ways:
 
1. By defining a keyword and passing a list containing the bindings as an 
  initarg.

2. By adding a required parameter to the specification of INITIALIZE-INSTANCE, etc.

3. By making the parameters bound in the dynamic environment.

4. By adopting DEFMETHOD-GENERIC-CLASSES
  


ALTERNATIVE-2 : (DEFCLASS-GENERIC-CLASSES:EXTEND-FOR-ALL-GENERICITIES)
                All genericities allowed

DEFCLASS class-name ({superclass-spec}*) 				[Macro]
         ({slot-specifier}*) [[class-option]]

DEFCLASS class-name specialized-lambda-list ({superclass-spec}*) 	[Macro]
         ({slot-specifier}*) [[class-option]]

superclass-spec         ::= restricted-class-spec
restricted-class-spec   ::= class-spec\built-in-class-spec     
class-spec              ::= class-name | type-specifier
specialized-lambda-list ::= ({var|specialized-parameter}*)
specialized-parameter   ::= (var type-specifier) | (var (type type-specifier))

When the parameter consists only of a variable, t is assumed as the 
corresponding type.
With this specification, a complete homogeneity with the built-in types
is obtained. Even arrays, supporing type specifiers of the form 
"(array integer 3)" can be programmed in this way.
This capability can be used to enforce required initargs for instances.


MAKE-INSTANCE class &rest initargs	   	     	     [Generic function]
MAKE-INSTANCE (class standard-class) &rest initargs	       [Primary method]
MAKE-INSTANCE (class symbol) &rest initargs	               [Primary method]

Where the nonterminals not specified above are those found in CLtL2 848
The definition of MAKE-INSTANCE stays unchanged, except for the fact that the 
first initarg can be a list of arguments which must be congruent with the 
lambda list of the corresponding DEFCLASS, and where each element must be an 
instance of the type associated to the corresponding parameter of the 
previously mentioned lambda list.
Instance allocation functions should be recoded to enforce the bindings.

Examples:

ALTERNATIVE-1

(DEFCLASS tree ((info-type t)) () 
	  ((info :accessor info :initarg :info 
		 :type info-type))
	  (children :accessor children :initarg :children 
		    :type (or nil (tree info-type))))

(DEFCLASS matrix-tree ((elem-type number)) ((tree (array elem-type (* *)))))

(DEFCLASS float-matrix-tree ((matrix-tree float)) ()     ; NO LAMBDA LIST HERE
          (:documentation "No problem with options thanks to atom"))  

(setf a-matrix (MAKE-INSTANCE 'matrix-tree (float) 
	       :info (make-array '(4 4) :element-type 'float
	       :initial-element 0.0)))
(defun foo (a)
  (declare (type (matrix-tree float) a))
  (let (x)
    (declare float x)
    (setf x (aref (info a) 0 0))))	; COULD BE COMPILED WITHOUT 2 TYPE CHECKS
                                       IF TYPE-SPECIFIER-BY-ASSOCIATON PASSES
ALTERNATIVE-2

(DEFCLASS tree ((info-type (type t))) () 
	  ((info :accessor info :initarg :info 
		 :type info-type))
	  (children :accessor children :initarg :children 
		    :type (or null (tree info-type))))

(DEFCLASS matrix-tree ((elem-type (type number)) 
		       (row-dim fixnum) (col-dim fixnum))
  ((tree (array elem-type (row-dim  col-dim)))) ()
  (:default-initargs :info (make-array `(,row-dim ,col-dim) 
				       :element-type elem-type
				       :initial-element 0.0)))


#! If DEFMETHOD-GENERIC-CLASSES approved

(DEFCLASS matrix-tree ((elem-type (type number)) 
		       (row-dim fixnum) (col-dim fixnum))
  ((tree (array elem-type (row-dim  col-dim)))) ())


(DEFMETHOD initialize-instance :after 
  ((instance (matrix-tree ?elem-type ?row-dim ?col-dim))         
   &key ((:initial-element init-elem 0 init-elem-specified-p)))
  (proclaim `(type ,?elem-type init-elem))  
  (with-slots (info)
      (if init-elem-specified-p
	(setf info (make-array `(,?row-dim ,?col-dim) 
				 :element-type ?elem-type
				 :initial-element init-elem))
	(setf info (make-array `(,?row-dim ,?col-dim) 
			       :element-type ?elem-type)))))
!#

(DEFCLASS float-matrix-tree ((row-dim fixnum) (col-dim fixnum))
  ((matrix-tree float row-dim col-dim)) ())

(DEFCLASS homogeneous-transform-tree	                  ; NO LAMBDA LIST HERE
  ((float-matrix-tree 4 4)) ())
   (:documentation "No problem with options thanks to atom"))  

(setf h-matrix (MAKE-INSTANCE 'matrix-tree (float 4 4))) 

(defun foo (a)
  (declare (type (matrix-tree float) a))
  (let (x)
    (declare float x)
    (setf x (aref (info a) 0 0))))    ; COULD BE COMPILED WITHOUT 2 TYPE CHECKS
                                        IF TYPE-SPECIFIER-BY-ASSOCIATON PASSES


Rationale:

Have a consistent type system capable of powerful declarations useful
for optimization and verification purposes.

Current practice:

No Common Lisp implementation works this way.
Generic classes are supported by other languages, such as Eiffel.

Cost to Implementors:

Minimal if declarations are ignored with respect to optimization.

Cost to Users:

None

Cost of non-adoption:

More burdensome and error-prone speed optimization and program verification 
process.

Performance impact:

It would allow compiler optimizations for speed.

Benefits:

No need to use risky 'safety 0' declarations improve performance.
Homogeneity of user defined classes and built-in classes type specifiers.
"Conventional" language users might take LISP more seriously.

Esthetics:

Improved.

Discussion:
==============================================================================
Forum:	Objects
Issue:  DEFMETHOD-GENERIC-CLASSES

References: Draft 12.24: 7-18..25;66..72  
            CLtL2: 826..842

Requires: DEFCLASS-GENERIC-CLASSES

Related issues: TYPE-SPECIFIER-BY-ASSOCIATION
                
Category:     ADDITION

Edit history: Mato Mira -- 19 Nov 1992

Problem description:

[See DEFCLASS-GENERIC-CLASSES for an introduction]
If DEFCLASS-GENERIC-CLASSES is approved, it would be possible to extend
method dispatching to discriminate according to specializations of the
type specifiers corresponding to generic classes.
This would also be the most elegant way of accessing specialization 
arguments in initialization functions.



Proposal (DEFMETHOD-GENERIC-CLASSES:EXTEND)                  [Macro]

DEFMETHOD function-name {method-qualifier}*
          specialized-lambda-list
          [[{declaration}* | doc-string]] {form}*

specialized-lambda-list ::= 
      ({var | (var parameter-specializer)}*
       [&optional {var | var [initform [supplied-p-parameter]])}* ]
       [&rest var]
       [&key {specialized-keyword-parameter}* [&allow-other-keys]]
       [&aux {var | (var [initform])}*])

parameter-specializer ::= symbol | (eql eql-specializer-form) | type-spec
type-spec ::= (symbol {specializer}*)
specializer ::= ?var | (?var parameter-specializer) | parameter-specializer

Where the nonterminals not specified above are those found in CLtL2 826..842
When using the form (?var parameter-specializer). IN THIS CASE, ALL THE OTHER 
UNRESTRICTED REFERENCES TO ?var ARE EXPANDED TO THE RESTRICTED FORM (including
those appearing in LIKE forms, if TYPE-SPECIFIER-BY-ASSOCIATION passes).
It is an error to specify two or more different restrictions for the same
variable.

Examples:

[see (DEFCLASS-GENERIC-CLASSES:EXTEND) for class definitions]

(DEFMETHOD initialize-instance :after 
  ((instance (matrix-tree ?elem-type ?row-dim ?col-dim))         
   &key ((:initial-element init-elem nil init-elem-specified-p)))
  (proclaim `(type ,?elem-type init-elem))  
  (with-slots (info)
      (if init-elem-specified-p
	(setf info (make-array `(,?row-dim ,?col-dim) 
				 :element-type ?elem-type
				 :initial-element init-elem))
	(setf info (make-array `(,?row-dim ,?col-dim) 
			       :element-type ?elem-type)))))

(DEFMETHOD initialize-instance :after 
  ((instance (matrix-tree (?elem-type real) ?row-dim ?col-dim))         
   &key ((:initial-element init-elem 0.0)))
  (proclaim `(type ,?elem-type init-elem))  
  (with-slots (info)
	(setf info (make-array `(,?row-dim ,?col-dim) 
				 :element-type ?elem-type
				 :initial-element init-elem)))) 

(DEFMETHOD initialize-instance :after 
  ((instance (matrix-tree float ?row-dim ?col-dim))         
   &key ((:initial-element init-elem 0.0)))
  (proclaim `(type ,?elem-type init-elem))  
  (with-slots (info)
	(setf info (make-array `(,?row-dim ,?col-dim) 
				 :element-type 'float
				 :initial-element init-elem))))


Rationale:

If generic classes are accepted, this extension increases expressive power
and elegance (except maybe for `?').

Current practice:

No lisp implementation works this way now.

Cost to Implementors:

Minor

Cost to Users:

None

Cost of non-adoption:

Loss of elegance.

Performance impact:

Dynamic method dispatching could be somewhat slower.

Benefits:

Expressive power augmented.
No need to change any specifications to pass class specialization arguments 
to initialization functions

Esthetics: 

Improved

Discussion:
===============================================================================
/////////////////////////////////////////////////////////////////////////////
THE FOLLOWING IS A FIRST APPROACH TO THE IDEA. IT IS BY NO MEANS A CLEANED UP
SPECIFICATION
/////////////////////////////////////////////////////////////////////////////

Forum:	Types & Declarations
Issue:  TYPE-SPECIFIER-BY-ASSOCIATION

References:   Draft 12.24: Section 4
              CLTL2:  49..68
               

Requires: TYPE-OF-FUNCTION
          TYPE-FOR-METHODS

Category:      ADDITION

Edit history:  Mato Mira -- 19 Nov 1992
               

Problem description:

The current implemention of Common Lisp and CLOS  donot allow for the 
declaration of types by association, that is, determined by the 
type of other LISP objects. This is much more problematic for CLOS 
methods.


Proposal: (TYPE-SPECIFIER-BY-ASSOCIATION:EXTEND)     (Alpha Version)

The symbol 'like' can be used as the car of a type specifier list, as follows:

(TYPE (LIKE object) var1 var2 ...)
Where object can be any LISP object.

(TYPE (LIKE (signature-accessor function) var1 var2 ...))
(TYPE (LIKE (signature-accessor method-type-with-variables function))
		  var1 var2 ...)

signature-accessor ::= VALUE | VALUE n | VALUES | 
                      PARAMETER n | OPTIONAL n | KEY keyword | AUX n

method-type-with-variables and  function are used in an TYPE-OF
expression with :general option to find the corresponding signature
(see TYPE-FOR-METHODS).

The value accessors have the obvious meanings, the PARAMETER accessor
can be used not only for required parameters, but also to access the type
of the default values provided for optional parameters. The OPTIONAL, KEY
and AUX accessors also serve to access the type of the default value of
the corresponding parameters (t if none).

Note that, if declarations are not ignored,
(proclaim `(TYPE ,(TYPE-OF object) var1 var2 ...))

differs from

(proclaim `(TYPE (LIKE object) var1 var2 ...))

in that the constraint should be mantained if the type of <object> changes
by calling UPDATE-INSTANCE-FOR-DIFFERENT-CLASS.	  
This is also true for function redefinitions when using FTYPE-OF in a 
declaration.

For completeness, it would be nice to be able to express type by asociation
in parameter specializers of methods.

Examples:

;;; The following can only be expressed by means of generic classes:
;;; See (DEFCLASS-GENERIC-CLASSES:EXTEND)

(defclass tree ((info-type t)) () 
  ((info :type info-type))
  (children :type (or nil (tree info-type))))

(defmethod info ((self tree))
  (slot-value self info))

;; Assuming the generation of:
;; (declaim (type (method ((tree ?typ) (eql 'info)) ?typ) #'slot-value))
;; 
;; Then it is possible to write:

(declaim
 (type 
  (method ((tree ?x)) 
	  (LIKE (value (method ((tree ?x) (eql 'info)) *) #'slot-value)))
  #'info))

;;Note the need of implementing slot-value with multi-methods for this to 
;;work.

;; An extension of the specification of DEFMETHOD to accept LIKE expressions
;; would enable a user to write:

(defmethod (setf info) 
    ((self (tree (?z t)))
     (val (like (value (method ((tree ?z)) *) #'info))))  ;; SEE NOTE[1]
  (setf (slot-value self) val))

NOTE[1] : Remember that the second ?z is expanded to (?z t) by DEFMETHOD
  (DEFMETHOD-GENERIC-CLASSES:EXTEND), and that FTYPE has expanded the second 
  ?typ to (?typ t) (FTYPE-FOR-METHODS:EXTEND), so the CADDR of the value 
  `returned' by the FTYPE-OF form AFTER SUBSTITUTION is the correct 
  expression `(?z t)

;; Many cases (like the one above) do not require that much expressive power,
;; so it would be nice to be able to write something like:

(defmethod (setf info) 
    ((self (tree (?z t)))
     (val (like (value (info tree)))))   
  (setf (slot-value self 'info) val))    

;; and for multiple-valued expressions:
(defmethod (setf n-infos) 
    ((self (multi-info-tree (?z t)))
     (val1 val2 ... valn (like (values (n-infos tree)))))
  ...)

Rationale:

Permit more precise declarations for users who need them. Improve 
theoretical purity of CLOS.

Current practice:

None in Common Lisp.
Supported in Eiffel (obvious generator of the idea). No dynamic constraints.

Cost to Implementors:

If not adopted in defmethod: Minor if declarations are ignored,  
                             small if redefinitions are ignored.

If adopted in defmethod (the most important context, actually):
  small to average (without redefinition support)

If type constraint maintenance supported:
  Average and up

Cost to Users:

None

Cost of non-adoption:

Higher cost of program modifications for users who make use of declarations.
Much worse in the case of CLOS programs.

Performance impact:

More specific declarations when using methods could improve it when using 
adecquate compilers.

Benefits:

Makes possible the use of more declarations, improving performance and program
verification with adecquate compilers.
Doesn't clash with the LISP philosophy, while at the same time promoting 
acceptance of LISP for "conventional" concerns.
Improved object-oriented programming methodology.

Esthetics:

Definitely subject to discussion

Discussion:

  "In the beginning, there was dynamically scoped LISP.
   Then somebody remembered lexical scoping and fixed it.
   Then structured programming and Pascal came, and LISP got a lot of new 
   toys, such as FLET.
   Object-oriented programming arrived, but, of course LISP programmers had 
   already used flavors for a long time, so they only made things neater when
   they adopted CLOS.
   A lot other more things happened, influenced by other languages (even some
   with few parentheses!!)
   Now some guy happened to be stuck programming for two years in the 
   non-higher-order language Eiffel, and to his surprise, he learned a couple
   of things about OO programming methodology. Back to LISP, happy to be able
   to use all the meta-power of CLOS, he finds that there are declarations he
   cannot make. And he needs every cycle of his computer when doing VR. He 
   can use unsafe declarations, of course, but why doing it when there is a 
   way to do it right?
   ...
   Like with Pascal, the LISP gurus hold their breadth, and adopted the idea.
   Of course they made sure that their way was more powerful than the original
   one..."

   Even if type declarations are optional in general, one cannot forget that 
   when programming methods one is explicity making use of them. While 
   maintaining the freedom of not being forced to declare anything, the 
   typing issue has acquired now a different dimension.

   This is a major non-trivial issue. A lot of discussion is required. This 
   is more an "idea generator" and a requirements list than a specification.
============================================================================
Forum:	Types & Declarations
Issue:  TYPE-OF-FUNCTION

References:    Draft 12.24: 4-37..38;         
	       CLtL2: 227..228

Related issues: TYPE-FOR-METHODS
                TYPE-SPECIFIER-BY-ASSOCIATION
	
Category:      ADDITION

Edit history:  Mato Mira -- 19 Nov 1992

Problem description:

Under the current specification of CL, there is no way to recover the 
signature of a function declared by means of FTYPE. This makes it 
impossible to implement types by association when the source of the 
specification is the type of an argument or of the result returned by a
function.
 
Proposal (TYPE-OF-FUNCTION:EXTEND)

  Make TYPE-OF return the complete signature of a function declared by means of
TYPE. 


TYPE-OF object						[Function]

Examples:

USER(1): (declaim (type (function (number) float) sin cos))
T
USER(2): (TYPE-OF #'cos)
(FUNCTION (number) float)

USER(2): (proclaim `(type ,(caddr (type-of #'cos)) some-var))
T

Rationale:

Type declarations are invertible, ftype declarations are not. Necessary for
meta-programming with types.

Current practice:

None that I know of.

Cost to Implementors:

Minimal

Cost to Users:

Code that depends on the result of calling type-of on a funcional object 
should be changed. 

Cost of non-adoption:

Impossibility of defining some powerful styles of declarations.

Performance impact:

None

Benefits:

More consistent language. Higher-order capabilities increased.

Esthetics:


Discussion:

  LISP is the language where "you can do anything" (and even efficiently). 
The current lack of support for this functionality goes against the 
philosophy of LISP.
==========================================================================
Forum:	Types & Declarations
Issue:  TYPE-FOR-METHODS

References:    Draft 12.24: 4/19..21;37..38          CLtL2: 227..228

Related issues: TYPE-SPECIFIER-BY-ASSOCIATION
		TYPE-OF-FUNCTION

Category:      ADDITION

Edit history:  Mato Mira -- 19 Nov 1992

Problem description:

Under the current specification of CL, there is no way to declare and
recover the type returned by a method. This makes it impossible to 
implement types by association when the source of the specification is 
the type of an argument or of the result returned by a method.
 
Proposal (TYPE-FOR-METHODS:EXTEND)

(TYPE method-type-spec method-name-1 method-name-2 ...)

method-type-spec  ::= (method-type ({type-spec}*) {type-spec}*)
Type-spec ::= (EQL form) | type-spec-with-vars
method-type ::= METHOD ...

where type-spec-with-variables are regular type specifiers or type 
specifiers where variables of the form ?var can be used to express 
interrelationships. They can also be restricted to be of a certain type 
by using the form (?var type-spec). IN THIS CASE, ALL THE OTHER UNRESTRICTED
REFERENCES TO ?var ARE EXPANDED TO THE RESTRICTED FORM.
It is an error to specify two or more different restrictions for the same
variable.

TYPE-OF object		                                    [Function]		
TYPE-OF method-type-with-variables function		    [Function]	
TYPE-OF method-type-with-variables function :general	    [Function]	
TYPE-OF method-type-with-variables function :strict	    [Function]	
	
where method-type-with-variables is a method-type where the CDR of the 
argument list or the  method-type-with-variables can also be replaced by 
variables to match all the remaining components of that part of the 
signature. The symbol '*' can be used as an anonymous variable.

The first form is explained in (TYPE-OF-FUNCTION:EXTEND) for the particular 
case of functions.
The second form returns a list of all the matching signatures declared 
for the methods of the generic function, including subtype relationships.
The third form returns the most general matching signature declared 
for the methods of the generic function, taking into account subtype 
relationships.
The fourth form returns a list of all the matching signatures declared 
for the methods of the generic function, without taking into account
subtypes.

EXTENSION:



IMPORTANT NOTE: Should be consistent with (DEFMETHOD-GENERIC-CLASSES:EXTEND), if
 both are accepted.

Examples:

USER(1): (declaim (TYPE (method (number) number) sin cos))
T
USER(2): (declaim (TYPE (method (complex) complex) sin cos))
T
USER(3): (declaim (TYPE (method (real) real) sin cos))
T
USER(4): (declaim (TYPE (method (float) float) sin cos))
T
USER(5): (TYPE-OF #'cos)
(CLOS:STANDARD-GENERIC-FUNCTION (number) number)

USER(6): (TYPE-OF '(method (number) number) #'cos :strict)
((CLOS:STANDARD-METHOD (number) number))

USER(7): (TYPE-OF '(method (t) *) #'cos)
((CLOS:STANDARD-METHOD (number) number)
 (CLOS:STANDARD-METHOD (complex) complex)
 (CLOS:STANDARD-METHOD (real) real) 
 (CLOS:STANDARD-METHOD (float) float))

USER(8): (TYPE-OF '(method (t) *) #'cos :strict)
NIL

USER(9): (TYPE-OF '(method (t) *) #'cos :general)
(CLOS:STANDARD-METHOD (number) number)


USER(10): (TYPE-OF '(method . *) #'cos)
((CLOS:STANDARD-METHOD (number) number)
 (CLOS:STANDARD-METHOD (complex) complex)
 (CLOS:STANDARD-METHOD (real) real)
 (CLOS:STANDARD-METHOD (float) float))

USER(11): (TYPE-OF '(method (*) real) #'cos)
((CLOS:STANDARD-METHOD (real) real) 
 (CLOS:STANDARD-METHOD (float) float))

USER(12): (TYPE-OF '(method (* . *) real) #'cos)
((CLOS:STANDARD-METHOD (real) real) 
 (CLOS:STANDARD-METHOD (float) float))

USER(13): (TYPE-OF '(method (*) real) #'cos :strict)
((CLOS:STANDARD-METHOD (real) real))

USER(14): (TYPE-OF '(method (float) . *) #'cos)
((CLOS:STANDARD-METHOD (float) float))

;;; GENERIC CLASS EXAMPLE - See (DEFCLASS-GENERIC-CLASSES:EXTEND)

USER(15) : (declaim (TYPE (method ((tree (?typ t)) (eql 'info)) ?typ) #'slot-value))
T
USER(16) : (TYPE-OF (method ((tree (?x t)) (eql 'info)) *) #'slot-value :general)
(CLOS:STANDARD-METHOD ((tree (?x t)) (eql 'info)) (?x t)) ;;NOTE THE SUBSTITUTION

Rationale:

Necessary for meta-programming with method signatures

Current practice:

None.

Cost to Implementors:

Minor.

Cost to Users:

None

Cost of non-adoption:

Impossibility of defining some powerful styles of declarations

Performance impact:

None

Benefits:

More consistent language. Higher-order capabilities increased.

Esthetics:


Discussion:


-- 
Fernando D. Mato Mira
Computer Graphics Lab
Swiss Federal Institute of Technology
matomira@di.epfl.ch

NeXTMail : matomira@lignext.epfl.ch
FAX 	 : +41 (21) 693 - 5328
Re: Extending syntax/semantics of method specializers
#556
Author: Len Charest
Date: Mon, 23 Nov 1992 19:21
22 lines
1741 bytes
In article <1992Nov23.113551@disun47.epfl.ch>, matomira@disun47.epfl.ch (Fernando Mato Mira) writes:

|> The current implemention of CLOS does not allow for the creation of generic
|> classes, that is, classes where slot types are determined by type parameters.
|> Under the current implementation, this inhibits the creation of type 
|> specifiers in the style of "(list integer)" for user-defined classes.
[  generic classes proposal deleted]

Generic classes would go a long way towards extending the expressiveness of
DEFMETHOD. However, they would not cover all of the discrimination strategies I
mentioned in my original post--especially the one I find most attractive: method
selection based on the *value* of a variable. To wit:

(defun interesting-value-p (x)
  (eq x *interesting-value*))

(defmethod observe ((thing (satisfies interesting-value-p)))
  ...)
..................................................
                                  Len Charest, Jr.
                 JPL Artificial Intelligence Group
                          charest@aig.jpl.nasa.gov
Re: Extending syntax/semantics of method specializers
#557
Author: Joe Konstan
Date: Mon, 23 Nov 1992 23:10
35 lines
2106 bytes
In article <1992Nov23.192133.10895@jpl-devvax.jpl.nasa.gov>, charest@Aig.Jpl.Nasa.Gov (Len Charest) writes:
|> Generic classes would go a long way towards extending the expressiveness of
|> DEFMETHOD. However, they would not cover all of the discrimination strategies
|> I mentioned in my original post--especially the one I find most attractive: 
|> method selection based on the *value* of a variable. To wit:
|> 
|> (defun interesting-value-p (x)
|>   (eq x *interesting-value*))
|> 
|> (defmethod observe ((thing (satisfies interesting-value-p)))
|>   ...)

Am I missing something here, or is this exactly what "eql" method specializers
are for?  Namely:

	(defmethod observer ((thing (eql *interesting-value*)))
          ...)

In fact, these can be combined nicely with macros for slot-value methods:

	(defmacro observer (object)
          `(real-observer (a-slot object) object))

        (defmethod real-observer ((sval (eql *interesting*)) (object itsclass))
         ...)

Now, I can see that extending this to an arbitrary predicate would be useful
(as has already been suggested), but I also see how easily this would
explode into a performance nightmare.  

Joe Konstan
konstan@cs.umn.edu

[for examples of using slot-value methods, and related constructs, see
 "Developing a GUIDE using object-oriented programming" in OOPSLA '91]
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads