我是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
?
也许答案就在我的面前,但是我花了最后两个小时来寻找这个并且找不到任何东西,所以会很感激任何指针。
谢谢。
答案 0 :(得分:3)
它不是通常意义上的“在其他地方写另一个定义”。
它允许阴影,它定义一个与导入过程同名的过程。因此,您(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
解决方案是最好的。
答案 1 :(得分:3)
您有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
的联合接口,因此这是纯粹的鸭子类型。因此,您可以创建一个期望实现消息的类的函数,并且根本不需要担心该类的其他方面。