From: Ron Garret on
In article <7nvrpuF3nupc4U1(a)mid.individual.net>,
Pascal Costanza <pc(a)p-cos.net> wrote:

> Ron Garret wrote:
> > In article <7ntfj7F3m9fjiU1(a)mid.individual.net>,
> > Pascal Costanza <pc(a)p-cos.net> wrote:
> >
> >> Filtered functions are an extension of generic functions, extended with
> >> a filtering step where the arguments received by a generic function are
> >> mapped to other values based on user-defined mapping functions. Those
> >> filtered values are then used to perform the actual selection and
> >> execution of applicable methods. Nevertheless, the methods that are
> >> eventually executed see the original objects as received by the generic
> >> function, and not the filtered ones.
> >
> > I like this concept, but is there a reason you designed the API the way
> > you did instead of simply providing a facility for subclassing built-in
> > classes? In other words, why not simply do:
> >
> > (def-subclass positive-integer integer 'plusp)
> >
> > (defmethod factorial ((n positive-integer)) ...)
> >
> > That would seem to me to provide the same functionality, and would make
> > code using this feature easier to write and debug.
>
> Maybe this would work for this particular example (but factorial is
> really not that interesting now, is it? ;).
>
> Just check the other examples as well, I don't think you could solve
> them that easily.

Obviously factorial is not the definitive test case, but I'm pretty sure
that the two APIs are formally equivalent. Is there a particular
example that you think could not be easily rendered in terms of
def-subclass?

rg
From: Pascal Costanza on
Ron Garret wrote:
> In article <7nvrpuF3nupc4U1(a)mid.individual.net>,
> Pascal Costanza <pc(a)p-cos.net> wrote:
>
>> Ron Garret wrote:
>>> In article <7ntfj7F3m9fjiU1(a)mid.individual.net>,
>>> Pascal Costanza <pc(a)p-cos.net> wrote:
>>>
>>>> Filtered functions are an extension of generic functions, extended with
>>>> a filtering step where the arguments received by a generic function are
>>>> mapped to other values based on user-defined mapping functions. Those
>>>> filtered values are then used to perform the actual selection and
>>>> execution of applicable methods. Nevertheless, the methods that are
>>>> eventually executed see the original objects as received by the generic
>>>> function, and not the filtered ones.
>>> I like this concept, but is there a reason you designed the API the way
>>> you did instead of simply providing a facility for subclassing built-in
>>> classes? In other words, why not simply do:
>>>
>>> (def-subclass positive-integer integer 'plusp)
>>>
>>> (defmethod factorial ((n positive-integer)) ...)
>>>
>>> That would seem to me to provide the same functionality, and would make
>>> code using this feature easier to write and debug.
>> Maybe this would work for this particular example (but factorial is
>> really not that interesting now, is it? ;).
>>
>> Just check the other examples as well, I don't think you could solve
>> them that easily.
>
> Obviously factorial is not the definitive test case, but I'm pretty sure
> that the two APIs are formally equivalent. Is there a particular
> example that you think could not be easily rendered in terms of
> def-subclass?

Yes, the other two examples in the paper. Especially the interpreter,
but also the state example. I actually want to experiment with state
being dynamically scoped such that you can have behavior depend on
particular special variables. In conjunction with special slots in
ContextL this means that it should be possible to have context-dependent
object-specific behavior - something which is currently not possible
with ContextL.

Maybe you can express such things with class hierarchies, but I don't
think that's convenient. In fact, what ContextL already provides is
implemented by creating now class metaobjects on the fly internally, but
I don't you'd want to create the resulting hierarchy by hand.

I cannot prove at the moment that filtered functions are strictly more
convenient than manual class hierarchies, but please read on...


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza on
Raffael Cavallaro wrote:
>
> Finally, if the two of you (i.e., Kenny and Pascal C.) can stop
> bickering for a moment, you'd realize that a dataflow framework and a
> predicate dispatch framework together (with a little macro syntactic
> sugar) would allow completely declarative programming.
>

I'm curious: How do you see them used in combination?


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Ron Garret on
In article <7nvteeF3mopq6U1(a)mid.individual.net>,
Pascal Costanza <pc(a)p-cos.net> wrote:

> Ron Garret wrote:
> > In article <7nvrpuF3nupc4U1(a)mid.individual.net>,
> > Pascal Costanza <pc(a)p-cos.net> wrote:
> >
> >> Ron Garret wrote:
> >>> In article <7ntfj7F3m9fjiU1(a)mid.individual.net>,
> >>> Pascal Costanza <pc(a)p-cos.net> wrote:
> >>>
> >>>> Filtered functions are an extension of generic functions, extended with
> >>>> a filtering step where the arguments received by a generic function are
> >>>> mapped to other values based on user-defined mapping functions. Those
> >>>> filtered values are then used to perform the actual selection and
> >>>> execution of applicable methods. Nevertheless, the methods that are
> >>>> eventually executed see the original objects as received by the generic
> >>>> function, and not the filtered ones.
> >>> I like this concept, but is there a reason you designed the API the way
> >>> you did instead of simply providing a facility for subclassing built-in
> >>> classes? In other words, why not simply do:
> >>>
> >>> (def-subclass positive-integer integer 'plusp)
> >>>
> >>> (defmethod factorial ((n positive-integer)) ...)
> >>>
> >>> That would seem to me to provide the same functionality, and would make
> >>> code using this feature easier to write and debug.
> >> Maybe this would work for this particular example (but factorial is
> >> really not that interesting now, is it? ;).
> >>
> >> Just check the other examples as well, I don't think you could solve
> >> them that easily.
> >
> > Obviously factorial is not the definitive test case, but I'm pretty sure
> > that the two APIs are formally equivalent. Is there a particular
> > example that you think could not be easily rendered in terms of
> > def-subclass?
>
> Yes, the other two examples in the paper. Especially the interpreter,
> but also the state example. I actually want to experiment with state
> being dynamically scoped such that you can have behavior depend on
> particular special variables. In conjunction with special slots in
> ContextL this means that it should be possible to have context-dependent
> object-specific behavior - something which is currently not possible
> with ContextL.
>
> Maybe you can express such things with class hierarchies, but I don't
> think that's convenient.

Well, here's how I'd do it:

(defun make-filter (key-function expected-result)
(lambda (thing) (eq (funcall key-function thing) expected-result)))

(def-subclass regular-stack stack (make-filter 'stack-state 'normal))

(def-subclass full-stack stack (make-filter 'stack-state 'full))

(def-subclass empty-stack stack (make-filter 'stack-state 'empty))

(defmethod stack-whatever ((stack regular-stack) ...) ...)
(defmethod stack-whatever ((stack empty-stack) ...) ...)
(defmethod stack-whatever ((stack full-stack) ...) ...)

And the EVAL example:

(defun make-form-type-checker (spec)
(lambda (form) (eq (car form) spec)))

(def-subclass quote-form cons (make-filter 'car 'quote))
(def-subclass lambda-form cons (make-filter 'car 'lambda))
etc...

(defmethod eval ((form quote-form)) form)
(defmethod eval ((form lambda-form)) (make-closure ...))

Seems pretty convenient to me.

rg
From: Pascal Costanza on
Ron Garret wrote:
> In article <7nvteeF3mopq6U1(a)mid.individual.net>,
> Pascal Costanza <pc(a)p-cos.net> wrote:
>
>> Ron Garret wrote:
>>> In article <7nvrpuF3nupc4U1(a)mid.individual.net>,
>>> Pascal Costanza <pc(a)p-cos.net> wrote:
>>>
>>>> Ron Garret wrote:
>>>>> In article <7ntfj7F3m9fjiU1(a)mid.individual.net>,
>>>>> Pascal Costanza <pc(a)p-cos.net> wrote:
>>>>>
>>>>>> Filtered functions are an extension of generic functions, extended with
>>>>>> a filtering step where the arguments received by a generic function are
>>>>>> mapped to other values based on user-defined mapping functions. Those
>>>>>> filtered values are then used to perform the actual selection and
>>>>>> execution of applicable methods. Nevertheless, the methods that are
>>>>>> eventually executed see the original objects as received by the generic
>>>>>> function, and not the filtered ones.
>>>>> I like this concept, but is there a reason you designed the API the way
>>>>> you did instead of simply providing a facility for subclassing built-in
>>>>> classes? In other words, why not simply do:
>>>>>
>>>>> (def-subclass positive-integer integer 'plusp)
>>>>>
>>>>> (defmethod factorial ((n positive-integer)) ...)
>>>>>
>>>>> That would seem to me to provide the same functionality, and would make
>>>>> code using this feature easier to write and debug.
>>>> Maybe this would work for this particular example (but factorial is
>>>> really not that interesting now, is it? ;).
>>>>
>>>> Just check the other examples as well, I don't think you could solve
>>>> them that easily.
>>> Obviously factorial is not the definitive test case, but I'm pretty sure
>>> that the two APIs are formally equivalent. Is there a particular
>>> example that you think could not be easily rendered in terms of
>>> def-subclass?
>> Yes, the other two examples in the paper. Especially the interpreter,
>> but also the state example. I actually want to experiment with state
>> being dynamically scoped such that you can have behavior depend on
>> particular special variables. In conjunction with special slots in
>> ContextL this means that it should be possible to have context-dependent
>> object-specific behavior - something which is currently not possible
>> with ContextL.
>>
>> Maybe you can express such things with class hierarchies, but I don't
>> think that's convenient.
>
> Well, here's how I'd do it:
>
> (defun make-filter (key-function expected-result)
> (lambda (thing) (eq (funcall key-function thing) expected-result)))
>
> (def-subclass regular-stack stack (make-filter 'stack-state 'normal))
>
> (def-subclass full-stack stack (make-filter 'stack-state 'full))
>
> (def-subclass empty-stack stack (make-filter 'stack-state 'empty))
>
> (defmethod stack-whatever ((stack regular-stack) ...) ...)
> (defmethod stack-whatever ((stack empty-stack) ...) ...)
> (defmethod stack-whatever ((stack full-stack) ...) ...)
>
> And the EVAL example:
>
> (defun make-form-type-checker (spec)
> (lambda (form) (eq (car form) spec)))
>
> (def-subclass quote-form cons (make-filter 'car 'quote))
> (def-subclass lambda-form cons (make-filter 'car 'lambda))
> etc...
>
> (defmethod eval ((form quote-form)) form)
> (defmethod eval ((form lambda-form)) (make-closure ...))
>
> Seems pretty convenient to me.

Can you provide a definition for def-subclass?

Do you need to use change-class? When is change-class triggered?


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14
Prev: [ANN] Filtered functions
Next: Filtered functions.