Why does this recursive Swift enum hang XCode? - swift

If I enter the following code in a REPL or Playground or main project, it just hangs when it attempts to create the empty list.
import Cocoa
public final class Box<T> {
private let _value : () -> T
public init(_ value : T) {
self._value = { value }
}
public var value: T {
return _value()
}
}
public enum List<U> {
case Empty
case Cons(U, Box<List<U>>)
}
var l = List<Int>.Empty;
I know this is a popular technique used to get around the fact that Swift doesn't let enums be truly recursive without some indirection (served by the Box class in this example).
I mean it's done here in this project, so I assume this works for some people.
I uninstalled and reinstalled XCode thinking somehow I had some "bad bits" left over from previous beta versions. Anyone else have this issue?
UPDATE 11/17/2015: Of course this question and answer are now obsolete. Please see how to define Recursive Enumerations here: Swift Programming Language - Enumerations

Was working with someone on this and they resolved it.
https://github.com/typelift/swiftz/issues/114
https://github.com/typelift/swiftz/pull/120
The answer is to box the first parameter of Cons as well (you can use an autoclosure) like this Cons(#autoclosure () -> U, Box<List<U>>) and that will fix it. A rdar was filed.

Related

Swift: casting un-constrained generic type to generic type that confirms to Decodable

Situation
I have a two generic classes which will fetch data either from api and database, lets say APIDataSource<I, O> and DBDataSource<I, O> respectively
I will inject any of two class in view-model when creating it and view-model will use that class to fetch data it needed. I want view-model to work exactly same with both class. So I don't want different generic constraints for the classes
// sudo code
ViewModel(APIDataSource <InputModel, ResponseModel>(...))
// I want to change the datasource in future like
ViewModel(DBDataSource <InputModel, ResponseModel>(...))
To fetch data from api ResponseModel need to confirms to "Decodable" because I want to create that object from JSON. To fetch data from realm database it need to inherit from Object
Inside ViewModel I want to get response like
// sudo code
self.dataSource.request("param1", "param2")
If developer tries to fetch api data from database or vice-versa it will check for correct type and throws proper error.
Stripped out version of code for playground
Following is stripped out version of code which shows what I want to achieve or where I am stuck (casting un-constrained generic type to generic type that confirms to Decodable)
import Foundation
// Just to test functions below
class DummyModel: Decodable {
}
// Stripped out version of function which will convert json to object of type T
func decode<T:Decodable>(_ type: T.Type){
print(type)
}
// This doesn't give compilation error
// Ignore the inp
func testDecode<T:Decodable> (_ inp: T) {
decode(T.self)
}
// This gives compilation error
// Ignore the inp
func testDecode2<T>(_ inp: T){
if(T.self is Decodable){
// ??????????
// How can we cast T at runtime after checking T confirms to Decodable??
decode(T.self as! Decodable.Type)
}
}
testDecode(DummyModel())
Any help or explanation that this could not work would be appreciated. Thanks in advance :)
As #matt suggests, moving my various comments over to an answer in the form "your problem has no good solution and you need to redesign your problem."
What you're trying to do is at best fragile, and at worst impossible. Matt's approach is a good solution when you're trying to improve performance, but it breaks in surprising ways if it impacts behavior. For example:
protocol P {}
func doSomething<T>(x: T) -> String {
if x is P {
return "\(x) simple, but it's really P"
}
return "\(x) simple"
}
func doSomething<T: P>(x: T) -> String {
return "\(x) is P"
}
struct S: P {}
doSomething(x: S()) // S() is P
So that works just like we expect. But we can lose the type information this way:
func wrapper<T>(x: T) -> String {
return doSomething(x: x)
}
wrapper(x: S()) // S() simple, but it's really P!
So you can't solve this with generics.
Going back to your approach, which at least has the possibility of being robust, it's still not going to work. Swift's type system just doesn't have a way to express what you're trying to say. But I don't think you should be trying to say this anyway.
In the method that fetch data I will check type of generic type and if it confirms to "Decodable" protocol I will use it to fetch data from api else from database.
If fetching from the API vs the database represents different semantics (rather than just a performance improvement), this is very dangerous even if you could get it to work. Any part of the program can attach Decodable to any type. It can even be done in a separate module. Adding protocol conformance should never change the semantics (outwardly visible behaviors) of the program, only the performance or capabilities.
I have a generic class which will fetch data either from api or database
Perfect. If you already have a class, class inheritance makes a lot of sense here. I might build it like:
class Model {
required init(identifier: String) {}
}
class DatabaseModel {
required init(fromDatabaseWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromDatabaseWithIdentifier: identifier )}
}
class APIModel {
required init(fromAPIWithIdentifier: String) {}
convenience init(identifier: String) { self.init(fromAPIWithIdentifier: identifier )}
}
class SomeModel: DatabaseModel {
required init(fromDatabaseWithIdentifier identifier: String) {
super.init(fromDatabaseWithIdentifier: identifier)
}
}
Depending on your exact needs, you might rearrange this (and a protocol might also be workable here). But the key point is that the model knows how to fetch itself. That makes it easy to use Decodable inside the class (since it can easily use type(of: self) as the parameter).
Your needs may be different, and if you'll describe them a bit better maybe we'll come to a better solution. But it should not be based on whether something merely conforms to a protocol. In most cases that will be impossible, and if you get it working it will be fragile.
What you'd really like to do here is have two versions of testDecode, one for when T conforms to Decodable, the other for when it doesn't. You would thus overload the function testDecode so that the right one is called depending on the type of T.
Unfortunately, you can't do that, because you can't do a function overload that depends on the resolution of a generic type. But you can work around this by boxing the function inside a generic type, because you can extend the type conditionally.
Thus, just to show the architecture:
protocol P{}
struct Box<T> {
func f() {
print("it doesn't conform to P")
}
}
extension Box where T : P {
func f() {
print("it conforms to P")
}
}
struct S1:P {}
struct S2 {}
let b1 = Box<S1>()
b1.f() // "it conforms to P"
let b2 = Box<S2>()
b2.f() // "it doesn't conform to P"
This proves that the right version of f is being called, depending on whether the type that resolves the generic conforms to the protocol or not.

