Racket编程指南——4 表达式和定义(三)

78 篇文章 16 订阅

4.4 lambda函数(过程)

一个lambda表达式创建一个函数。在最简单的情况,一个lambda表达式具有的表:

(lambda (arg-id ...)
  body ...+)

一个具有n个arg-id的lambda表接受n个参数:

> ((lambda (x) x)
   1)

1

> ((lambda (x y) (+ x y))
   1 2)

3

> ((lambda (x y) (+ x y))
   1)

#<procedure>: arity mismatch;

 the expected number of arguments does not match the given

number

  expected: 2

  given: 1

4.4.1 申明一个剩余(rest)参数

一个lambda表达式也可以有这种表:

(lambda rest-id
  body ...+)

也就是说,一个lambda表达式可以有一个没有被圆括号包围的单个rest-id。所得到的函数接受任意数量的参数,并且这个参数放入一个绑定到rest-id的列表:

Examples:

> ((lambda x x)
   1 2 3)

'(1 2 3)

> ((lambda x x))

'()

> ((lambda x (car x))
   1 2 3)

1

带有一个rest-id的函数经常使用apply函数调用另外的函数,它接受任意数量的参数。

apply函数》描述apply。

Examples:

(define max-mag
  (lambda nums
    (apply max (map magnitude nums))))
> (max 1 -2 0)

1

> (max-mag 1 -2 0)

2

lambda表还支持必需参数与一个rest-id组合:

(lambda (arg-id ...+ . rest-id)
  body ...+)

这个表的结果是一个函数,它至少需要与arg-id一样多的参数,并且还接受任意数量的附加参数。

Examples:

(define max-mag
  (lambda (num . nums)
    (apply max (map magnitude (cons num nums)))))
> (max-mag 1 -2 0)

2

> (max-mag)

max-mag: arity mismatch;

 the expected number of arguments does not match the given

number

  expected: at least 1

  given: 0

一个rest-id变量有时称为一个rest参数(rest argument),因为它接受函数参数的“剩余(rest)”。

4.4.2 声明可选(optional)参数

不只是一个标识,一个lambda表中的一个参数(不仅是一个剩余参数)可以用一个标识和一个缺省值指定:

(lambda gen-formals
  body ...+)
gen-formals=(arg ...)
|rest-id
|(arg ...+ . rest-id)
arg=arg-id
|[arg-id default-expr]

表的一个参数[arg-id default-expr]是可选的。当这个参数不在一个应用程序中提供,default-expr产生默认值。default-expr可以引用任何前面的arg-id,并且下面的每个arg-id也必须应该有一个默认值。

Examples:

(define greet
  (lambda (given [surname "Smith"])
    (string-append "Hello, " given " " surname)))
> (greet "John")

"Hello, John Smith"

> (greet "John" "Doe")

"Hello, John Doe"

(define greet
  (lambda (given [surname (if (equal? given "John")
                              "Doe"
                              "Smith")])
    (string-append "Hello, " given " " surname)))

> (greet "John")

"Hello, John Doe"

> (greet "Adam")

"Hello, Adam Smith"

4.4.3 声明关键字(keyword)参数

一个lambda表可以声明一个参数来通过关键字传递,而不是通过位置传递。关键字参数可以与位置参数混合,而且默认值表达式可以提供给两种参数:

关键字参数》介绍用关键字进行函数调用。

(lambda gen-formals
  body ...+)
gen-formals=(arg ...)
|rest-id
|(arg ...+ . rest-id)
arg=arg-id
|[arg-id default-expr]
|arg-keyword arg-id
|arg-keyword [arg-id default-expr]

由一个应用程序使用同一个arg-keyword提供一个参数指定为arg-keyword arg-id。关键字的位置——在参数列表中的标识序对与一个应用程序中的参数匹配并不重要,因为它将通过关键字而不是位置与一个参数值匹配。

(define greet
  (lambda (given #:last surname)
    (string-append "Hello, " given " " surname)))

> (greet "John" #:last "Smith")

"Hello, John Smith"

> (greet #:last "Doe" "John")

"Hello, John Doe"

一个arg-keyword [arg-id default-expr]参数指定一个带一个默认值的关键字参数。

Examples:

(define greet
  (lambda (#:hi [hi "Hello"] given #:last [surname "Smith"])
    (string-append hi ", " given " " surname)))
> (greet "John")

"Hello, John Smith"

> (greet "Karl" #:last "Marx")

"Hello, Karl Marx"

> (greet "John" #:hi "Howdy")

"Howdy, John Smith"

> (greet "Karl" #:last "Marx" #:hi "Guten Tag")

"Guten Tag, Karl Marx"

lambda表不直接支持创建一个接受“rest”关键字的函数。要构造一个接受所有关键字参数的函数,使用make-keyword-procedure函数。这个函数支持make-keyword-procedure通过最先的两个(按位置)参数中的并行列表接受关键字参数,然后来自一个应用程序的所有位置参数作为保留位置参数。

apply函数》介绍了keyword-apply。

Examples:

(define (trace-wrap f)
  (make-keyword-procedure
   (lambda (kws kw-args . rest)
     (printf "Called with ~s ~s ~s\n" kws kw-args rest)
     (keyword-apply f kws kw-args rest))))
> ((trace-wrap greet) "John" #:hi "Howdy")

Called with (#:hi) ("Howdy") ("John")

"Howdy, John Smith"

在《Racket参考》的“(lambda)”中提供了更多函数表达式的内容。

4.4.4 实参数量感知函数:case-lambda

case-lambda表创建一个函数,它可以根据提供的参数数量而具有完全不同的行为。一个case-lambda表达式有这样的表:

(case-lambda
  [formals body ...+]
  ...)
formals=(arg-id ...)
|rest-id
|(arg-id ...+ . rest-id)

每个[formals body ...+]类似于(lambda formals body ...+)。应用以case-lambda生成一个函数类似于应用一个lambda给匹配给定参数数量的第一种情况。

Examples:

(define greet
  (case-lambda
    [(name) (string-append "Hello, " name)]
    [(given surname) (string-append "Hello, " given " " surname)]))
> (greet "John")

"Hello, John"

> (greet "John" "Smith")

"Hello, John Smith"

> (greet)

greet: arity mismatch;

 the expected number of arguments does not match the given

number

  given: 0

一个case-lambda函数不能直接支持可选参数或关键字参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值