避免在 Swift 中使用连续的“if let”声明[重复]

2024-04-05

在斯威夫特我用过if let声明来检查我的对象是否不是nil

if let obj = optionalObj
{
}

但有时候,我不得不面对连续的if let声明

if let obj = optionalObj
{
    if let a = obj.a
    {
        if let b = a.b
        {
            // do stuff
        }
    }
}

我正在寻找一种方法来避免连续if let声明。

我会尝试这样的事情:

if let obj = optionalObj && if let a = obj.a && if let b = a.b
{
    // do stuff
}

但 swift 编译器不允许这样做。

有什么建议吗?


Update

在 swift 1.2 中你可以做

if let a = optA, let b = optB {
  doStuff(a, b)
}

原答案

在您的具体情况下,您可以使用可选链:

if let b = optionaObj?.a?.b {
  // do stuff
}

现在,如果您需要做类似的事情

if let a = optA {
  if let b = optB {
    doStuff(a, b)
  }
}

你运气不好,因为你不能使用可选链。

tl; dr

您更喜欢一件很酷的单线吗?

doStuff <^> optA <*> optB

继续阅读。虽然它看起来有多么可怕,但它确实很强大,而且使用起来并不像看起来那么疯狂。

幸运的是,使用函数式编程方法可以轻松解决这个问题。您可以使用Applicative抽象并提供apply将多个选项组合在一起的方法。

这是一个例子,取自http://robots.thoughtbot.com/function-swift-for-dealing-with-optional-values http://robots.thoughtbot.com/functional-swift-for-dealing-with-optional-values

首先,我们需要一个函数,仅当可选值包含某些内容时才将函数应用于可选值

// this function is usually called fmap, and it's represented by a <$> operator
// in many functional languages, but <$> is not allowed by swift syntax, so we'll
// use <^> instead
infix operator <^> { associativity left }

func <^><A, B>(f: A -> B, a: A?) -> B? {
    switch a {
    case .Some(let x): return f(x)
    case .None: return .None
    }
}

然后我们可以使用 apply 将多个选项组合在一起,我们将其称为<*>因为我们很酷(而且我们了解一些 Haskell)

// <*> is the commonly-accepted symbol for apply
infix operator <*> { associativity left }

func <*><A, B>(f: (A -> B)?, a: A?) -> B? {
    switch f {
    case .Some(let value): return value <^> a
    case .None: return .None
    }
}

现在我们可以重写我们的例子

doStuff <^> optA <*> optB

这会起作用,前提是doStuff是柯里化形式(见下文),即

func doStuff(a: A)(b: B) -> C { ... }

整个结果是一个可选值,要么nil或结果doStuff

这是一个完整的示例,您可以在 Playground 中尝试

func sum(a: Int)(b: Int) -> Int { return a + b }

let optA: Int? = 1
let optB: Int? = nil
let optC: Int? = 2

sum <^> optA <*> optB // nil
sum <^> optA <*> optC // Some 3

最后一点,将函数转换为其柯里化形式非常简单。例如,如果您有一个带有两个参数的函数:

func curry<A, B, C>(f: (A, B) -> C) -> A -> B -> C {
    return { a in { b in f(a,b) } }
}

现在您可以柯里化任何二参数函数,例如+例如

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

避免在 Swift 中使用连续的“if let”声明[重复] 的相关文章

