Jump to content

Constrained genericity: Difference between revisions

entry for common lisp, with disclaimers
m (→‎{{header|C#}}: Fix header link)
(entry for common lisp, with disclaimers)
Line 123:
void eat(int) {}
}</lang>
 
=={{header|Common Lisp}}==
 
The task says that this task is only for statically typed languages, and Common Lisp is dynamically typed. However, there are many places where type declarations can be provided to the compiler, and there is user access to the type system (e.g., a user can ask whether an object is of a particular type). Via the latter mechanism, one could write a class containing a collection such that the insert method checked that the object to be inserted is of an appropriate type.
 
In this example, we define a class <code>food</code>, and two subclasses, <code>inedible-food</code> and <code>edible-food</code>. We define a generic function <code>eat</code>, and specialize it only for <code>edible-food</code>. We then define a predicate <code>eatable-p</code> which returns true only on objects for which <code>eat</code> methods have been defined. Then, using <code>[http://www.lispworks.com/documentation/HyperSpec/Body/m_deftp.htm deftype]</code> with a <code>[http://www.lispworks.com/documentation/HyperSpec/Body/t_satisf.htm satisfies]</code> type specifier, we define a type <code>eatable</code> to which only objects satisfying <code>eatable-p</code> belong. Finally, we define a function <code>make-food-box</code> which takes, in addition to typical array creation arguments, a type specifier. The array is declared to have elements of the type that is the intersection of <code>food</code> and the provided type. <code>make-eatable-food-box</code> simply calls <code>make-food-box</code> with the type <code>eatable</code>.
 
The only shortcoming here is that the compiler isn't required to enforce the type specifications for the arrays. A custom insert function, however, could remember the specified type for the collection, and assert that inserted elements are of that type.
 
<lang lisp>(defclass food () ())
 
(defclass inedible-food (food) ())
 
(defclass edible-food (food) ())
 
(defgeneric eat (foodstuff)
(:documentation "Eat the foodstuff."))
 
(defmethod eat ((foodstuff edible-food))
"A specialized method for eating edible-food."
(format nil "Eating ~w." foodstuff))
 
(defun eatable-p (thing)
"Returns true if there are eat methods defined for thing."
(not (endp (compute-applicable-methods #'eat (list thing)))))
 
(deftype eatable ()
"Eatable objects are those satisfying eatable-p."
'(satisfies eatable-p))
 
(defun make-food-box (extra-type &rest array-args)
"Returns an array whose element-type is (and extra-type food).
array-args should be suitable for MAKE-ARRAY, and any provided
element-type keyword argument is ignored."
(destructuring-bind (dimensions &rest array-args) array-args
(apply 'make-array dimensions
:element-type `(and ,extra-type food)
array-args)))
 
(defun make-eatable-food-box (&rest array-args)
"Return an array whose elements are declared to be of type (and
eatable food)."
(apply 'make-food-box 'eatable array-args))</lang>
 
=={{header|D}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.