如何在球拍的正方形内找到一个点?
How to find a point within a square in racket?
目前,我正在努力找出一个函数,该函数可以确定一个点是否在正方形中,或者不给定正方形的边长和左上角。
; tl is a Posn, giving the top-left corner of the square
; side is a Number, giving the side length of the square
(define-struct SQ (tl side))
(define z (make-SQ tl side))
(define x (+ (posn-x SQ-tl z) (SQ-side z)))
(define y (+ (posn-y SQ-tl z) (SQ-side z)))
(define a (make-posn x y))
; Posn, SQ -> Boolean
(define (point-in-square? P S) (and (<= (posn-x P) (posn-x a) S)
(>= (posn-x P) (posn-x (SQ-tl z)) S)
(<= (posn-y P) (posn-y a) S)
(>= (posn-y P) (posn-y (SQ-tl z)) S)))
我收到错误 tl: undefined; cannot reference undefined identifier
我该如何解决这个错误?
最初的问题导致错误,例如:tl: undefined; cannot reference undefined identifier
。在构造正方形 z
的调用中,构造函数 make-SQ
被调用,参数为 tl
和 side
;但尚未为这些标识符分配任何值。 OP 似乎在使用它们,因为它们是插槽名称;构造函数需要适当的值来分配给槽。这里的解决方案只是认识到实际 SQ
实例的构造需要具体值。
越过第一个障碍就清楚地表明 point-in-square?
谓词的定义存在问题。该定义试图使用全局定义的 z
正方形和 a
点。但是这个过程还需要 P
和 S
参数,分别是一个点和一个正方形。这是解决问题所需的全部信息。
在评论中解决了 OP 的问题后,OP 已经解决了这些问题,使代码可以正常工作。这是一个替代解决方案,它使用 let*
使代码更易于阅读和思考:
#lang racket
(define-struct posn (x y))
(define-struct SQ (tl side))
(define (point-in-square? P S)
(let* ((top-left (SQ-tl S))
(side-length (SQ-side S))
(left (posn-x top-left))
(right (+ left side-length))
(top (posn-y top-left))
(bottom (+ top side-length)))
(and (<= (posn-x P) right)
(>= (posn-x P) left)
(<= (posn-y P) bottom)
(>= (posn-y P) top))))
以及 REPL 交互示例:
point-in-square.rkt> (define test-square (make-SQ (make-posn 4 2) 1))
point-in-square.rkt> (define p1 (make-posn 5 3)) ; in square
point-in-square.rkt> (define p2 (make-posn 5 2)) ; on edge of square
point-in-square.rkt> (define p3 (make-posn 5 1)) ; not in square
point-in-square.rkt> (point-in-square? p1 test-square)
#t
point-in-square.rkt> (point-in-square? p2 test-square)
#t
point-in-square.rkt> (point-in-square? p3 test-square)
#f
请注意,let
对于将计算中使用的值绑定到有意义的名称很有用;在这种情况下,let*
很方便,因为它允许我们在后续绑定中使用以前以相同 let*
形式绑定的值。另一种方法是嵌套 let
表单,以便内部 let
可以使用外部绑定。
目前,我正在努力找出一个函数,该函数可以确定一个点是否在正方形中,或者不给定正方形的边长和左上角。
; tl is a Posn, giving the top-left corner of the square
; side is a Number, giving the side length of the square
(define-struct SQ (tl side))
(define z (make-SQ tl side))
(define x (+ (posn-x SQ-tl z) (SQ-side z)))
(define y (+ (posn-y SQ-tl z) (SQ-side z)))
(define a (make-posn x y))
; Posn, SQ -> Boolean
(define (point-in-square? P S) (and (<= (posn-x P) (posn-x a) S)
(>= (posn-x P) (posn-x (SQ-tl z)) S)
(<= (posn-y P) (posn-y a) S)
(>= (posn-y P) (posn-y (SQ-tl z)) S)))
我收到错误 tl: undefined; cannot reference undefined identifier
我该如何解决这个错误?
最初的问题导致错误,例如:tl: undefined; cannot reference undefined identifier
。在构造正方形 z
的调用中,构造函数 make-SQ
被调用,参数为 tl
和 side
;但尚未为这些标识符分配任何值。 OP 似乎在使用它们,因为它们是插槽名称;构造函数需要适当的值来分配给槽。这里的解决方案只是认识到实际 SQ
实例的构造需要具体值。
越过第一个障碍就清楚地表明 point-in-square?
谓词的定义存在问题。该定义试图使用全局定义的 z
正方形和 a
点。但是这个过程还需要 P
和 S
参数,分别是一个点和一个正方形。这是解决问题所需的全部信息。
在评论中解决了 OP 的问题后,OP 已经解决了这些问题,使代码可以正常工作。这是一个替代解决方案,它使用 let*
使代码更易于阅读和思考:
#lang racket
(define-struct posn (x y))
(define-struct SQ (tl side))
(define (point-in-square? P S)
(let* ((top-left (SQ-tl S))
(side-length (SQ-side S))
(left (posn-x top-left))
(right (+ left side-length))
(top (posn-y top-left))
(bottom (+ top side-length)))
(and (<= (posn-x P) right)
(>= (posn-x P) left)
(<= (posn-y P) bottom)
(>= (posn-y P) top))))
以及 REPL 交互示例:
point-in-square.rkt> (define test-square (make-SQ (make-posn 4 2) 1))
point-in-square.rkt> (define p1 (make-posn 5 3)) ; in square
point-in-square.rkt> (define p2 (make-posn 5 2)) ; on edge of square
point-in-square.rkt> (define p3 (make-posn 5 1)) ; not in square
point-in-square.rkt> (point-in-square? p1 test-square)
#t
point-in-square.rkt> (point-in-square? p2 test-square)
#t
point-in-square.rkt> (point-in-square? p3 test-square)
#f
请注意,let
对于将计算中使用的值绑定到有意义的名称很有用;在这种情况下,let*
很方便,因为它允许我们在后续绑定中使用以前以相同 let*
形式绑定的值。另一种方法是嵌套 let
表单,以便内部 let
可以使用外部绑定。