Search code examples
structschemeracketuser-defined-types

Scheme struct with another struct


I'm trying to learn scheme (drracket) by myself and I encountered a problem.

I'm trying to work with different shapes such as circles , squares and rectangles. The task is the following:

"Define the types "circle", "square" and "rectangle" and define the main-type "shape". I need the shape struct for the next part of the task where I have to define a function "area-of-shape" which gets a "shape"databundle and which is supposed to represent the area of any given shape.

Here is what I have so far:

(define-struct square (nw lenght))

(define-struct circle (center radius))

(define-struct rectangle (nw width height))

(define-struct shape (...))



(define (area-of-shape shapeA)
  (cond 
    [(square? (shapeA)) (* (square-lenght shapeA) (square-lenght shapeA))]
    [(circle? (shapeA)) (* 3.14 (* (circle-radius shapeA) (circle-radius shapeA)))]
    [(rectangle? (shapeA)) (* (rectangle-width shapeA) (rectangle-height shapeA))]))

How do I define the struct shape? I tried something like

(define-struct shape (circle square rectangle))

But that wouldn't make any sense since the struct would need all 3 shapes.

Any help would be appreciated.


Solution

  • Racket structs can inherit from another struct. So:

    #lang racket
    
    (struct shape ())
    (struct square shape (nw length))
    (struct circle shape (center radius))
    (struct rectangle shape (nw width height))
    
    (define (area-of-shape shape)
      (if (shape? shape)
        (cond
          [(square? shape)    (* (square-length shape) (square-length shape))]
          [(circle? shape)    (* 3.14 (* (circle-radius shape) (circle-radius shape)))]
          [(rectangle? shape) (* (rectangle-width shape) (rectangle-height shape))]
          [else (error 'area-of-shape "Unhandled Shape Condition.")])
        (error 'area-of-shape "Argument not a Shape.")))
    
    ;; Example uses
    (area-of-shape (square 0 10))
    (area-of-shape (circle 0 10))
    (area-of-shape (rectangle 0 10 10))
    

    By the way, for something like area-of-shape, I find it handier to use match than cond:

    (define (area-of-shape shape)
      (match shape
        [(square _ len)    (* len len)]
        [(circle _ rad)    (* 3.14 (* rad rad))]
        [(rectangle _ w h) (* w h)]))