Swift type(of:) function signature - swift

I'm trying to implement function that returns simple name of value type:
func typeName(of value: Any) -> String {
return String(describing: type(of:value))
}
But when I try to call it before super.init call:
class SuperTest {
init(name: String) {
print(name)
}
}
class Test: SuperTest {
init() {
// super.init(name: String(describing: type(of: self)))
super.init(name: typeName(of: self))
}
}
Test()
it fails with:
'self' used before super.init call
which is totally clear to me.
But when I inline typeName(of:) body code (commented line) then it compiles and prints expected "Test" result.
Why does this magic happen and how can I use typeName(of:) before super.init() like type(of:)?
Also I can not find any information (function signature) about type(of:) in Swift docs or source code.

Even though it looks like it type(of:) is not a function, it is handled statically by the compiler as a Dynamic Type Expression. For this reason you can use it before calling super.init.
With your custom function the compiler doesn't know that you are not actually using the value so it can't allow the call.

Also I can not find any information (function signature) about type(of:)
Because it is not a function defined by the standard library. It is a primitive, i.e. it's part of the language. As the original Release Notes expressed it:
a new primitive function type(of:) has been added to the language [emphasis mine]
You might almost think of it as an operator. (That, indeed, was the whole point of its creation, as suggested in the original proposal.)

Related

Using Cuckoo with Swift, why is the call to `stub` complaining that the class from GeneratedMocks doesn't conform to Mock protocol?

Using Cuckoo 1.4.1, I get the error
Global function 'stub(_:block:)' requires that 'DeepFileManager' conform to 'Mock'
I don't know how to proceed, because the instance passed to the stub function was created from the class in GeneratedMocks.swift. The reference to DeepFileManager is the class that is mocked.
So it's a mystery to me why Swift 4 would complain about the conformance of the superclass of the instance I've passed to it. Can you lead me out of this conundrum?
Here's the code for the test:
class RecordingTests: QuickSpec {
override func spec() {
let FAKE_ID = "String";
let mockFileManager: MockDeepFileManager = MockDeepFileManager()
let cut = Recording(id: FAKE_ID, date: nil, status: nil, device: nil, deviceId: nil, deviceName: nil, fileManager: mockFileManager)
describe("A recording") {
context("when it's not on disk") {
it("responds that filePresent is false") {
stub(mockFileManager) {stub in
when(stub.fileExists(audioId: FAKE_ID)).then()
}
expect(cut.filePresent()).to(equal(false))
verify(mockFileManager).fileExists(audioId: "Matchable")
}
}
}
}
And here's the declaration of MockDeepFileManager from GeneratedMocks.swift:
class MockDeepFileManager: DeepFileManager, Cuckoo.ClassMock {
As noted in the comment, an issue was submitted against the package, and the response explains how to make it work.
The problem in the code was calling then() (with no arguments), as then requires a closure function with a signature to match the signature of the stubbed function. A simpler alternative that would achieve the aim is thenReturn (instead of then), which just needs a value of the type of the stubbed function's return.
The maintainer of the Cuckoo package expressed sympathy that Swift issues an error about the protocol, instead pointing to the error in the invocation of then.

Extension with a generic where clause is not beeing called

The following code works just as expected:
protocol Storeable {
associatedtype Value
func create(value: Value)
}
struct DefaultStore<V>: Storeable {
typealias Value = V
func create(value: V) {
print("base impl. is called with value type: \(String(describing: V.self))")
}
}
class Event {
var title: String = ""
init(title: String) {
self.title = title
}
}
extension DefaultStore where Value: Event {
func create(value: V) {
print("event impl. is called with event: \(value.title)")
}
}
DefaultStore().create(value: Event(title: "Dance Party"))
// prints "event impl. is called with event: Dance Party"
DefaultStore().create(value: "a string object")
// prints "base impl. is called with value of type: String"
Basically I call a function on the generic class DefaultStore and the compiler calls the correct implementation depending on the underlying type.
Now I have a scenario where I want the exact same thing except, that it is wrapped in another object called Wrapper:
struct Wrapper<StoreType: Storeable,ValueType> where StoreType.Value == ValueType {
let store: StoreType
func create(value: ValueType) {
store.create(value: value)
}
}
let defaultStore = DefaultStore<Event>()
let wrapper = Wrapper(store: defaultStore)
wrapper.create(value: Event(title: "Düsseldorfer Symphoniker"))
// prints: "base impl. is called with value of type: Event"
Here I expect that the extension for Event is called but instead the base implementation is called. Anyone any idea what I am doing wrong?
--
Update:
#matt was guessing that there might be a compile time issue: "without the wrapper when you say DefaultStore().create... the Event info can be read all the way back to the DefaultStore generic parameterized type. But in your wrapper the DefaultStore is created first so it is the general type and that's all it is."
I believe that is not the case because you can also create the DefaultsStore first and it's still working without the Wrapper. Also the compiler warns me if the types don't match.
Nothing to do with "wrappers".
You seem to think that a where extension on a generic struct is a kind of substitute for some sort of dynamic dispatch, i.e. we're going to wait until runtime, look to see what kind of object the parameter to create really is, and dispatch accordingly. That's not how it works. Everything has to be resolved at compile time. At compile time, what we know is that you are not calling create with an Event — you are calling it with a ValueType. So it passes into the create with generic V.
So, for example:
struct Wrapper {
let store: DefaultStore<Event>
func create(value: Event) {
store.create(value: value)
}
}
That works the way you have in mind because we are exposing the fact that this is an Event as far as the DefaultStore is concerned at the point of calling create.
That's just a guess at what your confusion is.
Another possibility is you might imagine that the generic resolution of ValueType somehow "leaks" up to the resolution of V, but that's not true either.
Yet another possibility is you might suppose that a DefaultStore<Event> is a subtype of DefaultStore<Storable> or similar, as if there were dynamic dispatch for parameterized types, but that is exactly what is not the case. Everything has to be known completely at compile time at the call site.

How Do I Instantiate AnyGenerator<T> in Swift?

So I'm trying to use AnyGenerator to wrap a generic GeneratorType, however I'm getting the error:
Argument passed to call that takes no argument
This seems to extend from a weird ambiguity as there is both an AnyGenerator struct (the one I expect) and an AnyGenerator class intended as an abstract class for implementations to extend.
However I don't have any idea how to specify one over the other, as all documentation I can find suggests I should just use:
let someGenerator = ["foo"].generate()
let anyGenerator = AnyGenerator(someGenerator)
Is there something else that I can do instead? For extra fun it seems there's also an anyGenerator global function, just to make sure no-one has any idea what's going on ;)
You can use the anyGenerator<G : GeneratorType>(_: G) function to create your AnyGenerator<...> instance
signature:
func anyGenerator<G : GeneratorType>(base: G) -> AnyGenerator<G.Element>
description:
Return a GeneratorType instance that wraps base but whose type depends only on the type of G.Element.
Example:
struct Foo : GeneratorType {
typealias Element = String
mutating func next() -> String? {
return "foo"
}
}
var bar = anyGenerator(Foo())
func foofoo(bar: AnyGenerator<String>) {
print("foobar")
}
foofoo(bar) // "foobar", ok
As I wrote in my comment to your question, you should probably avoid the specific name anyGenerator specifically since there exists a global native function anyGenerator(..).
Also, please see #MartinR:s comment to your question above; the two global anyGenerator functions are soon-to-be deprecated (Swift 2.2), and will be removed in Swift 3.0, in favour of initializers on AnyGenerator.

Bottom Type in Swift

I'm wondering if there is bottom type in the Swift language.
To weed out any confusion beforehand, unit type is a different kind than bottom type as we have it as Void or () in swift. Also Any is top type.
What I've found to be the closest, surprisingly, is #noreturn attribute in the form of fatalError() in that we can mostly pass this function to conform to most given arbitrary type.
But, of course, this is incomplete and thus a bad substitute for a true bottom type as, for example, Nothing in Scala, undefined in Haskell or even null in Java.
So, is there a bottom type in Swift language?
Turns out there is no Bottom Type in swift, but we can mock its general behavior through few hacks with #noreturn attribute and generics as explained in this talk.
func undefined<A>(_ message: String = "") -> A {
fatalError("Not Implemented: \(message)")
}
Then we can use it to mark yet-implemented parts of our code to pass compiler errors:
func someComplexFunction<U: User>(u: U) -> U {
return undefined("Do this after creating user")
}
Or to prove some invariances in our code:
let array = ["hello", "world"]
let hello: String = array.first ?? undefined("This is impossible!")
see Never
Basically, you can just do
func foo() -> Never {
// you can't return
}

Swift: How to access value of "_" parameter?

I noticed that this is a valid function in Swift:
func test(_:String) {
print("How do I access '_'?")
}
How do I access the parameter?
EDIT
Additional question, is there a valid/good use-case for this?
How do I access the param?
You don't. Using that syntax you are explicitly saying you don't want to access the param.
Use case
Lets say you have access to a very powerful async API like the following.
func theAnswerToLife(success:(answer: String) -> (), failure:(error: NSError) -> ())
yes, of course I am keeping the implementation secret
Now if the function theAnswerToLife does find the answer it calls the success closure, otherwise failure is invoked.
You are forced to pass both closure/functions but you are really interested only in the answer, if something goes wrong you don't mind about the actual error.
So you could define
func tellEveryone(answer: String) {
print("The answer to life is " + answer)
}
func badNews(_:NSError) {
print("Something went wrong, we will try again tomorrow")
}
badNews can be passed as second param to theAnswerToLife and who in future will look at the code will immediately understand that badNews does not care about the received param.
theAnswerToLife(tellEveryone, failure: badNews)
This is so called wildcard matching pattern, and it is introduced just for the sake of not being able to use a parameter, because you just do not care about it.
From documentation:
A wildcard pattern matches and ignores any value and consists of an underscore (_). Use a wildcard pattern when you don’t care about the values being matched against.
You have to use a proper identifier if you need to access the argument value.
Regarding updated part of your question. I do not know why would you want to do this (just a wild idea), but if you want to completely hide argument names of a method of a public class but still be able to use them in private sub-class, you can do something like:
public class Foo {
func test(_: String, _: Int) {
print("[Ignored]")
}
}
private class Bar: Foo {
override func test(stringArgument: String, _ intArgument: Int) {
print("\(stringArgument) \(intArgument)")
}
}
Anyone external, using your library, would use abstract Foo without knowing parameter names of test method.
The point of using _ is that you are not interested in using the parameter. An example usage is this
if let _ = someVariable as? String {
//Do stuff here if someVariable is a string
//But I'm not interested in accessing the unwrapped value, so I set the unwrapped variable name to _
}