关于条件的问题 (/;)

2024-01-07

Condition有属性HoldAll这会阻止在应用之前评估其第一个参数Condition。但由于某种原因Condition即使测试给出,也会评估其第一个参数False:

In[1]:= Condition[Print[x],False]
During evaluation of In[1]:= x
Out[1]= Null/;False

为什么是这样?出于什么目的Condition如果测试给出,则评估其第一个参数False?在什么情况下这种行为会有用?

附:当Condition用作第二个参数SetDelayed:

In[5]:= f:=Condition[Print[x],False]; f
Out[6]= f

这是我对所有情况的期望。


据我所知(其他回答者已经提到过这一点),Condition不应将其视为独立函数,而应将其视为用于形成涉及模式的较大表达式的包装器。但我想强调的是,这里的部分微妙之处来自于这样一个事实:Rule and RuleDelayed是范围构造。一般来说,作用域构造必须有一个变量绑定阶段,在该阶段它们解决变量名称中可能存在的冲突,并实际上将变量绑定到它们在作用域构造体中的出现(或者,在规则的右侧)Rule and RuleDelayed)。这可能被认为是作用域构造内部工作的一部分,但是,因为 Mathematica 允许通过属性和类似的东西进行顶级操作Evaluate,作用域构造并不像它们看起来那样黑盒 - 我们可以通过强制变量声明或主体或两者在绑定发生之前进行评估来更改绑定 - 例如,通过删除一些Hold*- 属性。我讨论了这些事情here http://forums.wolfram.com/mathgroup/archive/2010/May/msg00206.html更详细地说,虽然我不知道范围构造的确切实现细节,但我不得不大部分猜测。

回到案例Rule, RuleDelayed and Condition, 这是有指导意义的Trace讨论的例子之一:

In[28]:= Trace[Cases[{3,3.},a_:>Print[a]/;(Print["!"];IntegerQ[a])],RuleCondition,TraceAbove->All]
During evaluation of In[28]:= !
During evaluation of In[28]:= !
During evaluation of In[28]:= 3

Out[28]= {Cases[{3,3.},a_:>Print[a]/;(Print[!];IntegerQ[a])], 
{RuleCondition[$ConditionHold[$ConditionHold[Print[3]]],True],
      $ConditionHold[$ConditionHold[Print[3]]]},
{RuleCondition[$ConditionHold[$ConditionHold[Print[3.]]],False],Fail},
 {Print[3]},{Null}}

你看到的是有特殊的内部头RuleCondition and $ConditionHold,出现时Condition与使用Rule or RuleDelayed。我的猜测是,它们实现了将条件合并到模式变量上的机制,包括变量绑定。当你使用Condition作为一个独立的功能,这些不会出现。这些头对于条件机制真正发挥作用至关重要。 你可以看看他们是如何工作的Rule and RuleDelayed:

In[31]:= RuleCondition[$ConditionHold[$ConditionHold[Print[3.`]]],True]
Out[31]= $ConditionHold[$ConditionHold[Print[3.]]] 

In[32]:= RuleCondition[$ConditionHold[$ConditionHold[Print[3.`]]],False]
Out[32]= Fail

你可以看到,说,Cases仅选取表单的元素$ConditionHold[$ConditionHold[something]],并忽略那些RuleCondition结果是Fail。现在,当您使用时会发生什么Condition作为一个独立的功能是不同的 - 因此结果也不同。

我知道的一个很好的例子,很好地说明了上述几点,是这个线程 http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/3a5ae92bda1c7511,在可能的情况下实现一个版本With其顺序结合进行了讨论。我将在这里重复该讨论的一部分,因为它很有启发性。这个想法是制作一个 With 版本,其中先前的声明可以用于声明列表中更靠下的声明。如果我们称它为Let,那么,例如,对于像这样的代码

Clear[h, xl, yl];
xl = 1;
yl = 2;
h[x_, y_] := Let[{xl = x, yl = y + xl + 1}, xl^2 + yl^2];
h[a, b]

我们应该得到

a^2+(1+a+b)^2

建议并给出此结果的实现之一是:

ClearAll[Let];
SetAttributes[Let, HoldAll];
Let /: (lhs_ := Let[vars_, expr_ /; cond_]) := 
   Let[vars, lhs := expr /; cond]
Let[{}, expr_] := expr;
Let[{head_}, expr_] := With[{head}, expr]
Let[{head_, tail__}, expr_] := With[{head}, Let[{tail}, expr]]

(这是巴斯蒂安·埃德努斯的功劳)。这里发生的事情是Let在运行时执行绑定,而不是在定义函数时执行绑定。一旦我们想使用共享局部变量,它就会失败:

Clear[f];
f[x_,y_]:=Let[{xl=x,yl=y+xl+1},xl^2+yl^2/;(xl+yl<15)];
f[x_,y_]:=x+y;

