Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Methods and properties in scheme: is OOP possible in Scheme?

Tags:

oop

scheme

racket

I will use a simple example to illustrate my question. In Java, C, or any other OOP language, I could create a pie class in a way similar to this:

class Apple{
    public String flavor;
    public int pieces;
    private int tastiness;
    public goodness(){
        return tastiness*pieces;
    }
}

What's the best way to do that with Scheme? I suppose I could do with something like this:

(define make-pie
  (lambda (flavor pieces tastiness)
    (list flavor pieces tastiness)))

(define pie-goodness
  (lambda (pie)
    (* (list-ref pie 1) (list-ref pie 2))))

(pie-goodness (make-pie 'cherry 2 5))

;output: 10

...where cherry is the flavor, 2 is the pieces, and 5 is the tastiness. However then there's no type-safety or visibility, and everything's just shoved in an unlabeled list. How can I improve that?

Sidenote: The make-pie procedure expects 3 arguments. If I want to make some of them optional (like I'd be able to in curly-brace languages like Java or C), is it good practice to just take the arguments in as a list (that is treat the arguments as a list - not require one argument which is a list) and deal with them that way?


Update:

I've received a couple answers with links to various extensions/libraries that can satisfy my hunger for OOP in scheme. That is helpful, so thank you.

However although I may not have communicated it well, I'm also wondering what the best way is to implement the pie object above without such classes or libraries, so I can gain a better understanding of scheme best practices.

like image 799
Cam Avatar asked Dec 13 '22 21:12

Cam


1 Answers

In some sense, closures and objects are equivalent, so it's certainly possible. There are a heaping helping of different OO systems for Scheme -- a better question might be which one to use!

On the other hand, if this is an educational exercise, you could even roll your own using the closure-object equivalency. (Please forgive any errors, my Scheme is rather rusty.)

(define (make-pie flavor pieces tastiness)
        (lambda (selector)
                (cond ((eqv? selector 'flavor) flavor)
                      ((eqv? selector 'pieces) pieces)
                      ((eqv? selector 'tastiness) tastiness)
                      ((eqv? selector 'goodness) (* pieces tastiness))
                      (else '()))))

This is a simple constructor for a pie object. The parameter variables flavor, pieces and tastiness are closed over by the lambda expression, becoming fields of the object, and the first (and for simplicity's sake here, only) argument to the closure is the method selector.

That done, you can instantiate and poke at some:

> (define pie1 (make-pie "rhubarb" 8 4))
> (define pie2 (make-pie "pumpkin" 6 7))
> (pie1 'flavor)
"rhubarb"
> (pie1 'goodness)
32
> (pie2 'flavor)
"pumpkin"
like image 170
Jeffrey Hantin Avatar answered May 23 '23 08:05

Jeffrey Hantin