使用带有自定义结构的内置数学运算符 [英] Using built-in math operators with custom struct

查看:46
本文介绍了使用带有自定义结构的内置数学运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够做这样的事情:

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)?

推荐答案

您可以

  1. 使用 point-add
  2. 使用您自己的 + 匹配您想要采用的所有可能的值类型.如果您事先知道所有可能的值类型,这就足够了,但是扩展它以在客户端代码中包含新创建的结构定义并不容易.例如:

  1. Go with point-add
  2. 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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