?f
Global`f
f[x_,y_]:=x+y

如果它工作正常,我们最终应该得到两个不同的定义。到这里,我们就来到了问题的关键:既然如此Let在运行时起作用,SetDelayed没有察觉到Condition作为模式的一部分 - 它会这样做With, Block, Module,但不是一些未知的Let。因此,这两个定义对 Mathematica 的查找都是相同的(就模式而言),因此,第二个定义取代了第一个定义。但这并不是全部。现在我们只创建第一个定义,并尝试执行:

Clear[f];
f[x_, y_] := Let[{xl = x, yl = y + xl + 1}, xl^2 + yl^2 /; (xl + yl < 15)];

In[121]:= f[3, 4]

Out[121]= 73 /; 3 + 8 < 15

如果你追踪最后一次执行,就会很不清楚为什么Condition没有在这里开火。原因是我们搞乱了绑定阶段。这是我的改进版本,没有这些缺陷:

ClearAll[LetL];
SetAttributes[LetL, HoldAll];
LetL /: Verbatim[SetDelayed][lhs_, rhs : HoldPattern[LetL[{__}, _]]] :=
   Block[{With}, Attributes[With] = {HoldAll};
     lhs := Evaluate[rhs]];
LetL[{}, expr_] := expr;
LetL[{head_}, expr_] := With[{head}, expr];
LetL[{head_, tail__}, expr_] := 
  Block[{With}, Attributes[With] = {HoldAll};
    With[{head}, Evaluate[LetL[{tail}, expr]]]];

它的作用是扩展LetL进入嵌套With在定义时,而不是运行时,这种情况就会发生before绑定阶段。现在,让我们看看:

In[122]:= 
Clear[ff];
ff[x_,y_]:=LetL[{xl=x,yl=y+xl+1},xl^2+yl^2/;(xl+yl<15)];

Trace[ff[3,4]]

Out[124]= {ff[3,4],       
{With[{xl$=3},With[{yl$=4+xl$+1},RuleCondition[$ConditionHold[$ConditionHold[xl$^2+yl$^2]],
 xl$+yl$<15]]],With[{yl$=4+3+1},RuleCondition[$ConditionHold[$ConditionHold[3^2+yl$^2]],3+yl$<15]],
{4+3+1,8},RuleCondition[$ConditionHold[$ConditionHold[3^2+8^2]],3+8<15],
{{3+8,11},11<15,True},RuleCondition[$ConditionHold[$ConditionHold[3^2+8^2]],True],
$ConditionHold[$ConditionHold[3^2+8^2]]},3^2+8^2,{3^2,9},{8^2,64},9+64,73}

这工作正常,你可以看到头部RuleCondition and $ConditionHold显示一切正常。查看由此产生的定义是有启发性的ff:

?ff
Global`ff
ff[x_,y_]:=With[{xl=x},With[{yl=y+xl+1},xl^2+yl^2/;xl+yl<15]]

你可以看到LetL正如所宣传的那样,已在定义时扩展。由于模式变量绑定是在那之后发生的,所以一切工作正常。另外,如果我们添加另一个定义:

ff[x_,y_]:=x+y;

