如果不是 Nil,则变量重新分配方法结果

Posted

技术标签:

【中文标题】如果不是 Nil,则变量重新分配方法结果【英文标题】:Variable re-assign method result if not Nil 【发布时间】:2021-10-06 08:08:00 【问题描述】:

是否有应用和分配对象变量方法调用的惯用方式,但前提是它已定义(方法和结果)?

喜欢使用safe call operator .? 和defined-or operator //,并遵循“DRY 原则”——在操作中只使用一次变量?

像这样(但使用另一个变量感觉像是在作弊):

my $nicevariable = "fobar";

# key step
(my $x := $nicevariable) = $x.?possibly-nonexistent-meth // $x;

say $nicevariable;  # => possibly-nonexistent-meth (non-Nil) result or "foobar"

...如果可能的话,避免andthen

【问题讨论】:

【参考方案1】:

假设该方法返回 定义的内容,您可以这样做(如果我正确理解了这个问题):

my $x = "foobar";
$x = $_ with $y.?possibly-nonexistent-meth;

$x 如果方法不存在(或者它确实存在并返回一个类型对象)将保持不变。

【讨论】:

(你的意思可能是$x而不是$y。) 有趣。我还没有得到,它是如何通过我的非 Nil 条件的...... .. 可能是根据定义 :) (with 名称不是很具描述性) 如果我不想覆盖变量并在关键行中只“提及”一次,那可能是正确的选择。 @mykhal re $y vs $x:你告诉我 :-) 从示例代码中我并不清楚。【参考方案2】:

我不完全确定“在操作中仅使用一次变量”是什么意思。如果 Liz 的答案符合条件,那么这可能是更清洁的方法。

如果不是,这里有一种不同的方法,可以避免两次命名变量:

my $nicevariable = "foobar";
$nicevariable.=&.^lookup('possibly-nonexistent-meth')($_)

这对我来说有点太神秘了;它的作用是:如果该方法存在,则类似于¹调用&method($nicevariable),与$nicevariable.method 相同。如果该方法确实存在,那么它就像调用Mu($nicevariable) - 即将$nicevariable 强制转换为MuMu 的子类型。但是由于一切都已经是Mu 的子类型,所以这是一个空操作,只返回$nicevariable

[1]:不完全是,因为&method 将是一个 Sub,但基本上。

编辑

实际上,这太复杂了。这是一个更简单的版本:

my $nicevariable = "foobar";
$nicevariable.=&.?possibly-nonexistent-meth // $_

不知道为什么我一开始就没有这个……

【讨论】:

编辑非常接近我的意思...我在玩.=,但我没有想到&的把戏,谢谢。【参考方案3】:

你知道变量上的default trait吗?

不确定它是否适合您的用例,但 $some-var.?unknown-method 返回 Nil,所以:

my $nicevariable is default("fobar");
$nicevariable = $nicevariable.?possibly-nonexistent-meth;
say $nicevariable;  # fobar

导致$nicevariable 被重置为其默认值;

【讨论】:

【参考方案4】:

截至this merge,您可以写:

try  let $foo .= bar 

这比我认为的理想解决方案差了一步,不幸的是,这是一个语法错误(由于 Raku 的 当前 语法普遍存在弱点,我猜这实际上是无法解决的,尽管我很想解决它):

 let $foo .?= bar  # Malformed postfix call...

(也许我在想象一些事情,但我看到了一丝希望,即上述皱纹(以及许多人喜欢的皱纹)会在几年后被抚平。这将是在 RakuAST 登陆 Raku .e 之后,并且希望在 Raku .f.g 中清理语法。)


您的问题的标题是:

如果不是Nil,则变量重新分配方法结果

如果不是undefined,我的解决方案会执行变量重新分配方法,这比Nil 更通用。

然后,您的问题的 正文 要求正是更通用的解决方案:

是否有应用和分配对象变量方法调用的惯用方式,但前提是它已定义(方法和结果)?

那么我的解决方案是否理想?

我的解决方案不是惯用的。但这很可能是因为我发现的错误,现在通过我的答案开头链接的合并解决了。我看不出它为什么不应该成为惯用语,一旦它在运送 Rakudos。

潜在的大问题是try 存储$! 中抛出的任何异常,而不是让它爆炸。对于给定的用例,也许这没问题;也许不是。


特别感谢您提出问题,这促使我们提出了各种解决方案,这导致我提出问题,这导致 vrurg 分析我遇到的问题然后修复它。 :)

【讨论】:

我喜欢这个版本——尤其是因为您仍然可以访问$! 中的任何解除异常/故障,这可以保留您处理某些问题的选择权。 请注意,根据.bar 方法的内容,您无法保证$foo 实际上会保持不变,即使发生了一些异常。 @ElizabethMattijsen 我知道有些方法可能会开始改变它们的调用者然后抛出,或者先抛出然后.resume,但我认为你不是那个意思(这将是代码节答案的问题也)。我对在抛出异常时退出执行语句的确切细节感到模糊,但听到try 无法立即退出分配或绑定语句(let 或任何其他)让我感到惊讶如果在评估 rhs 时抛出异常。如果这就是你的意思,你能链接到我能读到的东西吗? TIA。 @raiph 我不确定你能读到什么。赋值实际上与在对象中设置属性没有什么不同。如果这发生在执行错误之前,它将保持设置。除非您有一个 UNDO 移相器来撤消该设置。这能回答你的问题吗? @ElizabethMattijsen “分配实际上与在对象中设置属性没有什么不同。”正确的。 “如果在执行错误之前发生这种情况,它将保持不变。”甚至是let?!?考虑my Int @array = 1, 2; try let @array = (42 and die) ; try let @array = 3, 'a' ; .say for $!, @array; # Type check failed in assignment ... got Str ("a")␤[1 2]␤。第一个try 在评估let 的右轴时抛出。第二次抛出分配letlhs。然而 both 情况的最终结果是 @array 保持不变。我错过了什么场景?

以上是关于如果不是 Nil,则变量重新分配方法结果的主要内容,如果未能解决你的问题,请参考以下文章

即使在分配值后显示 nil 的弱可选变量?

Codeigniter将数据库值分配给变量

Google Apps 脚本变量重新分配

常量未分配的可选项默认情况下不会为 nil

如果两个变量指向同一个对象,为啥重新分配一个变量不会影响另一个?

我是不是需要在块内的 strongSelf = weakSelf 分配上检查 nil ?