Are there any possible explicit uses of instances (values) of empty tuples (), i.e., of instances of typealias 'Void'?
There are lots of places that ()
can be useful when playing around with "CS" problems, which often have the form "implement X using Y even though you really already have X." So for instance, I might say, implement Set using Dictionary. Well, a Dictionary is a Key/Value pair. What should the type of the Value be? I've actually seen this done in languages that have Dictionaries but not Sets, and people often use 1 or true as the value. But that's not really what you mean. That opens up ambiguity. What if the value is false? Is it in the set or not? The right way to implement Set in terms of Dictionary is as [Key: ()]
, and then you wind up with lines of code like:
set[key] = ()
There are other, equivalent versions, like your Optional<()>
. I could also implement integers as [()]
or Set<()>
. It's a bit silly, but I've done things like that to explore number theory before.
That said, these are all almost intentionally impractical solutions. How about a practical one? Those usually show up when in generic programming. For example, imagine a function with this kind of form:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
This isn't as silly as it sounds. Something along these lines could easily show up in a Command pattern. But what if there's no retval; I don't care about the return? Well, that's fine, just pass a ()
value.
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
Similarly, you might want a function like zipMap
:
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { $0($1) }
}
This applies a series of functions that take T
to values of type T
. We could use that even if T
happens to ()
, but we'd have to generate a bunch of ()
values to make that work. For example:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
I wouldn't expect this to come up very often in Swift because Swift is mostly an imperative language and hides its Void
in almost all cases. But you really do see things like this show up in functional languages like Scala when they bridge over into imperative programming.
What is type '()' in swift?
()
is both a type (and Void
is a type alias for the empty tuple type) and the only value of that type. So
let x = ()
defines x
as a constant property of type ()
(aka Void
) with the value ()
.
Equivalent statements would be
let x:() = ()
let x:Void = ()
but not
let x = Void // error: expected member name or constructor call after type name
because Void
is a type but not a value.
When defining function types with no parameters and/or no return value
there seems to be a consensus to use ()
for an empty parameter list,
and Void
for no return value. This can for example be seen in
UIKit completion handlers, or for execution blocks submitted to
GCD dispatch queues, e.g.
func sync(execute block: () -> Void)
What is return type () ?
Your function iterateItems
has removeItem
addItem
calculateEfficiency
parameter is function type. So you must use function name as params when call function.
like this:
iterateItems(itemArray: WeaponItems.weaponItems, removeItem: removeWeaponItem, addItem: addWeaponItem, calculateEfficiency: calcWeaponDamage)
Are there any possible explicit uses of instances (values) of empty tuples (), i.e., of instances of typealias 'Void'?
There are lots of places that ()
can be useful when playing around with "CS" problems, which often have the form "implement X using Y even though you really already have X." So for instance, I might say, implement Set using Dictionary. Well, a Dictionary is a Key/Value pair. What should the type of the Value be? I've actually seen this done in languages that have Dictionaries but not Sets, and people often use 1 or true as the value. But that's not really what you mean. That opens up ambiguity. What if the value is false? Is it in the set or not? The right way to implement Set in terms of Dictionary is as [Key: ()]
, and then you wind up with lines of code like:
set[key] = ()
There are other, equivalent versions, like your Optional<()>
. I could also implement integers as [()]
or Set<()>
. It's a bit silly, but I've done things like that to explore number theory before.
That said, these are all almost intentionally impractical solutions. How about a practical one? Those usually show up when in generic programming. For example, imagine a function with this kind of form:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
This isn't as silly as it sounds. Something along these lines could easily show up in a Command pattern. But what if there's no retval; I don't care about the return? Well, that's fine, just pass a ()
value.
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
Similarly, you might want a function like zipMap
:
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { $0($1) }
}
This applies a series of functions that take T
to values of type T
. We could use that even if T
happens to ()
, but we'd have to generate a bunch of ()
values to make that work. For example:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
I wouldn't expect this to come up very often in Swift because Swift is mostly an imperative language and hides its Void
in almost all cases. But you really do see things like this show up in functional languages like Scala when they bridge over into imperative programming.
Variables of type void
Note: This is a crosspost of my reply on the cross-posted question in the Apple Dev Forums.
It's because Swift seems to be a little academically favourable (it's one of Swift's plus points for me! :-) ).
A mathematical function is a relation between some inputs (the arguments) and some outputs (the return values). Instead of defining a whole class (e.g. "subroutine" or "procedure") for which this doesn't apply (no output, specifically), Swift simply defines a "procedure" as a relation with some set of inputs (possibly empty) and an empty set of outputs.
There are some benefits to it, though, albeit uncommon (at least until functional programming becomes the more dominant style in the language and the community). A little example:
infix operator ~~ { precedence 10 associativity right }
func ~~(l: A -> B, r: A) -> B {
return l(r)
}
let productsSoldIn2014 = productOfSales ~~ salesInYears ~~ [2014]
let salespersonsInvolvedIn2014Sales = salespersonsOfSales ~~ salesInYears ~~ [2014]
fireSalespersons ~~ salespersonsOfSales ~~ salesInYears ~~ [2014] // Awful companies only.
func salesInYears(_ y: [Int]) -> [Sale] { … }
func productsOfSales(_ s: [Sale]) -> [Product] { … }
func salespersonsOfSales(_ s: [Sale]) -> [SalesPerson] { … }
func fireSalespersons(_ s: [SalesPerson]) -> () { … } // The appended arrow and null tuple can be left out.
I've defined a "chaining" operator ~~
(think of a bending chain) which, right to left, pushes a value through the chain. With some appropriately named functions, we can declaratively define the values we need. (With lazy collections instead of arrays, we approach Haskell paradigms. Unless I'm mistaken, ~~
is here an identity monad. Or it's just a composition operator.)
The third statement (after the two lets) fires the salespersons that sold anything in the year 2014. Note though that ~~
wants to return "fireSalespersons"'s value (to continue the chain on the left, which here isn't present), which in Swift is valid—it's just the null tuple and we discard it. There's no reason why functions without return value shouldn't work with the operator (without overloading it).
By the way, this is also valid:
increaseCEOBonus(35000) ~~ fireSalespersons ~~ salespersonsOfSales ~~ salesInYears ~~ [2014] // Really awful companies only.
// () -> () ~~ [Salesperson] -> () ~~ [Sales] -> [Salesperson] …
func increaseCEOBonus(amount: Int)() { … }
In this example, the leftmost chain is value-less—it's still left after right, but there aren't any values passed to the left. I wouldn't recommend this use though, it's better to simply enumerate each of them on a separate line.
To return to your question, since "nothing" can be consumed (via arguments), it'd be silly to explicitly prohibit "nothing" to be assigned to a variable—arguments are variables.
P.S.: Before anybody asks: yes, I did want to have an excuse to make a contrived example; it was just to test my ability to write complex types.
Swift running sum
The general combinator you're looking for is often called scan
, and can be defined (like all higher-order functions on lists) in terms of reduce
:
extension Array {
func scan<T>(initial: T, _ f: (T, Element) -> T) -> [T] {
return self.reduce([initial], combine: { (listSoFar: [T], next: Element) -> [T] in
// because we seeded it with a non-empty
// list, it's easy to prove inductively
// that this unwrapping can't fail
let lastElement = listSoFar.last!
return listSoFar + [f(lastElement, next)]
})
}
}
(But I would suggest that that's not a very good implementation.)
This is a very useful general function, and it's a shame that it's not included in the standard library.
You can then generate your cumulative sum by specializing the starting value and operation:
let cumSum = els.scan(0, +)
And you can omit the zero-length case rather simply:
let cumSumTail = els.scan(0, +).dropFirst()
Return in function without return value in Swift
The following signatures all return an instance of the empty tuple ()
(typealiased as Void
).
func implicitlyReturnEmptyTuple() { }
func explicitlyReturnEmptyTuple() {
return ()
}
func explicitlyReturnEmptyTupleAlt() {
return
}
In all of the three above, the return type of the function, in the function signature, has been omitted, in which case it is implicitly set to the empty tuple type, ()
. I.e., the following are analogous to the three above
func implicitlyReturnEmptyTuple() -> () { }
func explicitlyReturnEmptyTuple() -> () {
return ()
}
func explicitlyReturnEmptyTupleAlt() -> () {
return
}
With regard to your comment below (regarding body of implicitlyReturnEmptyTuple()
where we don't explicitly return ()
); from the Language Guide - Functions: Functions without return values:
Functions are not required to define a return type. Here’s a version
of thesayHello(_:)
function, calledsayGoodbye(_:)
, which prints
its ownString
value rather than returning it:func sayGoodbye(personName: String) {
print("Goodbye, \(personName)!")
}
...
Note
Strictly speaking, the
sayGoodbye(_:)
function does still return a
value, even though no return value is defined. Functions without a
defined return type return a special value of typeVoid
. This is
simply an empty tuple, in effect a tuple with zero elements, which can
be written as()
.
Hence, we may omit return ...
only for ()
-return (Void
-return) function, in which case a ()
instance will be returned implicitly.
Difference between returning Void and () in a swift closure
If you look into headers, you will see that Void is typealias for (),
/// The empty tuple type.
///
/// This is the default return type of functions for which no explicit
/// return type is specified.
typealias Void = ()
You can verify that using playground like this,
let a = Void()
print(a) // prints ()
Update
If you wish to see the declaration of Void in header file, in the above code, type the code below in swift playground or xcode editor like so,
let a: Void = ()
Then, cmd + click on the "Void" keyword in above expression, you will be taken to the header file where you can actually see the declaration for Void.
The document has been updated with more information which is like this,
/// The return type of functions that don't explicitly specify a return type;
/// an empty tuple (i.e., `()`).
///
/// When declaring a function or method, you don't need to specify a return
/// type if no value will be returned. However, the type of a function,
/// method, or closure always includes a return type, which is `Void` if
/// otherwise unspecified.
///
/// Use `Void` or an empty tuple as the return type when declaring a
/// closure, function, or method that doesn't return a value.
///
/// // No return type declared:
/// func logMessage(_ s: String) {
/// print("Message: \(s)")
/// }
///
/// let logger: (String) -> Void = logMessage
/// logger("This is a void function")
/// // Prints "Message: This is a void function"
public typealias Void = ()
Get Type Argument of Arbitrarily High Generic Parent Class at Runtime
The following approach is based on __class_getitem__
and __init_subclass__
. It might serve your use case, but it has some severe limitations (see below), so use at your own judgement.
from __future__ import annotations
from typing import Generic, Sequence, TypeVar
T = TypeVar('T')
NO_ARG = object()
class Parent(Generic[T]):
arg = NO_ARG # using `arg` to store the current type argument
def __class_getitem__(cls, key):
if cls.arg is NO_ARG or cls.arg is T:
cls.arg = key
else:
try:
cls.arg = cls.arg[key]
except TypeError:
cls.arg = key
return super().__class_getitem__(key)
def __init_subclass__(cls):
if Parent.arg is not NO_ARG:
cls.arg, Parent.arg = Parent.arg, NO_ARG
class Child1(Parent[int]):
pass
class Child2(Child1):
pass
class Child3(Parent[T], Generic[T]):
pass
class Child4(Parent[Sequence[T]], Generic[T]):
pass
def get_parent_type_parameter(cls):
return cls.arg
classes = [
Parent[str],
Child1,
Child2,
Child3[int],
Child4[float],
]
for cls in classes:
print(cls, get_parent_type_parameter(cls))
Which outputs the following:
__main__.Parent[str] <class 'str'>
<class '__main__.Child1'> <class 'int'>
<class '__main__.Child2'> <class 'int'>
__main__.Child3[int] <class 'int'>
__main__.Child4[float] typing.Sequence[float]
This approach requires that every Parent[...]
(i.e. __class_getitem__
) is followed by an __init_subclass__
because otherwise the former information may be overwritten by a second Parent[...]
. For that reasons it won't work with type aliases for example. Consider the following:
classes = [
Parent[str],
Parent[int],
Parent[float],
]
for cls in classes:
print(cls, get_parent_type_parameter(cls))
which outputs:
__main__.Parent[str] <class 'float'>
__main__.Parent[int] <class 'float'>
__main__.Parent[float] <class 'float'>
Related Topics
Change Background Color of Texteditor in Swiftui
Swift 3: Atomic_Compare_Exchange_Strong
Swift 3.0 Iterate Over String.Index Range
How to Check the Network Speed Using Swift
How to Compare "Any" Value Types
How Does Dictionary Use the Equatable Protocol in Swift
Swiftui: Prevent Image() from Expanding View Rect Outside of Screen Bounds
How to Open Your App in Settings iOS 11
What Is the Practical Use of Nested Functions in Swift
Keyboard Overlaying Action Sheet in iOS 13.1 on Cncontactviewcontroller
How to Limit the Movement of Two Anchored Lines So They Swing Continually Like a Pendulum
Division Not Working Properly in Swift
Is There an Alternative to Initialize() in MACos Now That Swift Has Deprecated It
Swiftui Exporting or Sharing Files
How to Get the Height of a Uilabel in Swift
How to Open Settings App Programmatically
In Swift, How to Get Memory Back to Normal After an Skscene Is Removed