(define (country-population/area this)  (/ (this 'population) (this    'area      )))
(define (country-gdp/population  this)  (/ (this 'gdp       ) (this    'population)))
(define (country-area> this another  )  (> (this 'area      ) (another 'area      )))

(define (new-country gdp area population)
  (letrec
    (
    (this.props
      (list
        (cons 'gdp            gdp                    )
        (cons 'area           area                   )
        (cons 'population     population             )
        (cons 'density        country-population/area)
        (cons 'gdp-per-capita country-gdp/population )
        (cons 'is-bigger      country-area>          )
      )
    )
    (this
      (lambda (operation . args)
        (case operation
          ((set!)
            (let
              ((pair (assq (car args) this.props)))
              (if pair (set-cdr! pair (cadr args)))
              (car args)
            )
          )
          ((get)
            (let
              ((pair (assq (car args) this.props)))
              (if pair (cdr pair) (if (null? (cdr args)) #f (cadr args)))
            )
          )
          (else
            (set! operation (assq operation this.props))
            (if operation
              (begin
                (set! operation (cdr operation))
                (if (procedure? operation) (apply operation (cons this args)) operation)
              )
            "Invalid Option"
            )
          )
        )
      )
    )
    )
    this
  )
)

(define make-country-mp new-country)

; ------------------------------------------------------------------------------

(define Country-A (make-country-mp 1 10 20))
(define Country-B (make-country-mp 2500 5000 50))

(display "gdp           : ") (display (Country-B 'gdp                )) (newline)
(display "area          : ") (display (Country-B 'area               )) (newline)
(display "population    : ") (display (Country-B 'population         )) (newline)
(display "density       : ") (display (Country-A 'density            )) (newline)
(display "gdp-per-capita: ") (display (Country-B 'gdp-per-capita     )) (newline)
(display "is-bigger     : ") (display (Country-B 'is-bigger Country-A)) (newline)
(newline)
(display "get 'gdp     : ") (display (Country-B 'get 'gdp    )) (newline)
(display "set! 'gdp 12 : ") (display (Country-B 'set! 'gdp 12)) (newline)
(display "get 'gdp     : ") (display (Country-B 'get 'gdp    )) (newline)
(display "get 'area    : ") (display (Country-B 'get 'area   )) (newline)
(display "get 'density : ") (display (Country-B 'get 'density)) (newline)
(display "get 'Joey    : ") (display (Country-B 'get 'Joey   )) (newline)
(display "get 'Joey 'u : ") (display (Country-B 'get 'Joey 'u)) (newline)