当前位置: 首页 > 知识库问答 >
问题:

保护语句不一致

楚和悌
2023-03-14

//在guard语句中首先执行let,然后执行bool检查,会导致编译错误

   self.action = {  [weak self] in
      guard let `self` = self, data.isJSON() else { return }

//先执行布尔检查,然后让它工作

  self.action = {  [weak self] in
     guard data.isJSON(), let `self` = self else { return }

上面的两种说法似乎与我的说法相同。为什么在第一种情况下它不起作用?

共有1个答案

习旻
2023-03-14

首先,请注意,如果您的问题包含一个最小、完整且可验证的示例(mvce)就更好了,但在当前形式下,它不包含:

    < li >关闭列表无关紧要,在这里只会引起混乱 < li >未知的< code >自我(...没有上下文)同样只会引起混淆,并且与此问题无关

相反,你的问题的mvce可以按照以下方式构建:

func foo(bar: Int?) {
    // 1. why does this cause a compile time error?
    guard let baz = bar, true else { return }

    // 2. whereas this does not?
    guard true, let bax = bar else { return }
}

下面的答案将讨论这个mvce,而不是原始问题中模糊的例子。最后还要注意,守卫/守卫让语句与问题的核心并不完全相关(唯一),因为我们看到 if/if let 语句具有相同的行为。下面的答案将使用保护语句。

上面函数foo(…)中的第一条保护statement的编译时错误非常明显

布尔条件需要where将其与变量绑定分开。

修复此问题:将 替换为,其中

这在《语言指南-基础知识-可选装订》中也有说明

您可以在单个if语句中包含多个可选绑定,并使用whereclause检查0.05布尔条件。如果可选绑定中的任何值为nil其中clause的计算结果为 false,则认为整个可选绑定不成功。

因此,如果我们想在Guardif语句中的可选绑定之后使用条件子句,则需要使用where子句将条件子句与前面的可选绑定分开。

func foo(bar: Int?) {
    // 1. ok, compiles
    guard let baz = bar where true else { return }

    /* 2. or, include a conditional-clause prior to the
          optional binding, but is this really equivalent..? */
    guard true, let bax = bar else { return }
}

然而,这两者并不真正等同;

  • 语句2.上面允许我们短路Guard语句,以防初始条件子句被证明是false(然后不进行可选绑定,而是直接进入Guard语句的else块)
  • 而1.上面允许相反:仅当可选绑定成功时才检查条件子句。

当然,在某些情况下,我们更喜欢一个而不是另一个,例如,如果条件子句包含一些非常繁重的计算,我们可能不想执行这些,除非我们确定可选绑定成功。

let heavyStuff: () -> Bool = { print("foo"); /* ... */ return true }

func foo(bar: Int?) {
    /* 1. call the heavyStuff boolean construct only if
          the optional binding succeeds */
    guard let baz = bar where heavyStuff() else { return }

    /* 2. possibly unnesessarily perform heavy boolean
          stuff prior to failing the optional binding */
    guard heavyStuff(), let bax = bar else { return }
}

一个不太人为的例子是,如果我们想在下面的条件子句中使用一个成功绑定的变量(此处:作为参数)

let integerStuff: (Int) -> Bool = { _ in /* ... */ return true }

func foo(bar: Int?) {
    /* 1. call the integerStuff boolean construct only if
          the optional binding succeeds, using the binded
          immutable as closure argument */
    guard let baz = bar where integerStuff(baz) else { return }

    /* 2. ... not really any good alternatives for such 
          flow if using this alternative */
    guard integerStuff(baz ?? 0), let bax = bar else { return }
}

最后请注意,从技术上讲,如果您确实想将初始可选绑定与以下条件子句分开,则可以使用虚拟大小写 let(非可选始终接替变量绑定/赋值)语句以及条件子句的 where 关键字

let checkThis: () -> Bool = { /* ... */ return true }

func foo(bar: Int?) {
    // ...
    guard let baz = bar, case let _ = () where checkThis() else { return }
}

然而,这只是为了展示这种技术性;在实践中,只需使用where子句。

 类似资料:
  • 我在谷歌分析的实施说明中遇到了这个问题: 我从没想过在 else 子句中有一个断言是可能的,而不返回。这对我来说没有意义,因为断言只会在测试方案中进行评估。那么,为什么编译器不警告它不会返回(在发布版本的情况下)。 编辑:这是在函数

  • 按照下面的介绍youtube.com/playlist?list=plea0wjq13cnafcc0azrcyqucn_tpeljn1创建本体。它稍微缩小了http://prntscr.com/bo4l3w,我自己添加了canBeTutor(意思是某人可以成为某人的导师)对象属性。据我理解,我可以添加SWRL规则,然后启动reasoner来创建新的知识。所以我添加了prntscr.com/bo4l

  • 问题内容: 我知道有些人可能会回答这个问题,但是我的问题来自于您和您的答案。我正在阅读有关SQL注入以及如何保护数据库的过去两个小时的问答。我看到的大量网页和教程也是如此。 我发现有一半人声称prepare语句确实可以保护您的数据库,而另外50人则声称不是。 另一方面,我读到mysql_real_escape_string可以完成这项工作,而其他人则说不行。 我的问题是谁相信? 另外,这是适当的准

  • 问题内容: 我有两个枚举: 如果ServerState设置为基础TL State无法实现的状态,则需要在它们之间进行切换,并返回’false’。例如,如果将返回false 。我试图使用switch语句执行此操作,但是我发现我真正想要的是匹配一个状态 不是 特定状态的情况。例如: 显然,这是行不通的,因为您不能放在case语句之前。我唯一的其他选择是指定所有 允许的 情况,而这种情况要多得多。指定限

  • 我在Jpa存储库中使用Spring Boot。我在循环中保存一些记录,在保存所有记录后,会打印下面的异常。 JAVAsql。SQLRecoverableException:oracle的Instruço Fechada。jdbc。驾驶员OracleClosedStatement。oracle上的getMaxRows(OracleClosedStatement.java:3578)~[ojdbc6-

  • 本文向大家介绍Scala语言保护(if表达式),包括了Scala语言保护(if表达式)的使用技巧和注意事项,需要的朋友参考一下 示例 案例语句可以与if表达式结合使用,以在模式匹配时提供额外的逻辑。 确保您的警卫人员不会产生非详尽的匹配非常重要(编译器通常不会捕获此匹配): 这将引发一个MatchError奇数。您必须考虑所有情况,或使用通配符匹配情况: