Swift 可选的链接和合并,包括函数参数

Swift 可选的链接和合并,包括函数参数,swift,swift4,null-coalescing,optional-chaining,Swift,Swift4,Null Coalescing,Optional Chaining,可选链接允许我们对对象的存在作出决定: var text : String? let len = text?.lengthOfBytes(using: .utf8) ?? 0 它将始终将len设置为整数 对于非可选函数参数,是否可能有类似的情况?考虑下面的例子,用三元运算符已经不太雅致了。 func length(text: String) -> Int { return text.lengthOfBytes(using: .utf8) } var text : String?

可选链接允许我们对对象的存在作出决定:

var text : String?
let len = text?.lengthOfBytes(using: .utf8) ?? 0
它将始终将
len
设置为整数

对于非可选函数参数,是否可能有类似的情况?考虑下面的例子,用三元运算符已经不太雅致了。
func length(text: String) -> Int {
    return text.lengthOfBytes(using: .utf8)
}

var text : String?
let len = (text != nil) ? length(text!) : 0
如果我们继续链接,它很容易变得一团糟(这就是我实际上看到的):

let y = (arg!= nil) ? (foo?.bar(arg!) ?? 0) : 0 // how to improve on this?
此外,它也开始变得冗余,两次定义默认值


最后一行还有更简洁的解决方案吗?

考虑到
的使用会影响编译时间。
在您描述的示例中,我个人喜欢使用易于使用的扩展

extension Optional where Wrapped == String {
    func unwrappedLengthOfBytes(using: String.Encoding) -> Int {
        guard let text = self else {
            return 0
        }
        return text.lengthOfBytes(using: .utf8)
    }
}
用法:

var text : String?
text.unwrappedLengthOfBytes(using: .utf8)

您不必将自己限制为可选链接。Swift提供了其他语言结构来清楚地表达这一点:

let y: Int
if let arg = arg, let foo = foo {
    y = foo.bar(arg)
} else {
    y = 0
}

map
方法是最好的方法<代码>平面图
也可能会引起兴趣

func length(text: String) -> Int {
    return text.lengthOfBytes(using: .utf8)
}

var text : String?
let len = text.map(length) ?? 0

如果你有多个参数,你可以很容易地编写一个函数
(a,B?)->(a,B?)

我认为可选的链接就足够了,关于你的例子,我会说:
让len=length(text:text??)
或者
让len=text.map(length)??0
使用默认参数有缺点:1)调用该函数的代价可能很高,2)它将默认值的逻辑放入该函数中并远离其上下文。@Eiko只需使用nil合并运算符。顺便说一句,不需要创建一个方法来获取字符串的字节数。只需获取utf8字符的计数View
yourString.utf8.count
如果您的字符串是可选的
let len=text?.utf8.count??0
字节数只是一个示例,根本没有理由改进第一个示例。问题是如何绕过函数调用,而nil合并似乎并没有提供解决方案。谢谢,有趣的想法-不确定这如何解决主要问题(传递可能为nil的参数)。“?”凝聚效果很好。事实上,我正试图提出更简洁的代码,而不是帮助函数。我认为斯威夫特可能也有这方面的东西。这在可读性方面是非常误导人的。它使它看起来像是一个非可选的对象。是的,我知道-我刚刚习惯了合并快捷方式,并希望有类似的参数。