How do you do java equivalent of Generic callback interface in Swift

In java you can declare an interface like this
public interface Foo<T>
{
public void doFoo(T result);
}
And you can use this as a type parameter in another method like this
public void doSomeAsyncTask(final Foo<MyObject> foo)
{
Runnable asyncRunnable = new Runnable()
{
#Override
void run()
{
MyObject result;
// do task to get result
foo.doFoo(result);
}
};
Thread asyncThread = new Thread(asyncRunnable);
asyncThread.start();
}
foo.doFoo(result);
}
As you can see I used the interface for callback from some asynchronous task that runs on a different thread.
UPDATE
Following this guide, I have come up with a solution similar to this
public protocol GenericProtocol {
associatedType T
func magic(result:T)
}
class GenericProtocolThunk<T> : GenericProtocol {
private let _magic : (T)
init<P : GenericProtocol where P.T == T>(_dep : P) {
_magic = p.magic
}
func magic(result: T) {
_magic(result)
}
}
Now in my doSomeAsyncTask method I can just pass GenericProtocolThunk<MyObject> as the parameter type. Is this the right way to achieve what I asked in the question? Honestly it looks quite ugly to me.
I think your problem boils indeed down to what is also noted in the blog post you link to:
"Protocols in Swift can be generic via abstract type members rather
than parameterisation. Consequently, the protocol itself can no longer
be used as a type but only as a generic constraint."
The (ugly) thunk based workaround looks like it solves your problem indeed, although to verify it would help if in your question you used similar terminology for both your Java and Swift examples, and they would be complete, including the type that actually contains the doSomeAsyncTask method to avoid possible confusions.
I can think of a few alternative more Swift friendly solutions if you can change the formulation a bit.
If you could describe Result too with a protocol, then the language isn't fighting against you quite so much. Compared to Java, conforming to a protocol (= implementing an interface) is also not limited to just class types, as shown in the below example so arguably you get a bit more rather out of the language to this end, than in Java:
import Foundation
protocol Result {
// any restrictions on Result that you need.
}
class A:Result { }
struct B:Result { }
enum C:Result { case X }
protocol Foo {
func doFoo(result:Result) -> Void
}
class Bar {
func doSomeAsyncTask(foo:Foo) -> Void {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
foo.doFoo(A())
foo.doFoo(B())
foo.doFoo(C.X)
}
}
}
Another alternative that I've used only recently myself in a related sort of problem is to model result as an enum which enumerates the possible result types, like below (incidentally, each of BibliographyItem, InlineMathFragment, Equation, BlockElement, InlineElement in my code example below are themselves protocols, not concrete types):
public enum Result {
case None
case BibliographyItems([BibliographyItem])
case InlineMathFragments([InlineMathFragment])
case Equations([Equation])
case BlockElements([BlockElement])
case InlineElements([InlineElement])
}
This is handy in a situation where your results come from some already known set of result types, and you commonly end up needing to deal with them in some conditional form.
You may want to simplify it to:
func doSomeAsyncTask<T>(callback: (T)->Void)
Check out this great video:
Rob Napier: Beyond Crusty: Real world protocols

