【问题标题】:Does racket allow for function overloading?球拍是否允许功能超载?
【发布时间】:2018-02-04 23:31:50
【问题描述】:

我是 Lisp-scheme 的新手,对整个函数式范式也很陌生,目前我正在做一个任务,要求我重载一个具有相同名称但在 racket 中具有不同参数集的函数。下面是我想要实现的一个示例:

#lang racket

(define (put-ball-in-box two-by-fours nails ball)
  ... )

(define (put-ball-in-box box ball)
  ... )

这些不是实际的功能,但足够接近。正如暗示的那样,这两个函数都会将一个球放入一个盒子中,但一个会首先从它的组件组装盒子,然后调用另一个。显然,当我在 DrRacket 中或使用命令行尝试上述操作时,我会收到 module: duplicate definition for identifier ... 错误。

有没有办法在racket 中实现这一点?

也许答案就在我面前,但我在过去的两个小时里一直在寻找这个,但找不到任何东西,所以不胜感激。

谢谢。

【问题讨论】:

标签: racket


【解决方案1】:

这不是通常意义上的“在其他地方写另一个定义”。

它允许映射,即定义一个与导入过程同名的过程。因此,您可以(define + ...) 并且您对+ 的定义将从racket/base 隐藏+。如果您想要原始过程,那么您可以执行以下操作,其中我将+ 定义为添加或字符串附加。

 #lang racket/base
 (require (rename-in racket/base (+ base:+)))

 (define (+ . args)
   (if (andmap string? args)
       (apply string-append args)
       (apply base:+ args)))

您可以做的另一件事是使用racket/match 根据参数的形状具有不同的行为。

#lang racket/base
(require racket/match)
(define (fib . arg)
  (match arg
   [(list n) (fib n 1 0)]
   [(list 1 a b) a]
   [(list 0 a b) b]
   [(list n a b) (fib (sub1 n) (+ a b) a)]))

第二个示例仍然不能完全满足您的要求,因为您必须转到原始定义点并修改 match 子句。但这可能足以满足您的目的。

一个更复杂的例子是使用自定义语法来创建define/overload 表单。但我认为您会发现racket/match 解决方案是最好的。

【讨论】:

  • 虽然我通常会像你一样写出来,但 FWIW 也有一些小方糖,如define/matchmatch-lambdamatch-lambda* 等。见docs.racket-lang.org/reference/…跨度>
  • 另请注意,case-lambda 的编译效率更高,但与match 相比,通用性较差。
【解决方案2】:

你有 JS 和 PHP 中默认值的概念:

(define (fib n (a 0) (b 1))
  (if (zero? n)
      a
      (fib (sub1 n) b (+ a b))))

(fib 10) ; ==> 55

现在,如果您有 5 个可选参数,您需要对它们进行排序,甚至传递一些值以便能够添加以后的参数。为避免这种情况,您可以使用关键字:

(define (test name #:nick [nick name] #:job [job "vacant"])
  (list name nick job))

(test "sylwester" #:job "programmer")
; ==> ("sylwester" "sylwester" "programmer")

现在 Racket 有课程了。你可以调用(send object method args ...)之类的方法。

(define circle%
  (class object%
    (super-new)
    (init-field radius)
    (define/public (area)
      (* radius radius 3.1415))))

(define cube%
  (class object%
    (super-new)
    (init-field side)
    (define/public (area)
      (* side side))))


(define circle (new circle% [radius 7]))
(define cube (new cube% [side 7]))

(map
 (lambda (o) (send o area))
 (list circle cube))
; ==> (153.9335 49)

请注意,这两个类并没有真正致力于与area 的联合接口,所以这是纯粹的鸭子类型。因此,您可以创建一个期望实现消息的类的函数,并且根本不需要担心该类的其他方面。

【讨论】:

  • 感谢您的回答。我测试了你的和生命法则的一个,实际上两者都有效,所以因为我不能同时接受这两个,根据these guidelines,我要支持你的,因为它也很有帮助,并接受法律- 为后代而活。
  • @claudiusbrout 出于好奇我添加了 OO。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 2019-07-31
  • 2014-03-08
相关资源
最近更新 更多