如何处理传递给Racket中函数的可变数量的参数?

Jam*_*val 4 scheme arguments list variadic-functions racket

我喜欢创建带有无限数量参数的函数,并能够将它们作为列表处理.在创建二叉树时,它对我很有用,我现在正在使用它来获取最近邻算法的变体.然而,我的方法非常糟糕:因为我无法想到迭代一个不正确的列表(可能是不正确和退化)的方法,我尝试使用各种列表函数强制将不正确的列表转换为列表形式.

这是我在一个简单的函数中最好的尝试,以确定地图节点之间的差异(工作,只是不知道它为什么工作):

(define distance-between
  (lambda xs
    (let ([input-list (list* xs null)])
      (letrec ([f (lambda (xs acc)
                    (if (null? (cdr xs))
                        acc
                        (f (cdr xs) (+
                                     (abs (- (map-node-x (car xs)) (map-node-x (cadr xs))))
                                     (abs (- (map-node-y (car xs)) (map-node-y (cadr xs))))
                                     acc))))])                   
       (f (car input-list) 0)))))
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,这是一个丑陋的解决方案,并涉及一些看似神奇的东西 - 为什么当我将它包含在列表中时,不正确的列表被强制转换为列表形式?(注意:这句话有误导性,不会发生这种情况).

我宁愿有一个漂亮的解决方案,没有魔力.有人可以帮忙吗?

例如,典型的输入是:

(distance-between (map-node 1 2) (map-node 2 3) (map-node 3 4))
Run Code Online (Sandbox Code Playgroud)

预期结果:

4
Run Code Online (Sandbox Code Playgroud)

(map-node(a)和mn(b)之间的距离为2,加上map-node(b)和map-node(c)之间的距离为2).

或者,可以简单地输入:

(distance-between (map-node 1 2) (map-node 2 2))
Run Code Online (Sandbox Code Playgroud)

并得到一个答案:

1
Run Code Online (Sandbox Code Playgroud)

如果我在原始输入上尝试这个,没有我的(let([input-list ...])...)语句,它会导致错误(?实际上不确定给出响应这个问题的原因).

该功能按预期工作.

Ósc*_*pez 8

作为可变参数列表接收的列表没有任何不当之处(意思是:变量数量的参数).例如:

(define test-list
  (lambda xs
    (length xs))) ; xs is a normal list, use it like any other list

(test-list 1 2 3 4)
=> 4
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,xs参数是一个普通的普通香草列表,没有什么不合适的.您可以像对任何其他列表一样迭代它.它没有必要car,它已经是一个列表了!另外,请注意可以像这样编写相同的函数:

(define (test-list . xs)
  (length xs))   ; xs is a normal list, use it like any other list
Run Code Online (Sandbox Code Playgroud)

仅供参考:不正确的列表是以空列表结尾的列表.例如:'(1 2 3 . 4).同样,这不是可变参数列表的外观.