使用带有自定义结构的内置数学运算符 [英] Using built-in math operators with custom struct
问题描述
我希望能够做这样的事情:
I want to be able to do something like this:
(struct point (x y))
(define p1 (point 1 2))
(define p2 (point 10 20))
(+ p1 p2) ; -> (point 11 22)
是否可以教像 point
这样的结构体使用像 +
这样的内置数学运算符?
Is it possible to teach a struct like point
to work with built-in math operators like +
?
文档似乎设法在 本页.我正在尝试做的非常相似......
The docs seem to manage to implement custom (equal? ...)
handling in section 5.5 on this page. What I'm trying to do is quite similar ...
或者我应该定义像 (point-add p1 p2)
这样的函数吗?
Or should I just define function like (point-add p1 p2)
?
推荐答案
您可以
- 使用
point-add
使用您自己的
+
匹配您想要采用的所有可能的值类型.如果您事先知道所有可能的值类型,这就足够了,但是扩展它以在客户端代码中包含新创建的结构定义并不容易.例如:
- Go with
point-add
Use your own
+
that matches against all possible value types that you want to take on. This is sufficient if you know all possible value types beforehand, but it wouldn't be easy to extend it to include newly created struct definitions in client's code. For example:
;; We will "shadow" Racket's + with our own +, but we still
;; need the functionality of Racket's +, so let's require
;; Racket's + but use the name racket:+ instead
(require (only-in racket/base [+ racket:+]))
(struct point (x y) #:transparent)
(define (+ x y)
(match* (x y)
[((point a b) (point c d)) (point (+ a c) (+ b d))]
[((point _ _) _) (error '+ "Can't add a point with non point")]
[(_ (point _ _)) (error '+ "Can't add a point with non point")]
[(_ _) (racket:+ x y)]))
;; in client's code
(+ (point 1 2) (point 3 4)) ;=> (point 4 6)
(+ 1 2) ;=> 3
定义一个新的泛型,以便我们可以对 equal?
执行类似于 gen:equal+hash
的操作.例如:
Define a new generics so that we can do something similar to gen:equal+hash
for equal?
. For example:
(require racket/generic
(only-in racket/base [+ racket:+]))
(define-generics addable
(add addable _)
#:fast-defaults ([number?
(define (add x y) (racket:+ x y))]))
(define + add)
;; in client's code
(struct point (x y)
#:transparent
#:methods gen:addable
[(define (add x y)
(match* (x y)
[((point a b) (point c d)) (point (+ a c) (+ b d))]
[(_ _) (error 'add "Can't add a point with non point")]))])
(struct point-3d (x y z)
#:transparent
#:methods gen:addable
[(define (add x y)
(match* (x y)
[((point-3d a b c) (point-3d d e f))
(point-3d (+ a d) (+ b e) (+ c f))]
[(_ _) (error '+ "Can't add a point-3d with non point-3d")]))])
(+ (point 1 2) (point 3 4)) ;=> (point 4 6)
(+ (point-3d 1 2 3) (point-3d 4 5 6)) ;=> (point-3d 5 7 9)
(+ 1 2) ;=> 3
要接受多个参数,将(3)修改如下
To accept multiple arguments, modify (3) as follows
(define +
(case-lambda
[() 0]
[(x . xs) (foldl add x xs)]))
;; client's code
(+ (point 1 2) (point 3 4) (point 5 6)) ;=> (point 9 12)
(+ 1 2 3) ;=> 6
(+) ;=> 0
(+ 1) ;=> 1
(+ (point-3d 1 2 3)) ;=> (point-3d 1 2 3)
这篇关于使用带有自定义结构的内置数学运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!