什么是'参数化'不要在DrScheme?
-
18-09-2019 - |
解决方案
parameterize
是用有价值,是"动态范围".你会得到一个参与 make-parameter
.的参数本身行为作为一个功能:叫它没有输,你会得到它的价值,呼吁它与一个值和它将设置的价值。例如:
> (define p (make-parameter "blah"))
> (p)
"blah"
> (p "meh")
> (p)
"meh"
许多功能(包括许多原始的那些)使用的参数作为一种方式,以定制自己的行为。例如 printf
将打印的东西使用的港口,是值的 current-output-port
参数。现在,说你有一些功能打印一些东西:
> (define (foo x) (printf "the value of x is ~s\n"))
你通常称这个功能和看到的东西打印在屏幕上--但在某些情况下,你想要用它来打印一些东西到的文件或什么的。你可以这样做:
(define (bar)
(let ([old-stdout (current-output-port)])
(current-output-port my-own-port)
(foo some-value)
(current-output-port old-stdout)))
一个问题是,它是繁琐的做--但是,这是很容易地解决了一个宏。(事实上,专利法条约仍然有一个构造,这会在某些语言: fluid-let
.) 但是,还有更多的问题:会发生什么,如果电话来 foo
结果,在一个运行错误?这可能会使系统处于一个糟糕的状态,所有输出你的口(和你甚至不会看到一个问题,因为它会不会打印什么).一个解决方案(其中 fluid-let
使用过的)保护保存和恢复的参与 dynamic-wind
, ,这使得肯定的是,如果有一个错误(和更多,如果你知道约的延续),那么值仍然是恢复。
所以问题是什么样的参数,而不是只采用和globals fluid-let
?还有两个问题无法解决的只是globals.一个是什么时候会发生你有多线程--在这种情况下,设定价值的暂时将会影响其他线,这可能仍然想要印刷的标准输出。参解决这个由具有特定的价值每线。会发生什么情况是,每个线"继承"的价值从线,创造了它,并且改变一个线程是可见的,只有在该线。
其他问题更为微妙。说你有一个参数的数值,并且你想要做如下:
(define (foo)
(parameterize ([p ...whatever...])
(foo)))
在方案,"尾呼吁"是重要的--他们是基本的工具,用于创建循环等等。 parameterize
不会一些魔法,允许它改变的参数值的暂时但仍可保留这些尾的呼吁。例如,在上述情况下,您 将 获得一个无限循环,而不是得到一堆溢出错误-什么情况是,这些 parameterize
表可以以某种方式检测当有一个较早的 parameterize
不再需要完成其清理。
最后, parameterize
实际上使用的两个重要部分的血小板做的工作:它使用螺纹细胞实现每个线程的价值,它使用的延续标记可以保留尾巴-电话。这些特征的每一个很有用的本身。
其他提示
parameterize
设置特定参数为指定值的所述块的持续时间,而不影响它的外它们的值。
参数化是通过它可以动态地重新绑定的现有函数内的值,而无需使用lambda这样做的装置。在实践中,有时它是一个更容易使用参数化的函数内重新绑定值,而不是被要求来传递参数和使用lambda约束力。
举例来说,假设你使用一个库发出HTML到标准输出,但为方便起见,你要拍摄价值为字符串,并在其上执行进一步的操作。图书馆设计师至少有两个选择,使这容易让你:1)接受一个输出端口作为参数传递给函数或2)参数的电流输出端口值。图1是难看和麻烦。 2是更好的,因为最有可能的行为是打印到标准输出,但如果你要打印到一个字符串端口,你可以只是参数调用该函数。