随机推荐

  • 用于 bean 验证的自定义验证消息

    我正在创建一个 JSF 2 应用程序 并且尝试在 bean 中而不是 faces page 中使用表单验证 我还想使用 properties 文件来存储消息 我在看这个问题 https stackoverflow com questions
  • 卸载后取消 Redux 操作

    我想在组件卸载后取消一些功能 因为它会导致内存泄漏我的代码如下所示 componentDidUpdate prevProps if prevProps org org this props org org this mounted this
  • 如何使用 Perl SOAP 获取 JIRA 中的自定义字段列表?

    我很好奇是否有其他人知道如何获取您在 JIRA 中创建的所有自定义字段的列表 如果是这样 你是怎么做到的 我一直在尝试使用我在上找到的 Perl SOAP 例程JIRA SOAP 服务文档 http docs atlassian com s
  • Phonegap - 无法从服务器下载存档

    我正在尝试从我的 Phonegap Developer 应用程序运行电话间隙应用程序 但出现错误 无法从服务器下载存档 我正在连接到电话间隙桌面应用程序中显示的 IP 地址 PhoneGap 桌面应用程序显示消息 服务器正在运行http 1
  • 使用自定义键进行数组拼接

    假设我有这个代码 test array test zero abc test two ghi test three jkl dump test array splice test 1 0 def dump test 这给了我输出 Array
  • EF Core 中的 modelBuilder.Configurations.AddFromAssembly

    In EntityFramework 6 x 如果我们有很多EntityConfiguration那么我们可以将它们全部分配给OnModelCreating ModelBuilder modelBuilder 不一一列举如下 protect
  • MVC RadioButtonFor 组

    我有一个 PDF 课程 public class UIClonePDFDetail public int CatalogueID get set public List
  • 通过 API 在我的 Android 应用程序中查看 Excel 文件

    我想在我自己的 Android 应用程序中查看 Excel 文件 目前 使用我的应用程序我可以看到所有谷歌文档 但是在单击任何一个文档 例如 Excel 文件 myDemo xls 后 我想在我自己的应用程序中打开它 用于查看目的 我读过关
  • 使用 Python Paramiko 在不同的 SSH 服务器中并行运行多个命令

    我有一个SSH py目标是通过 SSH 连接到许多服务器来运行 Python 脚本 worker py 我正在使用 Paramiko 但对它非常陌生 并且不断学习 在我通过 ssh 连接的每台服务器上 我需要保持 Python 脚本运行 这
  • 如何使用 ASP.NET 5 MVC 6 保护 Web API

    我有一个很好的 ASP NET 5 MVC 6 应用程序正在运行 本质上 出于此目的 它只是您在启动新项目时获得的普通示例应用程序 以保持简单 到目前为止我可以 注册用户 Login Logout 保护页面 强制登录等 现在 我想要的是为应
  • “venv activate”不会改变我的Python路径

    我创建了一个虚拟环境 假设 test venv 我激活它 一切成功 然而 Python 解释器的路径不会改变 我已经在下面说明了这种情况 为了澄清起见 python 路径应该是 Desktop test venv bin python gt
  • .NET System.Text.Decoder.Convert 方法在字符中间返回completed==true

    我需要从 UTF 8 字节序列中读取一个字符串 这些字节的来源来自单独的读取操作 这些操作不考虑字符边界 因此我无法使用 System Text Encoding UTF8 GetString 但是 由 System Text Encodi
  • x86汇编代码的语法

    我试图了解操作系统的基础知识 并在 OCW 中找到了相关课程 名为 6 828 我在课程的实验室中找到了引导加载程序的代码 我尝试了但不明白以下部分代码 Enable A20 For backwards compatibility with
  • 仅防止二元运算符的隐式转换运算符

    我遇到了一个问题 我已将其归结为以下问题 其中 即使应该失败 运算符用法也会编译 C 17 在 GCC 5 x 8 x 和 9 x 上测试 template
  • 如何从节点本机插件正确创建 Buffer 对象?

    我正在使用节点 6 9 1 并尝试创建一个 cpp 插件来创建节点缓冲区对象 经过一番研究 我想出了以下代码 include
  • 展平单子栈

    所以我的第一个严肃的 haskell 项目中到处都有这样的代码 f MonadTrans t gt ExceptT t StateT A B C f do mapExceptT lift do lift do lift do r lt re
  • C++ 中集合集合的高效集合交集

    我有一个收藏std set 我想以最快的方式找到这个集合中所有集合的交集 集合中的集合数量通常非常小 5 10 每个集合中的元素数量通常小于 1000 但偶尔会达到 10000 左右 但是我需要进行数十次这些交集数千次 尽可能快 我尝试对以
  • WPF 的免费字体和颜色选择器?

    我正在为 WPF 寻找一些好的字体选择器和颜色选择器组件 我试图找到一些标准解决方案 例如 Winforms 组件 但似乎没有 我想知道为什么 它不一定是完美的 代码项目中的一些东西就足够了 但我更喜欢好看且直观易用的组件 谢谢 Look
  • 响应式 SVG 图像蒙版

    我使用 SVG 作为图像蒙版 但我不知道如何在调整页面大小时使 SVG 改变其大小 当我更改窗口大小时 SVG 内的图像会调整大小 但 SVG 不会 关于如何解决这个问题有什么想法吗 这是 SVG 代码
  • 避免在 Swift 中使用连续的“if let”声明[重复]

    这个问题在这里已经有答案了 在斯威夫特我用过if let声明来检查我的对象是否不是nil if let obj optionalObj 但有时候 我不得不面对连续的if let声明 if let obj optionalObj if let