[plt-scheme] "appending" to classes rather than extending

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Wed Mar 5 17:53:42 EST 2008

Let's do it with modules:

(module foo mzscheme
   (require scheme/class)
   (provide foo%)

   (define foo%
     (class object% (init-field count)
       (super-new)
       (define/public (bar)
         (if (<= count 0)
             (printf "done\n")
             (begin
               (printf "bar\n")
               (set! count (- count 1))
               (send this baz)))))))

(module foo-extended scheme
   (require scheme/class
            'foo)
   (provide (rename-out (foo-extended% foo%)))

   (define foo-extended%
     (class foo% (inherit-field count)
       (super-new)
       (define/public (baz)
         (if (<= count 0)
             (printf "done\n")
             (begin
               (printf "baz\n")
               (set! count (- count 1))
               (send this bar)))))))

(require 'foo-extended)
(send (new foo% [count 4]) bar)

This uses inheritance to simulate appending. Do you like this better?  
-- Matthias






On Mar 5, 2008, at 5:36 PM, Rob Hunter wrote:

> Yeah, seems to just work in Ruby (see code below).
>
> It seems strange to me that I can't just "re-export" the definition  
> of foo:
>
> (define-unit extension-unit%
>   (import sig^)
>   (export sig^)
>
>   (define (bar)
>     "appended bar impl"))
>
> But unfortunately? it gives me:
>
> define-unit: import foo is exported in: (define-unit extension-unit%
> (import sig^) (export sig^) (define (bar) "appended bar impl"))
>
> Here's that Ruby code:
>
> class Foo
>   def initialize(count)
>     @count = count
>   end
>
>   def bar
>     if @count <= 0
>       print "done\n"
>     else
>       print "bar\n"
>       @count = @count - 1
>       baz
>     end
>   end
> end
>
> class Foo
>   def baz
>     if @count <= 0
>       print "done\n"
>     else
>       print "baz\n"
>       @count = @count - 1
>       bar
>     end
>   end
> end
>
> Foo.new(4).bar =>
> bar
> baz
> bar
> baz
> done
>
>
>
>
> On Wed, Mar 5, 2008 at 2:25 PM, Matthias Felleisen  
> <matthias at ccs.neu.edu> wrote:
>>
>>  Yes. Since you want to talk about both base:bar and extension:bar in
>>  one unit, I don't see how to do it w/o some name shuffling.
>>
>>  BTW, happens if the foo and bar methods are (mutually) recursive in
>>  Ruby. Does this "just work"?
>>
>>  -- Matthias
>>
>>
>>
>>
>>
>>
>>
>>
>>  On Mar 5, 2008, at 4:51 PM, Rob Hunter wrote:
>>
>>> Thanks, Matthias.  Below is my interpretation of your suggestion of
>>> using units to get this effect.  The only parts of my solution  
>>> that I
>>> don't like is how I had to prefix the import in extension-unit%, and
>>> how I had to explicitly define foo for export even though I didn't
>>> want to override it.  Surely there's a way to avoid both of those
>>> things...
>>>
>>> Thanks,
>>> Rob
>>>
>>> (define-signature sig^ (foo bar))
>>>
>>> (define-unit base-unit%
>>>   (import)
>>>   (export sig^)
>>>
>>>   (define (foo)
>>>     "foo base impl")
>>>
>>>   (define (bar)
>>>     "bar base impl"))
>>>
>>> (define-unit extension-unit%
>>>   (import (prefix base: sig^))
>>>   (export sig^)
>>>
>>>   (define foo base:foo)
>>>
>>>   (define (bar)
>>>     "appended bar impl"))
>>>
>>> (define-compound-unit merged-unit%
>>>   (import)
>>>   (export RESULT)
>>>   (link [((BASE : sig^)) base-unit%]
>>>         [((RESULT : sig^)) extension-unit% BASE]))
>>>
>>>
>>> REPL interaction:
>>>> (define-values/invoke-unit merged-unit% (import) (export sig^))
>>>> (foo)
>>> "foo base impl"
>>>> (bar)
>>> "appended bar impl"
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Wed, Mar 5, 2008 at 12:58 PM, Matthias Felleisen
>>> <matthias at ccs.neu.edu> wrote:
>>>>
>>>>  You could achieve this kind of effect (via units) but re- 
>>>> definitions
>>>>  in a module (and that's what this boils down to) of the same name
>>>> are
>>>>  frowned upon in Scheme. -- Matthias
>>>>
>>>>  P.S. Re-definitions at the top-level have been around for a LONG
>>>> time
>>>>  and there is a reason why Schemers are moving away from that
>>>> approach.
>>>>
>>>>
>>>>
>>>>  On Mar 5, 2008, at 3:41 PM, Rob Hunter wrote:
>>>>
>>>>> Hi all,
>>>>>
>>>>> I'm looking to be able to append a few methods to a class.  In
>>>>> Ruby, I
>>>>> can do something like this:
>>>>>
>>>>> class Foo
>>>>>   def bar
>>>>>     ...
>>>>>   end
>>>>>   ...
>>>>> end
>>>>>
>>>>> class Foo
>>>>>   def baz
>>>>>     ...
>>>>>   end
>>>>> end
>>>>>
>>>>> and both bar and baz will be a part of Foo (these two class defs
>>>>> could
>>>>> be in the same file, or in two different files that are both
>>>>> loaded).
>>>>> Anything like this in the PLT Scheme class system?
>>>>>
>>>>> Thanks,
>>>>> Rob
>>>>> _________________________________________________
>>>>>   For list-related administrative tasks:
>>>>>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>>>>
>>>>
>>
>>



Posted on the users mailing list.