swift组合声明语法
swiftcombine的声明性语法在我看来很奇怪,似乎有很多事情是不可见的 例如,以下代码示例在Xcode中生成和运行:swift组合声明语法,swift,variadic,combine,Swift,Variadic,Combine,swiftcombine的声明性语法在我看来很奇怪,似乎有很多事情是不可见的 例如,以下代码示例在Xcode中生成和运行: [1, 2, 3] .publisher .map({ (val) in return val * 3 }) .sink(receiveCompletion: { completion in switch completion { case .failure(let error): print("Something went wr
[1, 2, 3]
.publisher
.map({ (val) in
return val * 3
})
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
print("Something went wrong: \(error)")
case .finished:
print("Received Completion")
}
}, receiveValue: { value in
print("Received value \(value)")
})
我看到我假设的是一个使用[1,2,3]创建的数组文本实例。我猜它是一个数组文字,但我不习惯看到它“声明”,而不将它赋给变量名或常量或使用=
我有意在之后加入了一个新行。publisher。Xcode是否忽略了空格和换行符
由于这种风格,或者说我对这种风格的视觉分析比较新,我错误地认为“receiveValue:”是一个可变参数或一些新语法,但后来意识到它实际上是.sink(…)的一个参数。Literals
首先,关于文字。可以在任何可以使用包含相同值的变量的地方使用文字。两者之间没有重要区别
let arr = [1,2,3]
let c = arr.count
let c = [1,2,3].count
及
空白
第二,关于空格。简单地说,斯威夫特不在乎你是否在一个点之前拆分一条语句。所以两者之间没有区别
let arr = [1,2,3]
let c = arr.count
let c = [1,2,3].count
及
锁链
当你一个接一个地链接很多函数时,拆分实际上是一种提高易读性的好方法。而不是
let c = [1,2,3].filter {$0>2}.count
写起来更好
let c = [1,2,3]
.filter {$0>2}
.count
或者为了更清楚
let c = [1,2,3]
.filter {
$0>2
}
.count
结论
这就是您展示的代码中所发生的一切:一个文本后跟一长串方法调用。为了便于阅读,它们被分割成不同的行,仅此而已
所以你在问题中提到的与联合收割机无关。这只是Swift语言的基本内容。您所谈论的一切都可能(而且确实)发生在根本不使用Combine的代码中
因此,从语法的角度来看,没有什么是“不可见的”,除了知道每个方法调用返回一个值,下一个方法调用可以应用到该值(就像我在上面的示例代码中,我对.filter
的结果应用.count
)。当然,因为您的示例是Combine,所以出现了一些“不可见的情况”,即这些值中的每一个都是发布者、运营商或订阅者(订阅者确实订阅了)。但这基本上只是知道什么是联合收割机的问题。因此:
是一个数组,它是一个序列,因此它有一个[1,2,3]
方法publisher
- 可应用于序列的
方法生成发布者publisher
方法(Combine的map
,而不是Array的map
)可以应用于发布者,并生成另一个作为发布者的对象map
方法可以应用于此,并生成一个订户,这就是链的末端sink
[1, 2, 3]
.publisher
.map({ (val) in
return val * 3
})
.sink(
receiveCompletion: { completion in
switch completion {
case .failure(let error):
print("Something went wrong: \(error)")
case .finished:
print("Received Completion")
}
},
receiveValue: { value in
print("Received value \(value)")
}
)
清理映射
表达式
我们可以通过以下方式进一步清理地图:
map({ (val) in
return val * 3
})
map({ (val) in
val * 3
})
map({ (val) in
return val * 3
})
map({ (val) in
val * 3
})
map({ val in
val * 3
})
map({ val in val * 3 })
val
map({ $0 * 3 })
map { $0 * 3 }
/* 1 */[1, 2, 3]
/* 2 */ .publisher
/* 3 */ .map { $0 * 3 }
/* 4 */ .sink(
/* 5 */ receiveCompletion: { completion in
/* 6 */ switch completion {
/* 7 */ case .failure(let error):
/* 8 */ print("Something went wrong: \(error)")
/* 9 */ case .finished:
/* 10 */ print("Received Completion")
/* 11 */ }
/* 12 */ },
/* 13 */ receiveValue: { value in
/* 14 */ print("Received value \(value)")
/* 15 */ }
/* 16 */ )
经历它。
第1行,[1,2,3]
第1行是一个数组文本。它是一个表达式,就像1
,“hi”
,true
,someVariable
或1+1
。这样的数组不需要分配给任何对象就可以使用
有趣的是,这并不意味着它一定是一个数组。相反,Swift有ExpressibleByArrayLiteralProtocol
。任何一致性类型都可以从数组文本初始化。例如,Set
符合,因此您可以编写:let s:Set=[1,2,3]
,您将得到一个Set
包含1
、2
和3
。在缺少其他类型信息(例如上面的Set
type注释)的情况下,Swift使用Array
作为首选数组文字类型
第2行,.publisher
第2行调用数组文本的publisher
属性。这将返回一个序列,这是一个非通用协议,但它位于组合
模块的发布者
命名空间(无大小写的枚举)中。因此,它的完全限定类型是
它是一个发布者
,其输出
为Int
,其失败
类型为从不
(即,由于无法创建从不
类型的实例,因此不可能发生错误)
第3行,map
第3行正在调用Combine.publisher.Sequence的map
实例函数(也称为方法)。有两个闭包参数
{completion in…}
闭包作为标记为receiveCompletion:
{value in…}
闭包作为标记为receiveValue:
Sink正在为订阅创建一个新订阅服务器,该订阅服务器是一个带有.failure(failure)
案例或.finished
案例的枚举。由于Failure
类型为Never
,因此实际上不可能在此处创建.Failure(Never)
的值。因此,完成将始终是.finished
,这将导致打印(“接收到的Com”)