Generic method override not working in swift

There is a protocol Printable and a struct Printer from a 3rd Party.
protocol Printable {}
struct Printer {
static func print<T>(object: T) -> String {
return "T"
}
static func print<T: Printable>(object: T) -> String {
return "Printable"
}
}
Now i am making a generic
struct Generic<T> {
var args: T
func display() {
print(Printer.print(args))
}
}
and two structs
struct Obj {}
struct PrintableObj: Printable {}
var obj = Generic(args: Obj())
var printableObj = Generic(args: PrintableObj())
When i call the display functions on both of them.
obj.display()
displays T
printableObj.display()
displays T but i want it to print "Printable"
One solution i can think of is having two different generics
struct Generic<T>
struct PrintableGeneric<T: Printable>
Is there any other solution without changing the Printable protocol and Printer struct.
static func print<T>(object: T) -> String {
if object is Printable {
return "Printable"
} else {
return "T"
}
}
Yes. But the answer is a bit weird. The first part makes a decent amount of sense; the second part is just totally weird. Let's walk through it.
struct Generic<T> {
var args: T
func display() {
print(Printer.print(args))
}
}
The correct overload to choose for print is decided at compile time, not runtime. This is the thing that confuses people the most. They want to treat Swift like JavaScript where everything is dynamic. Swift likes to be static because then it can make sure your types are right and it can do lots of optimizations (and Swift loves to do compiler optimizations). So, compile time, what type is args? Well, it's T. Is T known to be Printable? No it is not. So it uses the non-Printable version.
But when Swift specializes Generic using PrintableObj, doesn't it know at that point that it's Printable? Couldn't the compiler create a different version of display at that point? Yes, if we knew at compile time every caller that would ever exist of this function, and that none of them would ever be extended to be Printable (which could happen in a completely different module). It's hard to solve this without creating lots of weird corner cases (where internal things behave differently than public things for instance), and without forcing Swift to proactively generate every possible version of display that might be required by some future caller. Swift may improve in time, but this is a hard problem I think. (Swift already suffers some performance reductions so that public generics can be specialized without access to the original source code. This would make that problem even more complicated.)
OK, so we get that. T isn't Printable. But what if we had a type that was unambiguously Printable that we knew at compile time and lived inside this function? Would it work then?
func display() {
if let p = args as? Printable {
print(Printer.print(p))
} else {
print(Printer.print(args))
}
}
Oh so close... but not quite. This almost works. The if-let actually does exactly what you want it to do. p gets assigned. It's Printable. But it still calls the non-Printable function. ?!?!?!?!
This is a place I personally think that Swift is just currently broken and have high hopes it will be fixed. It might even be a bug. The problem is that Printable itself does not conform to Printable. Yeah, I don't get it either, but there you go. So we need to make something that does conform to Printable in order to get the right overload. As usual, type erasers to the rescue.
struct AnyPrintable: Printable {
let value: Printable
}
struct Generic<T> {
var args: T
func display() {
if let p = args as? Printable {
print(Printer.print(AnyPrintable(value: p)))
} else {
print(Printer.print(args))
}
}
}
And this will print the way you wanted. (On the assumption that Printable requires some methods, you'd just add those methods to the AnyPrintable type eraser.)
Of course the right answer is not to use generic overloads this way in Printer. It's just way too confusing and fragile. It looks so nice, but it blows up all the time.
To my mind, the only option you have - is to use if-else with type casting in "print()" function
static func print<T>(object: T) -> String {
if let _ = object as? Printable {
return "Printable"
}
return "T"
}
or non-generic variant
static func print(object: Any) -> String {
if let _ = object as? Printable {
return "Printable"
}
return "T"
}

Xcode6.3.2 Swift bug with static constants

I am trying to figure out why I am having constant compile problems with this type of construct in Xcode 6.3.2.
class Foo {
static let CONSTANT_NAME = "CONSTANT_STRING"
...
func bar () -> String {
var s = String(format:"%s,%d\n", CONSTANT_NAME, 7)
return s
}
...
}
As I understand the language, this should be perfectly legal code however Xcode is constantly (hah-pun) having issues with it raising the error
"there is no member CONSTANT_NAME in class Foo"
If I get lucky and force it to clean, and then rebuild it will some times sort itself out and work. Other times, even doing that, then trying an open/close project will still not resolve the issue.
So, I guess my implicit follow up question (if the answer to the above is - it is legal code) is: is the Xcode Swift compiler that buggy that even basic things like this are likely to cause problems? If so, swift seems to be in a pretty bad state.
static is class property, that means you have to call it like this ClassName.property
class Foo {
static let CONSTANT_NAME = "CONSTANT_STRING"
func bar () -> String {
var s = String(format:"%s,%d\n", Foo.CONSTANT_NAME, 7)
return s
}
}
That is not a bug. That is what it should be. A class property "belongs" to the class.
If you want your code work without using ClassName, do not use static
class Foo {
let CONSTANT_NAME = "CONSTANT_STRING"
func bar () -> String {
var s = String(format:"%s,%d\n",CONSTANT_NAME, 7)
return s
}
}
More details in the Apple Documentation
The static let syntax is legal and valid. The issue is that you must fully qualify that variable when you access it:
var s = String(format:"%s,%d\n", Foo.CONSTANT_NAME, 7)
The compiler error is a bit obtuse, but it is telling the truth... CONSTANT_NAME is not a member, but a type property of class Foo: Swift Type Properties
I hear you about saving key strokes. I've personally been trying to make my Swift code as idiomatic as possible by milking every short cuts but when you find code like this, you should be glad that the compiler asks you to keep on the safe side:
class Foo {
static let CONSTANT = "hello"
func bar() -> String {
let CONSTANT = "bye"
return CONSTANT // I know which one! Thanks Swift!
}
}
println(Foo.CONSTANT)
println(Foo().bar())

Swift generics and protocols issue

I'm trying to push MVVM patterns on my application, but I've found that quite difficult using Swift and Generics. Example:
I have a Comic struct on my model layer. But I want my viewControllers to consume objects conforming ComicViewModel protocol in order to increase separation of concerns.
I'm wrapping the model structs in a class called Box defined like this:
public class Box<T> {
public let value: T
public init(_ value: T) { self.value = value }
}
This is used only to wrap the actual return value in a Result enum like the one explained here
However, the Swift compiler doesn't seem to like the cast from Comic to ComicViewModel even if I'm clearly defining that
func sampleComics() -> Box<Comic> {...}
protocol ComicViewModel {...}
extension Comic : ComicViewModel {...}
func fetchComicsViewModel() -> Box<ComicViewModel> {
return sampleComics() //ERROR
}
Full playground available here.
Thanks a lot for your help!
Sad to say, Swift doesn't perform implicit casting like that. As of now, you have to re-Box() the value.
func fetchComicsViewModel() -> Box<ComicViewModel> {
return Box(sampleComics().value)
}