【问题标题】:Swift reduce - why is value optional?Swift reduce - 为什么 value 是可选的?
【发布时间】:2019-06-07 09:11:21
【问题描述】:

为什么total 在线return total + 1 是可选的?

return first.enumerated().reduce(0) { total, letter in
   let index = first.index(first.startIndex, offsetBy: letter.offset)
   if first[index] != second[index]{
       return total + 1
   }
   return total
}

可选类型“Int?”的值必须解包为 使用 '??' 键入'Int' Coalesce可选时提供默认值 值包含 'nil' 使用 '!' 强制展开中止执行,如果 可选值包含 'nil'

所以这解决了它:

return first.enumerated().reduce(0) { total, letter in
   let index = first.index(first.startIndex, offsetBy: letter.offset)
   if first[index] != second[index]{
       return total! + 1
   }
   return total
}

如果我将其分解,则添加 let index.... 时会发生更改。

OK - 这将返回 first 的总数,并且 total 不是可选的:

return first.reduce(0) { total, letter in
    return total + 1
}

好的 - 这个枚举和总计不是可选的:

return first.enumerated().reduce(0) { total, letter in
    return total + 1
}

ERROR - 这会得到一个编译错误,total 是可选的

return first.enumerated().reduce(0) { total, letter in
    let index = first.index(first.startIndex, offsetBy: letter.offset)
    return total + 1
}

【问题讨论】:

  • first的类型是什么?你在哪里写这段代码?
  • 你能提供一个minimal reproducible example吗?我猜你所在函数的返回类型是可选的,因此因为bodies of multi-statement closures don't participate in type inference,编译器假设Result 占位符完全绑定到返回类型。
  • 另请注意,您的代码(除非我弄错了)表现出未定义的行为:index 在第一个字符串的索引中,并且不能用作不同字符串的下标。 – 顺便说一句,如果目的是计算两个字符串的不同字符的数量:有更简单的解决方案。
  • 这两个字符串 具有 相同的计数(三个)。 – return zip(first, second).filter(!=).count 将是一个与您的代码等效的简单解决方案。
  • @Turnipdabeets 这是因为表情符号字符不能用单个字节表示。试试"????????????".utf8.count

标签: swift reduce enumeration


【解决方案1】:

为了让你得到这个结果(据我所知),封闭函数必须返回一个Int?。这意味着reduce 可以返回一个可选项。如果没有条件,编译器可以确定 reduce 永远不会返回 nil,即 total 永远不会是 nil。所以,编译器推断闭包的返回类型是Int。编译器似乎在纠缠reduce 闭包和total 的类型推断。添加条件后,编译器无法确定 reduce 是否会返回 nil。现在,当它不必要地推断 total 的类型时,它会出错。

在我看来,这看起来像是一个 Swift 类型推断误入歧途的案例。显然,根据enumerated 的文档,total 永远不会为零。

如果你稍微修改一下代码,你会得到预期的结果:

   return first.enumerated().reduce(0) { (total: Int, letter) in
       let index = first.index(first.startIndex, offsetBy: letter.offset)
       if first[index] != second[index]{
          return total + 1
       }
       return total
   }

Swift 进行了很多类型推断,这真的很棒,因为我获得了强类型,同时保留了动态语言的许多优点。然而,根据我的经验,斯威夫特的推论有时会令人费解。它可以轻松处理神秘的情况,并在我认为显而易见的事情上绊倒。

对我来说它看起来像一个错误。

【讨论】:

    猜你喜欢
    • 2014-07-23
    • 2012-02-07
    • 2013-12-16
    • 2010-09-28
    • 2017-09-27
    • 1970-01-01
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多