是否有任何可能显式使用空元组 () 的实例(值),即 typealias 'Void' 的实例?
Are there any possible explicit uses of instances (values) of empty tuples (), i.e., of instances of typealias 'Void'?
问题:
- 空元组
()
是否有任何可能的明确用途,作为 Swift [=50] 中的 值 (而不是类型) =]?
我知道这些空元组在标准意义上可以用来定义void函数。当我错误地定义了一个带有空元组 value var a = ()
(()
类型)的变量时,我开始怀疑这些空元组值是否可以在某些上下文中使用.有人知道这样的应用程序吗?
示例:数组和可选值的可能应用?
例如,我们可以创建一个可选的空元组数组,它自然只能容纳 nil
或 ()
:
/* Optionals */
var foo: ()? = ()
print(foo.dynamicType) // Optional<()>
var arr : [()?] = [foo]
for i in 2...8 {
if i%2 == 0 {
arr.append(nil)
}
else {
arr.append(foo)
}
}
print(arr) // [Optional(()), nil, Optional(()), ... ]
由于空元组的内存占用很小,对于 micro-memory-management 对于 "boolean nil/not nil" 这似乎很整洁,但是由于类型 Bool
具有相同的小内存占用,我不能真的在这里看到任何直接使用,即使在我们确实需要 bit-low 优化我们的操作的(不同)场景中也是如此。
也许我只是在用一些狭窄的无法使用的应用程序追逐自己的尾巴,但无论如何:这些无效 ()
存在是否有任何可能的明确用途(如 instances, 不是类型)?
假设您有两个重载相同名称的函数:
func foo()
func foo() -> Int
第一个没有 return 任何东西,第二个 return 有某种价值。在大多数情况下,尝试调用其中任何一个都会导致编译器出现歧义错误。
foo()
let a = foo()
您认为编译器会知道第一个调用明确引用第一个函数,因为它假定没有 return 值。但实际上,没有声明return类型的函数的return类型是Void
,或者()
。所以第一次调用其实更像这样:
let _ = foo()
并且缺少对丢弃的左值的类型注释,编译器无法推断要调用哪个 foo
。您可以使用显式类型注释来消除歧义:
let b: Void = foo()
let c: Int = foo()
好吧,这不是 Void
的一个非常好的或常见的用例,因为您一开始就倾向于避免进入这种情况。但是你要求 a use... 它是将 ()
用作值而不仅仅是类型,因为你可以从 b
中检索它分配后(对你有好处)。
请注意,当你深入观察Void
时,Void
也在观察你。或类似的东西。
有很多地方 ()
在解决 "CS" 问题时很有用,这些问题的形式通常是 "implement X using Y even though you really already have X." 例如,我可能会说,实现 Set使用词典。嗯,字典是 Key/Value 对。 Value 的类型应该是什么?实际上,我已经在有字典但没有集合的语言中看到过这种情况,人们经常使用 1 或 true 作为值。但这不是你的意思。这打开了歧义。如果该值是假的怎么办?它在集合中还是不在集合中?根据 Dictionary 实现 Set 的正确方法是 [Key: ()]
,然后你会得到如下代码行:
set[key] = ()
还有其他等效版本,例如您的 Optional<()>
。我还可以将整数实现为 [()]
或 Set<()>
。这有点傻,但我以前做过类似的事情来探索数论。
也就是说,这些几乎都是故意不切实际的解决方案。实用的怎么样?这些通常出现在泛型编程中。例如,想象一个具有这种形式的函数:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
这并不像听起来那么愚蠢。沿着这些思路的东西很容易出现在命令模式中。但是,如果没有 retval 怎么办?我不关心 return?好吧,没关系,只需传递一个 ()
值即可。
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
同样,您可能需要一个像 zipMap
:
这样的函数
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { [=13=]() }
}
这将应用一系列函数,这些函数采用 T
到类型 T
的值。即使 T
碰巧 ()
,我们也可以使用它,但我们必须生成一堆 ()
值才能使其工作。例如:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
我不认为这会在 Swift 中经常出现,因为 Swift 主要是一种命令式语言,几乎在所有情况下都隐藏了它的 Void
。但是当 Scala 等函数式语言过渡到命令式编程时,您确实会看到类似的事情出现。
问题:
- 空元组
()
是否有任何可能的明确用途,作为 Swift [=50] 中的 值 (而不是类型) =]?
我知道这些空元组在标准意义上可以用来定义void函数。当我错误地定义了一个带有空元组 value var a = ()
(()
类型)的变量时,我开始怀疑这些空元组值是否可以在某些上下文中使用.有人知道这样的应用程序吗?
示例:数组和可选值的可能应用?
例如,我们可以创建一个可选的空元组数组,它自然只能容纳 nil
或 ()
:
/* Optionals */
var foo: ()? = ()
print(foo.dynamicType) // Optional<()>
var arr : [()?] = [foo]
for i in 2...8 {
if i%2 == 0 {
arr.append(nil)
}
else {
arr.append(foo)
}
}
print(arr) // [Optional(()), nil, Optional(()), ... ]
由于空元组的内存占用很小,对于 micro-memory-management 对于 "boolean nil/not nil" 这似乎很整洁,但是由于类型 Bool
具有相同的小内存占用,我不能真的在这里看到任何直接使用,即使在我们确实需要 bit-low 优化我们的操作的(不同)场景中也是如此。
也许我只是在用一些狭窄的无法使用的应用程序追逐自己的尾巴,但无论如何:这些无效 ()
存在是否有任何可能的明确用途(如 instances, 不是类型)?
假设您有两个重载相同名称的函数:
func foo()
func foo() -> Int
第一个没有 return 任何东西,第二个 return 有某种价值。在大多数情况下,尝试调用其中任何一个都会导致编译器出现歧义错误。
foo()
let a = foo()
您认为编译器会知道第一个调用明确引用第一个函数,因为它假定没有 return 值。但实际上,没有声明return类型的函数的return类型是Void
,或者()
。所以第一次调用其实更像这样:
let _ = foo()
并且缺少对丢弃的左值的类型注释,编译器无法推断要调用哪个 foo
。您可以使用显式类型注释来消除歧义:
let b: Void = foo()
let c: Int = foo()
好吧,这不是 Void
的一个非常好的或常见的用例,因为您一开始就倾向于避免进入这种情况。但是你要求 a use... 它是将 ()
用作值而不仅仅是类型,因为你可以从 b
中检索它分配后(对你有好处)。
请注意,当你深入观察Void
时,Void
也在观察你。或类似的东西。
有很多地方 ()
在解决 "CS" 问题时很有用,这些问题的形式通常是 "implement X using Y even though you really already have X." 例如,我可能会说,实现 Set使用词典。嗯,字典是 Key/Value 对。 Value 的类型应该是什么?实际上,我已经在有字典但没有集合的语言中看到过这种情况,人们经常使用 1 或 true 作为值。但这不是你的意思。这打开了歧义。如果该值是假的怎么办?它在集合中还是不在集合中?根据 Dictionary 实现 Set 的正确方法是 [Key: ()]
,然后你会得到如下代码行:
set[key] = ()
还有其他等效版本,例如您的 Optional<()>
。我还可以将整数实现为 [()]
或 Set<()>
。这有点傻,但我以前做过类似的事情来探索数论。
也就是说,这些几乎都是故意不切实际的解决方案。实用的怎么样?这些通常出现在泛型编程中。例如,想象一个具有这种形式的函数:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
这并不像听起来那么愚蠢。沿着这些思路的东西很容易出现在命令模式中。但是,如果没有 retval 怎么办?我不关心 return?好吧,没关系,只需传递一个 ()
值即可。
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
同样,您可能需要一个像 zipMap
:
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { [=13=]() }
}
这将应用一系列函数,这些函数采用 T
到类型 T
的值。即使 T
碰巧 ()
,我们也可以使用它,但我们必须生成一堆 ()
值才能使其工作。例如:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
我不认为这会在 Swift 中经常出现,因为 Swift 主要是一种命令式语言,几乎在所有情况下都隐藏了它的 Void
。但是当 Scala 等函数式语言过渡到命令式编程时,您确实会看到类似的事情出现。