[英]Swift macros when creating Array from literals
对于下面的代码:
let services: [MyServices] = [
MyService(),
#if DEBUG
DebugService(),
#endif
]
我收到编译器错误:
表达式无法解析:错误:MyPlayground.playground:375:5:错误:容器文字中的预期表达式#if DEBUG ^
错误:MyPlayground.playground:376:19: 错误:一行中的连续语句必须用“;”分隔调试服务(), ^;
错误:MyPlayground.playground:376:19: 错误:预期表达式 DebugService(), ^
错误:MyPlayground.playground:378:1:错误:预期的表达]
但相同的代码适用于 Objective-C
NSArray *array = @[
@"11",
#if DEBUG
@"debug",
#endif
@"22"
];
这是编译器错误还是预期行为? 谢谢。
#if
/ #endif
结构不像 C 那样是预处理器宏。它们是编译器指令。 它们是语言的一部分。
在 C 中,它会在您的源文件上运行预处理器,从而生成经过修改的源文件。 修改后的源文件被编译。
在 Swift 中不是这样。在 Swift 中,编译器解析源文件并尝试编译它。
要理解为什么您尝试的方法不起作用,请将#if / #endif
想象成一个常规的 if 语句。 以下会编译吗?
let debug = true
let services: [MyServices] = [
MyService(),
if debug {
DebugService(),
}
]
(答案:不。那是不合法的。您不能在数组初始值设定项的参数中间插入 if 语句。 #if / #elseif
语句也是如此。)
您不能使用#if / #endif
块将语句的片段组合在一起。
在这两种情况下,您都必须创建完整的语句:
#if debug
let services: [MyServices] = [
MyService(),
DebugService(),
]
#else
let services: [MyServices] = [
MyService()
]
#endif
(或者您可以将services
设为 var,并在#if / #endif
中将其设为 append DebugServices()
。)
更好的是,使用“后缀” .appending()
就像@MartinR 的出色答案一样。
通常, #if... #else... #endif
编译器指令中每个子句的主体必须包围完整的语句。
但是随着 Swift 5.5 中后缀成员表达式的 SE-308 #if
的实现,这个指令已经扩展到能够包围后缀成员表达式。
所以有了自定义扩展
extension Array {
func appending(_ e: Element) -> Self {
return self + [e]
}
}
可以像这样有条件地初始化一个数组:
let services = [
MyService() ]
#if DEBUG
.appending(DebugService())
#endif
let services: [MyServices] = [
#if DEBUG
DebugService()
#else
MyService()
#endif
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.