[racket] question about classes

From: Joe Gilray (jgilray at gmail.com)
Date: Sun May 20 11:02:07 EDT 2012

Hi Matt,

Thanks, what you wrote makes perfect sense (of course... that's what I get
for programming at such hours!)

Anyway, working code included below and the main purpose of learning about
classes in Racket helped along the way.

To take a step back and look at what I've "accomplished" in this exercise:

1) I was able to re-use the rational-rep code in gencontfrac% which was the
main intent.
2) rational-rep calls expand-repeat which in the base class calls a
client-provided function called repeat, in the sqrtcontfrac% subclass
expand-repeat uses a list called repeatlst instead of the function
3) in sqrtcontfrac% repeat is set to #<void>.   The is-a relationship is
not honored by what I've done.

Questions:
1)  Is what I've done an abomination?  Am I simply abusing inheritance?
2)  To make the code below work, I had to make expand-repeat public as I
couldn't override a private function.  Is there another way (something like
"protected" in C++)?

Thanks again!
-Joe


(module contfrac racket
  (require racket/class)
  (provide gencontfrac%)
  (provide sqrtcontfrac%)

  ; class that represents the continued fraction of a general irrational
number and acts as a base class for continued fractions of other sorts
  (define gencontfrac%
    (class object%
      (super-new)
      (init-field start)
      (init-field repeat)
      ; create a n-long list of repeat digits (in reverse order - which
makes creation of a rational easier)
      (define/public (expand-repeat n)
        (let lp ([c n] [rl '()])
          (if (zero? c) rl (lp (sub1 c) (cons (repeat) rl)))))
      ; create a rational representation using the passed number of repeat
digits
      (define/public (rational-rep n)
        (define rdiglst (expand-repeat n))
        (let lp ([rdigs (rest rdiglst)] [res (first rdiglst)])
          (if (empty? rdigs) (+ start (/ 1 res)) (lp (rest rdigs) (+ (first
rdigs) (/ 1 res))))))
      ; display the continued fraction
      (define/public (show)
        (printf "[~a; ~a]~n" start repeat))
      ))

  ; define a class that represents the continued fraction of a square root
  (define sqrtcontfrac%
    (class gencontfrac%
      (init sqrval)
      (define repeatlst (build-repeatlst sqrval))
      (super-new [start (integer-sqrt sqrval)] [repeat (void)])
      (inherit rational-rep show)
      (inherit-field start)
      ; build the repeating sequence (see
http://en.wikipedia.org/wiki/Continued_fraction)
      (define/private (build-repeatlst n)
        (define start (integer-sqrt n))
        (let loop ([adder start] [denom (- n (sqr start))] [result '()])
          (cond [(zero? denom) '()]  ; perfect square
                [(= 1 denom) (reverse (cons (+ (integer-sqrt n) adder)
result))] ; found the end of the repeating sequence
                [else
                 (let* ([nextval (quotient (+ adder start) denom)] [nextadd
(- (* nextval denom) adder)])
                   (loop nextadd (quotient (- n (sqr nextadd)) denom) (cons
nextval result)))])))
      ; create a n-long list of repeat digits (in reverse order - which
makes creation of a rational easier)
      (define/override (expand-repeat n)
        (let lp ([c n] [rl '()] [stock repeatlst])
          (if (zero? c) rl (lp (sub1 c) (cons (first stock) rl) (if (empty?
(rest stock)) repeatlst (rest stock))))))
      ; accessor
      (define/public (get-repeatlst) repeatlst)
      ))
  )


On Sun, May 20, 2012 at 6:49 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:

> The problem is that `start' doesn't get a value for a `sqrtcontfrac%'
> instance until `super-new' in `sqrtcontfrac%' is evaluated. But the
> expression for the second argument in `super-new' calls `build-repeat',
> so that `build-repeat' tries to use `start' before it has a value.
>
> I'm not sure of the solution in this case, but it might be to pass the
> value for `start' into `build-repeat' instead of trying to get the
> value from the `start' field within `build-repeat'.
>
> At Sun, 20 May 2012 02:06:35 -0700, Joe Gilray wrote:
> > I'm trying to learn to use classes in Racket.  I did some successful
> simple
> > experiments then moved on to inheritance.  When I try to use the code
> > below, the following code:
> >
> > (new sqrtcontfrac% [sqrval i])  leads to the message: sqr: expected
> > argument of type <number>; given #<undefined>
> >
> > Why isn't start being inherited properly?  Any help is appreciated!
> >
> > Thanks,
> > -joe
> >
> > Here is the class code:
> >
> > (module contfrac racket
> >   (require racket/class)
> >   (provide gencontfrac%)
> >   (provide sqrtcontfrac%)
> >
> >   ; class that represents the continued fraction of a general irrational
> > number and acts as a base class for continued fractions of other sorts
> >   (define gencontfrac%
> >     (class object%
> >       (super-new)
> >       (init-field start) *; here start is defined*
> >       (init-field repeat)
> >       ; create a n-long list of repeat digits (in reverse order - which
> > makes creation of a rational easier)
> >       (define/private (expand-repeat n)
> >         (let lp ([c n] [rl '()])
> >           (if (zero? c) rl (lp (sub1 c) (cons (repeat) rl)))))
> >       ; create a rational representation using the passed number of
> repeat
> > digits
> >       (define/public (rational-rep n)
> >         (define rdiglst (expand-repeat n))
> >         (let lp ([rdigs (rest rdiglst)] [res (first rdiglst)])
> >           (if (empty? rdigs) (+ start (/ 1 res)) (lp (rest rdigs) (+
> (first
> > rdigs) (/ 1 res))))))
> >       ; display the continued fraction
> >       (define/public (show)
> >         (printf "[~a; ~a]~n" start repeat))
> >       ))
> >
> >   ; define a class that represents the continued fraction of a square
> root
> >   (define sqrtcontfrac%
> >     (class gencontfrac%
> >       (init sqrval)
> >       (super-new [start (integer-sqrt sqrval)] [repeat (build-repeat
> > sqrval)])
> >       (inherit rational-rep show)
> >       (inherit-field start repeat)
> >       ; build the repeating sequence (see
> > http://en.wikipedia.org/wiki/Continued_fraction)
> >       (define/private (build-repeat n)
> >         (let loop ([adder start] [denom (- n (sqr start))] [result '()])
> *;
> > this is where the error is occurring *
> >           (cond [(zero? denom) '()]  ; perfect square
> >                 [(= 1 denom) (reverse (cons (+ start adder) result))] ;
> > found the end of the repeating sequence
> >                 [else
> >                  (let* ([nextval (quotient (+ adder (integer-sqrt n))
> > denom)] [nextadd (- (* nextval denom) adder)])
> >                    (loop nextadd (quotient (- n (sqr nextadd)) denom)
> (cons
> > nextval result)))])))
> >       ; create a n-long list of repeat digits (in reverse order - which
> > makes creation of a rational easier)
> >       (define/private (expand-repeat n)
> >         (let lp ([c n] [rl '()] [stock repeat])
> >           (if (zero? c) rl (lp (sub1 c) (cons (first stock) rl) (if
> (empty?
> > (rest stock)) repeat (rest stock))))))
> >       ))
> >   )
> > ____________________
> >   Racket Users list:
> >   http://lists.racket-lang.org/users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120520/235b036b/attachment-0001.html>

Posted on the users mailing list.