如何在 Racket 中访问子结构变量 (Lisp/Scheme)
How to access sub-struct variables in Racket (Lisp/Scheme)
我正在尝试将 AM/PM 时钟转换函数编写为 24 小时制(军用时间),但是有一个结构和子结构具有我无法弄清楚如何提取的变量. 24HourClock-hours 或 AM/PM-hours 都无法从 AM/PM 时间实例中提取小时或分钟变量,该时间实例作为函数的两个版本中的每一个的参数。
以下两个函数是对同一函数的两次独立尝试:
(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)]))
这个尝试使用 lambda 函数访问子成员:
(define (AM/PM->24HourClock time)
(lambda (hr min meridiem)
(cond
[(isAM? time) (24HourClock (hr min))]
[else (24HourClock (+ hr 12) min)]))
但这是输出:
这是使其可重现的早期代码:
#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")))
应该是
(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)])))
但是由于 AM/PM-hours
和 AM/PM-minutes
没有像你在这里用 24HourClock
定义为超级 class 那样定义时,你必须写:
(define (AM/PM->24HourClock2 time)
(cond
[(isAM? time) (24HourClock (24HourClock-hours time) (24HourClock-minutes time))]
[else (24HourClock (+ (24HourClock-hours time) 12) (24HourClock-minutes time))]))
(define (AM/PM->24HourClock time)
(let ((hr (24HourClock-hours time))
(min (24HourClock-minutes time))
(mer (AM/PM-meridiem time)))
(cond
[(isAM? time) (24HourClock hr min)]
[else (24HourClock (+ hr 12) min)])))
你的问题是你认为struct-slot
本身就是struct中slot的值。但事实并非如此。它只是 struct
中 slot
的 getter 函数。因此,您必须执行 (struct-slot instance)
才能在类型为 struct
.
的 instance
中获取 slot
的值
如果你想要AM/PM->24HourClock
,那么time
就是AM/PM
的类型。
这是所有代码的组合,与您的回复和显示的内容相同:
#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")))
(define (AM/PM->24HourClock time)
(let ((hr (AM/PM-hours time))
(min (AM/PM-minutes time))
(cond
[(isAM? time) (24HourClock hr min)]
[else (24HourClock (+ hr 12) min)])))
这是我用于测试用例的内容:
;=======================
; Test Cases
;=======================
; (24HourClock 0 20)
; (24HourClock 24 20)
; (24HourClock 11 60)
; (AM/PM 0 20 "AM")
; (AM/PM 1 20 "Am")
; (AM/PM 2 20 "am")
; (is-AM? 2 20 "am")
; (AM/PM->24HourClock (AM/PM 0 10 "AM"))
; (AM/PM->24HourClock (AM/PM 12 10 "am"))
我正在尝试将 AM/PM 时钟转换函数编写为 24 小时制(军用时间),但是有一个结构和子结构具有我无法弄清楚如何提取的变量. 24HourClock-hours 或 AM/PM-hours 都无法从 AM/PM 时间实例中提取小时或分钟变量,该时间实例作为函数的两个版本中的每一个的参数。
以下两个函数是对同一函数的两次独立尝试:
(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)]))
这个尝试使用 lambda 函数访问子成员:
(define (AM/PM->24HourClock time)
(lambda (hr min meridiem)
(cond
[(isAM? time) (24HourClock (hr min))]
[else (24HourClock (+ hr 12) min)]))
但这是输出:
这是使其可重现的早期代码:
#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")))
应该是
(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)])))
但是由于 AM/PM-hours
和 AM/PM-minutes
没有像你在这里用 24HourClock
定义为超级 class 那样定义时,你必须写:
(define (AM/PM->24HourClock2 time)
(cond
[(isAM? time) (24HourClock (24HourClock-hours time) (24HourClock-minutes time))]
[else (24HourClock (+ (24HourClock-hours time) 12) (24HourClock-minutes time))]))
(define (AM/PM->24HourClock time)
(let ((hr (24HourClock-hours time))
(min (24HourClock-minutes time))
(mer (AM/PM-meridiem time)))
(cond
[(isAM? time) (24HourClock hr min)]
[else (24HourClock (+ hr 12) min)])))
你的问题是你认为struct-slot
本身就是struct中slot的值。但事实并非如此。它只是 struct
中 slot
的 getter 函数。因此,您必须执行 (struct-slot instance)
才能在类型为 struct
.
instance
中获取 slot
的值
如果你想要AM/PM->24HourClock
,那么time
就是AM/PM
的类型。
这是所有代码的组合,与您的回复和显示的内容相同:
#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")))
(define (AM/PM->24HourClock time)
(let ((hr (AM/PM-hours time))
(min (AM/PM-minutes time))
(cond
[(isAM? time) (24HourClock hr min)]
[else (24HourClock (+ hr 12) min)])))
这是我用于测试用例的内容:
;=======================
; Test Cases
;=======================
; (24HourClock 0 20)
; (24HourClock 24 20)
; (24HourClock 11 60)
; (AM/PM 0 20 "AM")
; (AM/PM 1 20 "Am")
; (AM/PM 2 20 "am")
; (is-AM? 2 20 "am")
; (AM/PM->24HourClock (AM/PM 0 10 "AM"))
; (AM/PM->24HourClock (AM/PM 12 10 "am"))