Scheme - 可选参数和默认值

4

我目前正在研究Scheme,根据我的理解,过程可以接受任意数量的参数。

我一直在尝试着玩弄这个功能,但是我还无法完全理解它。

例如,假设我想根据用户提供的信息编写欢迎消息。

如果用户提供了名字和姓氏,则程序应该输出:

Welcome, <FIRST> <LAST>!
;; <FIRST> = "Julius", <LAST>= "Caesar"
Welcome, Julius Caesar!

否则,程序应该参考一个默认值,该默认值指定为:
Welcome, Anonymous Person!

我有以下代码大纲,但不知道如何最终完成。
(define (welcome . args)
  (let (('first <user_first>/"Anonymous")
        ('last <user_last>/"Person"))
    (display (string-append "Welcome, " first " " last "!"))))

使用示例:

(welcome) ;;no arguments
--> Welcome, Anonymous Person!
(welcome 'first "John") ;;one argument
--> Welcome, John Person!
(welcome 'first "John" 'last "Doe") ;;two arguments
--> Welcome, John Doe!

任何帮助都非常感激!

2个回答

6
在Racket中,实现这一功能的方法是使用关键字参数。您可以在声明参数时使用#:关键字 参数-id定义带有关键字参数的函数:
(define (welcome #:first first-name #:last last-name)
  (display (string-append "Welcome, " first-name " " last-name "!")))

您可以这样调用:
> (welcome #:first "John" #:last "Doe")
Welcome, John Doe!

然而,您想要让它们变成可选项。为此,您可以在参数声明中编写#:keyword [argument-id default-value]
(define (welcome #:first [first-name "Anonymous"] #:last [last-name "Person"])
  (display (string-append "Welcome, " first-name " " last-name "!")))

所以,如果您在某个函数调用中未使用该关键字,则会填充默认值。
> (welcome)
Welcome, Anonymous Person!
> (welcome #:first "John")
Welcome, John Person!
> (welcome #:first "John" #:last "Doe")
Welcome, John Doe!
> (welcome #:last "Doe" #:first "John")
Welcome, John Doe!

这个函数不接受任意数量的参数。 - Zelphir Kaltstahl
3
我本意不是要让它接受任意数量的参数;如果你需要这样,可以写成(define (welcome #:first 名字 #:last 姓氏 . 其他参数) ...) - Alex Knauth

3

@Alex Knauth的回答非常好。那是我不知道的事情。

这里有一个替代方案,虽然它不太灵活。

(define (welcome (first "Anonymous") (last "Person"))
  (displayln (string-append "Welcome, " first " " last "!")))

这与您的基本要求非常匹配。
> (welcome)
Welcome, Anonymous Person!
> (welcome "John")
Welcome, John Person!
> (welcome "John" "Doe")
Welcome, John Doe!

然而,Alex的解决方案有两个显著的优点。

  1. 参数可以以任意顺序调用
  2. 可以指定姓氏而不必指定名字

2
你可以通过定义 (define welcome (lambda args (string-append "欢迎," (or (assq-ref args 'first) "匿名") " " (or (assq-ref args 'last) "用户")))) 并调用 (welcome '(first . "John") '(last . "Doe")) 来改进你的答案。 - Michael Vehrs
2
你应该将这作为另一个答案提交到问题中。这是一个不错的选择,但如果我想要给参数加关键字,我可能会使用Alex的解决方案。感谢分享 ^_^ - Mulan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接