?ff
Global`ff
ff[x_,y_]:=With[{xl=x},With[{yl=y+xl+1},xl^2+yl^2/;xl+yl<15]]

ff[x_,y_]:=x+y

我们看到 Mathematica 现在认为这些模式是不同的。

最后一个问题是为什么Unevaluated不恢复的行为RuleDelayed因移除其而损坏HoldRest属性。我只能猜测这与异常行为有关RuleDelayed(它吃掉任意数量的Unevaluatedr.h.s. 周围的包装器),在评论中指出这个问题 https://stackoverflow.com/questions/5036907/how-to-make-an-analog-of-instring.

总结一下:最常见的预期用途之一Condition与封闭的范围结构密切相关(Rule and RuleDelayed),在分析其行为时,应考虑作用域构造中的变量绑定阶段。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于条件的问题 (/;) 的相关文章

随机推荐

  • C# 中的树形数据结构

    我正在寻找 C 中的树或图数据结构 但我想没有提供 使用 C 2 0 对数据结构进行广泛检查 http msdn microsoft com en us library ms379574 aspx关于为什么 是否有一个常用的方便的库来提供此
  • 为什么Python for循环中的临时变量计算会占用这么多内存? [复制]

    这个问题在这里已经有答案了 下面两段代码是等价的 但是第一个代码占用了大约700M内存 后一个代码只占用了大约100M内存 通过Windows任务管理器 这里会发生什么 def a lst for i in range 10 7 t a t
  • python Qt:主小部件滚动条

    我们试图在主窗口部件上放置滚动条 因此如果用户调整主窗口的大小 滚动条就会出现 并让他上下移动以查看较小窗口部件之外的子部件 从而允许其左右移动 这是带有滚动条的主小部件的代码 def centralWDG self MainWindow
  • 带有关键字参数的 PyObject_CallMethod

    我正在尝试在我的 C 应用程序中嵌入 Python 2 7 库 并且使用 Python C API 从 C 调用 Python 代码 我需要调用采用关键字参数的 Python 方法 从语义上讲 我试图在 Python 中实现与以下行等效的效
  • 对字符串使用小于比较运算符

    我正在关注 C 教程 并查看字符串和运算符重载 例如 目前我有一个简单的 if 语句 if s1 lt s2 cout lt lt s2 lt
  • PHP - 按原样显示小浮点数

    我必须显示一个计算出的数字 有时它非常小 显示如下 1 0E 8 我怎样才能显示它 0 00000001 http php net manual en function number format php http php net manu
  • GraalVM - 在没有上下文的情况下使用多语言值

    我正在 Graal 之上编写一个应用程序 它将能够执行不同语言的小脚本 我正在尝试为一个类编写一些单元测试 我正在使用该类将 Context eval 调用 类型 Value 的结果转换 处理为 Java 对象 我从文档中知道 Value
  • 代码完成未给出建议

    假设我正在使用 requests Python 库 req requests get http google com Now after this if I type req I m supposed to get a list of al
  • 在 git 中,如何从一个分支中删除提交并将其应用到另一个分支?

    我有两个来自 master 的分支 每个分支都有不同的功能 然后我有一个将两者结合起来的综合分支 我向综合分支提交了一些内容 但现在我发现我宁愿将该更改应用到特定于该功能的分支之一 有没有办法用 git 在其他地方执行此取消应用 应用操作
  • SQL Server - 从经度和纬度到几何数据类型[重复]

    这个问题在这里已经有答案了 可能的重复 SQL Server 2008 Spatial 在多边形中找到一个点 https stackoverflow com questions 11054149 sql server 2008 spatia
  • 如何选择DDD聚合?

    In book 通过 C 示例应用领域驱动设计 in 第4章 第一个草图 在点上4 并发冲突检测很重要我不明白为什么作者选择这个聚合 客户有他自己的聚合 订单有他自己的聚合 我认为客户应该参考他的订单 订单仅与客户相关 我没有看到任何一种情
  • SQL代码:-420,SQLSTATE:22018,SQLERRMC:BIGINT

    运行 DB2 UDB 版本 9 为什么此 SQL 语句有效 SELECT CASE WHEN A DAILYDOWNLOADSIZE is null THEN 0 else bigint A DAILYDOWNLOADSIZE END DA
  • Boost 没有静态链接到 boost::python 共享对象

    我使用 boost python 为我的应用程序创建了一个包装器 到目前为止 这已经奏效了 静态库 源代码数量 gt python mapping so 通过这种方式 我的共享对象由许多静态库组成 包括 boost 本身 特别是 boost
  • java中的“表名模式不能为NULL或空”

    当我想从数据库元数据获取表时 出现此错误 Exception in thread main java sql SQLException Table name pattern can not be NULL or empty at com m
  • 我可以通过 add_action 将参数传递给我的函数吗?

    我可以做类似的事情吗 将参数传递给我的函数 我已经学过添加操作文档 http codex wordpress org Function Reference add action但不知道该怎么做 传递两个参数的确切语法是什么样的 特别是如何通
  • 一切都一样,在 C++ 中将数据输出到磁盘的最快方法是什么?

    我正在运行的模拟代码很大程度上受 CPU 速度的限制 我对将数据输入 输出到用户界面不感兴趣 只需在计算时将其保存到磁盘即可 减少开销的最快解决方案是什么 iostreams 打印 我之前读过 printf 更快 这取决于我的代码吗 如果不
  • Google App Engine Python Webapp2 301 从 www 重定向到非 www 域

    我有一个基于 gae 构建的应用程序 我使用 python 和 webapp2 框架 我需要进行 301 重定向www my crazy domain com to my crazy domain com这样可以消除搜索结果中的 www 和
  • 带通配符的 Logback 记录器名称

    是否可以对记录器名称使用通配符来匹配不同的包 这样我们就不必单独指定它们 所以而不是写
  • pyspark 根据 lat lng 获取到另一个车站的最小距离的车站

    我正在使用 1 个数据框 它包含车站名称及其坐标 现在我想找出距离每个车站最近的车站 并将其记录在单独的列中 例如 df Station name lat Lng mainstation 8 3838 6 9848 bus station
  • 关于条件的问题 (/;)

    Condition有属性HoldAll这会阻止在应用之前评估其第一个参数Condition 但由于某种原因Condition即使测试给出 也会评估其第一个参数False In 1 Condition Print x False During