- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在研究具有深/浅绑定(bind)的动态/静态作用域,并手动运行代码以了解这些不同的作用域/绑定(bind)实际上是如何工作的。我阅读了理论并在谷歌上搜索了一些示例练习,我发现这些练习非常简单(例如 this one 这对动态作用域非常有帮助)但是我无法理解静态作用域的工作原理。
在这里,我发布了一个练习,以检查我是否获得了正确的解决方案:
考虑以下用伪代码编写的程序:
int u = 42;
int v = 69;
int w = 17;
proc add( z:int )
u := v + u + z
proc bar( fun:proc )
int u := w;
fun(v)
proc foo( x:int, w:int )
int v := x;
bar(add)
main
foo(u,13)
print(u)
end;
屏幕上打印的内容
a) 使用静态作用域?答案=180
b) 使用动态作用域和深度绑定(bind)?答案=69(u的总和=126,但它是foo的本地v,对吧?)
c) 使用动态作用域和浅绑定(bind)? answer=69(u 的总和 = 101,但它是 foo 的本地 v,对吧?)
PS:我正在尝试做一些这样的练习,如果你知道我在哪里可以找到这些类型的问题(最好有解决方案),请提供链接,谢谢!
最佳答案
您对词法(静态)范围的回答是正确的。您对动态范围的回答是错误的,但如果我正确地阅读了您的解释,那是因为您在 u
和 v
之间感到困惑,而不是因为对深度和浅层绑定(bind)的工作原理。 (我假设您的 u
/v
混淆只是偶然的,而不是由于对 foo< 的调用中的值与引用的奇怪混淆
。)
a) using static scope? answer=180
正确。
b) using dynamic scope and deep binding? answer=69 (sum for u = 126 but it's foo's local v, right?)
您的括号解释是正确的,但您的答案是错误的:u
确实设置为126
,并且foo
确实本地化了 v
,但由于 main
打印 u
,而不是 v
,所以答案是 126
。
c) using dynamic scope and shallow binding? answer=69 (sum for u = 101 but it's foo's local v, right?)
u
的总和实际上是 97
(42+13+42
),但由于 bar
本地化u
,答案是42
。 (您的括号解释对此是错误的 - 您似乎在解释语句 int u := w 时使用了全局变量
在 w
,即 17
bar
的定义中;但该语句实际上引用了 foo
的局部变量 w
,它的第二个参数,即13
。但这实际上并不影响答案。您的答案对于这个答案是错误的,只是因为 main
打印 u
,而不是 v
。)
对于词法范围,通过将伪代码翻译成具有词法范围的语言来检查您的答案非常容易。同样具有浅绑定(bind)的动态作用域。 (事实上,如果您使用 Perl,您几乎可以同时测试这两种方式,因为它支持这两种方式;只需使用 my
作为词法范围,然后执行查找和替换将其更改为 local
表示动态作用域。但是,即使您使用 JavaScript 表示词法作用域,使用 Bash 表示动态作用域,也应该可以快速测试两者。)
具有深度绑定(bind)的动态作用域要棘手得多,因为很少有广泛部署的语言支持它。如果您使用 Perl,则可以通过使用从变量名映射到标量引用的哈希(关联数组)并将此哈希从一个函数传递到另一个函数来手动实现它。在伪代码声明局部变量的任何地方,您都将现有的标量引用保存在 Perl 词法变量中,然后将新的映射放入哈希中;在函数结束时,恢复原始标量引用。为了支持绑定(bind),您可以创建一个包装函数,该函数创建哈希的副本,并将该传递给其包装函数。下面是使用该方法在 Perl 中动态范围、深度绑定(bind)的程序实现:
#!/usr/bin/perl -w
use warnings;
use strict;
# Create a new scalar, initialize it to the specified value,
# and return a reference to it:
sub new_scalar($)
{ return \(shift); }
# Bind the specified procedure to the specified environment:
sub bind_proc(\%$)
{
my $V = { %{+shift} };
my $f = shift;
return sub { $f->($V, @_); };
}
my $V = {};
$V->{u} = new_scalar 42; # int u := 42
$V->{v} = new_scalar 69; # int v := 69
$V->{w} = new_scalar 17; # int w := 17
sub add(\%$)
{
my $V = shift;
my $z = $V->{z}; # save existing z
$V->{z} = new_scalar shift; # create & initialize new z
${$V->{u}} = ${$V->{v}} + ${$V->{u}} + ${$V->{z}};
$V->{z} = $z; # restore old z
}
sub bar(\%$)
{
my $V = shift;
my $fun = shift;
my $u = $V->{u}; # save existing u
$V->{u} = new_scalar ${$V->{w}}; # create & initialize new u
$fun->(${$V->{v}});
$V->{u} = $u; # restore old u
}
sub foo(\%$$)
{
my $V = shift;
my $x = $V->{x}; # save existing x
$V->{x} = new_scalar shift; # create & initialize new x
my $w = $V->{w}; # save existing w
$V->{w} = new_scalar shift; # create & initialize new w
my $v = $V->{v}; # save existing v
$V->{v} = new_scalar ${$V->{x}}; # create & initialize new v
bar %$V, bind_proc %$V, \&add;
$V->{v} = $v; # restore old v
$V->{w} = $w; # restore old w
$V->{x} = $x; # restore old x
}
foo %$V, ${$V->{u}}, 13;
print "${$V->{u}}\n";
__END__
实际上它打印了126
。这显然很困惑且容易出错,但它也确实可以帮助您了解正在发生的事情,因此出于教育目的,我认为这是值得的!
关于具有深/浅绑定(bind)的动态/静态范围(练习),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3869040/
免责声明 这篇文章是关于术语“浅拷贝”和“深拷贝”的正确用法,特别是在谈论复制一个不包含任何引用的对象时。这个问题并不意味着(也不应该)基于意见,除非真的没有关于这个话题的共识。我已将此问题标记为 C
我有这个功能 int getrelation(string name, RELATION& output){ bool found=0; int index=0;
与 why should I make a copy of a data frame in pandas 有关 我注意到在流行的backtesting图书馆, def __init__(self, d
我的问题很基础,但我想 100% 理解所有内容。 SO中的很多问题都引用了我的帖子,但我没有找到满意的答案。 我们知道java中的枚举是引用类型。让我们考虑以下片段: public static cl
请引用这个 fiddle 的问题。 http://jsfiddle.net/AQR55/ 1)为什么附加到隔离范围属性的 watch - 双向绑定(bind)到父属性,不会在更改父范围属性时触发。 在
我想使用 UP3 来完成一项非常具体的任务,我应该能够使用 API 来实现该任务。我想了解是否可以编写以下应用程序。 基于https://jawbone.com/support/articles/00
如何在辅助方法中传递上下文并提取数据? 请参阅以下代码片段: import AppContext from '../../context/AppContext' import extractDatta
我正在尝试使用 simple-git 创建浅克隆。我正在尝试创建与此命令等效的命令:git clone --depth 1 https://github.com/steveukx/git-js.git
我是一名优秀的程序员,十分优秀!