Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to access sub-struct variables in Racket (Lisp/Scheme)

I’m trying to write an AM/PM clock conversion function to a 24 hour clock (military time), but there’s a struct and sub-struct that have variables I can’t figure out how to pull. Neither 24HourClock-hours or AM/PM-hours is working to pull the hours or minutes variable out of the AM/PM instance of time that goes as the parameter of each of the two versions of the function.

The following two functions are two separate attempts at the same function:

(define (AM/PM->24HourClock2 time)
  (cond
   [(isAM? time) (24HourClock (24HourClock-hours 24HourClock-minutes))]
   [else (24HourClock (+ 24HourClock-hours 12) 24HourClock-minutes)]))
(define (AM/PM->24HourClock time)
  (cond
   [(isAM? time) (24HourClock (AM/PM-hours AM/PM-minutes))]
   [else (24HourClock (+ AM/PM-hours 12) AM/PM-minutes)]))

This one attempts to use a lambda function to access the sub-members:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

(define (AM/PM->24HourClock time)
  (lambda (hr min meridiem)
    (cond
      [(isAM? time) (24HourClock (hr min))]
      [else (24HourClock (+ hr 12) min)]))

But here’s the output:

output

Here’s the earlier code that makes it reproducible:

#lang slideshow

(struct 24HourClock (hours minutes)
  #:transparent
  #:mutable
  #:guard (lambda (hours minutes err_name)
    (if (not (and (>= hours 0) (< hours 24)))
     (error err_name "Hours must be between 0 and 24")
    (if (not (and (>= minutes 0) (< minutes 60)))
     (error err_name "Minutes must be between 0 and 60")
    (values hours minutes)))))

(struct AM/PM 24HourClock (meridiem)
  #:transparent
  #:mutable
  #:guard (lambda (hours minutes meridiem err_name)
            (if (not(and(and(number? hours)(> hours 0)(<= hours 12)(number? minutes))))
                (error err_name "Hours must be between 1 and 12 : 0")
                    (if [not (and(string? meridiem)(or
                         (equal? meridiem "am")
                         (equal? meridiem "AM")
                         (equal? meridiem "pm")
                         (equal? meridiem "PM")))]                    
                    (error err_name "Invalid value for meridiem")
                    (values hours minutes meridiem)))))
       
 (define (isAM? time)
    (or (equal? (AM/PM-meridiem time) "AM")
        (equal? (AM/PM-meridiem time) "am")))

>Solution :

It should be rather

(define (AM/PM->24HourClock2 time)
  (cond
   [(isAM? time) (24HourClock (AM/PM-hours time) (AM/PM-minutes time))]
   [else (24HourClock (+ (AM/PM-hours time) 12) (AM/PM-minutes time))]))

(define (AM/PM->24HourClock time)
  (let ((hr (AM/PM-hours time))
        (min (AM/PM-minutes time))
        (mer (AM/PM-meridiem time)))
    (cond
      [(isAM? time) (24HourClock hr min)]
      [else (24HourClock (+ hr 12) min)])))

Your problem is that you think struct-slot is itself the value of slot in struct. But it isn’t. It is just the getter function for the slot in struct. Therefore, you have to do (struct-slot instance) to get the value of slot in the instance which is of the type struct.

If you want AM/PM->24HourClock, then time is of the type AM/PM.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading