Re: [swift-users] Re-initializing lazy vars

2017-10-19 Thread David Sweeris via swift-users
I don't know. IIRC (big if), though, there was talk of adding support for 
"property behaviors"(?). Resetting lazy vars probably would've been one of 
them, and if so, it probably got pulled so that we wouldn't risk breaking 
source compatibility later by adding a consistent syntax for other behaviors. I 
think. I wish I could remember who'd brought up the idea... they'd probably 
know straight away if that's what happened.

- Dave Sweeris

> On Oct 19, 2017, at 5:40 PM, Rick Mann via swift-users 
>  wrote:
> 
> Googling for the answer, it seemed some versions of Swift supported setting a 
> lazy var property to nil, such that the next time it's accessed, the 
> initializer would be run again.
> 
> But I just tried this in a playground in Swift 4 and it doesn't work.
> 
> It sure seems to me like it should work. What's the reasoning for the current 
> behavior?
> 
> -- 
> Rick Mann
> rm...@latencyzero.com
> 
> 
> ___
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


[swift-users] Re-initializing lazy vars

2017-10-19 Thread Rick Mann via swift-users
Googling for the answer, it seemed some versions of Swift supported setting a 
lazy var property to nil, such that the next time it's accessed, the 
initializer would be run again.

But I just tried this in a playground in Swift 4 and it doesn't work.

It sure seems to me like it should work. What's the reasoning for the current 
behavior?

-- 
Rick Mann
rm...@latencyzero.com


___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users
Right now, collection types in the standard library (`Array`, 
`Dictionary`, and `Set`) employ a workaround for the lack of conditional 
conformance, which would allow us to expose things like `extension Array 
: Codable where Element : Codable` (i.e. `Array` is `Codable` if and 
only if `T` is `Codable`).
These collections unconditionally conform to `Codable` and trap at 
runtime if the type is not actually `Codable`. The synthesis complaint 
is an explicit check in the compiler so we don’t go ahead and happily 
synthesize code on your behalf that would just trap at runtime.


When the conditional conformance feature lands, `[String : Any]() is 
Codable` should return `false`.


On 19 Oct 2017, at 14:15, Kevin Nattinger wrote:

So, what I see as the problem here is contradictory compiler 
statements:


MyPlayground.playground:5:9: note: cannot automatically synthesize 
'Encodable' because '[String : Any]' does not conform to 'Encodable'

let someDict: [String : Any]
^

warning: MyPlayground.playground:8:18: warning: 'is' test is always 
true

[String : Any]() is Codable
 ^

So is it codable or isn't it? You can use a [String: Any] in encode() 
and decode() directly, so why doesn't it get compiler support? At the 
least, the message needs to be updated to something that's actually 
true.


On Oct 19, 2017, at 1:38 PM, David Sweeris via swift-users 
 wrote:


Oh! Yeah, my bad... You are correct; I'd started thinking like I was 
on -evolution instead of -users.



On Oct 19, 2017, at 1:29 PM, Itai Ferber > wrote:


Mm, the point I’m trying to get at here is that JSON is inherently 
untyped while Swift is strongly typed, and the two don’t line up.
It doesn’t really make sense to ask to decode an existential 
because there’s not enough type information to influence what you 
get back.


On 19 Oct 2017, at 13:20, David Sweeris wrote:

I think if you can figure that out, you’re halfway to letting 
protocols conform to themselves.


(Syntactically, I would probably say that something like 
“Codable.Self” would read well, but I think that already means 
something. Maybe the answer will become clearer when we rework the 
reflection APIs?)


Sent from my iPhone

On Oct 19, 2017, at 13:13, Itai Ferber > wrote:


Even then, that wouldn’t necessarily help in the general case. If 
you decode {"key" : 1} as [String : Codable], what concrete type 
would 1 have? Int? Double? Int8? (Arguments can be made for any one 
of these, but the key here is that it is inherently ambiguous and 
there isn’t necessarily a good answer.)


On 19 Oct 2017, at 12:57, David Sweeris wrote:

On Oct 19, 2017, at 12:50 PM, David Baraff via swift-users 
> wrote:


Yes; this is a case where anywhere in the code base I want to just 
say

struct MyNewType : Codable {
// add codable datatypes
}

and don’t want/can’t always go to the centralized place to add 
it in.
Is there some extension-like trick I can pull off that lets me 
spread the implementation out over different files/libraries?


Ah, ok.

No, I don't think you'll be able to do that until/unless Swift gets 
more macro/metaprogramming features. Maybe if protocols ever get to 
conform to themselves? That's a common request, but implementing it 
is apparently beyond tricky. I'm pretty sure somebody's working on 
it, but "bigger fish" and all that...


- Dave Sweeris





___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users



___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Kevin Nattinger via swift-users
So, what I see as the problem here is contradictory compiler statements:

MyPlayground.playground:5:9: note: cannot automatically synthesize 'Encodable' 
because '[String : Any]' does not conform to 'Encodable'
let someDict: [String : Any]
^

warning: MyPlayground.playground:8:18: warning: 'is' test is always true
[String : Any]() is Codable
 ^

So is it codable or isn't it? You can use a [String: Any] in encode() and 
decode() directly, so why doesn't it get compiler support? At the least, the 
message needs to be updated to something that's actually true. 

> On Oct 19, 2017, at 1:38 PM, David Sweeris via swift-users 
>  wrote:
> 
> Oh! Yeah, my bad... You are correct; I'd started thinking like I was on 
> -evolution instead of -users.
> 
> 
>> On Oct 19, 2017, at 1:29 PM, Itai Ferber > > wrote:
>> 
>> Mm, the point I’m trying to get at here is that JSON is inherently untyped 
>> while Swift is strongly typed, and the two don’t line up.
>> It doesn’t really make sense to ask to decode an existential because there’s 
>> not enough type information to influence what you get back.
>> 
>> On 19 Oct 2017, at 13:20, David Sweeris wrote:
>> 
>> I think if you can figure that out, you’re halfway to letting protocols 
>> conform to themselves.
>> 
>> (Syntactically, I would probably say that something like “Codable.Self” 
>> would read well, but I think that already means something. Maybe the answer 
>> will become clearer when we rework the reflection APIs?)
>> 
>> Sent from my iPhone
>> 
>> On Oct 19, 2017, at 13:13, Itai Ferber > > wrote:
>> 
>>> Even then, that wouldn’t necessarily help in the general case. If you 
>>> decode {"key" : 1} as [String : Codable], what concrete type would 1 have? 
>>> Int? Double? Int8? (Arguments can be made for any one of these, but the key 
>>> here is that it is inherently ambiguous and there isn’t necessarily a good 
>>> answer.)
>>> 
>>> On 19 Oct 2017, at 12:57, David Sweeris wrote:
>>> 
>>> On Oct 19, 2017, at 12:50 PM, David Baraff via swift-users 
>>> > wrote:
>>> 
>>> Yes; this is a case where anywhere in the code base I want to just say
>>> struct MyNewType : Codable {
>>> // add codable datatypes
>>> }
>>> 
>>> and don’t want/can’t always go to the centralized place to add it in.
>>> Is there some extension-like trick I can pull off that lets me spread the 
>>> implementation out over different files/libraries?
>>> 
>>> Ah, ok.
>>> 
>>> No, I don't think you'll be able to do that until/unless Swift gets more 
>>> macro/metaprogramming features. Maybe if protocols ever get to conform to 
>>> themselves? That's a common request, but implementing it is apparently 
>>> beyond tricky. I'm pretty sure somebody's working on it, but "bigger fish" 
>>> and all that...
>>> 
>>> - Dave Sweeris
>>> 
>> 
> 
> ___
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Sweeris via swift-users
Oh! Yeah, my bad... You are correct; I'd started thinking like I was on 
-evolution instead of -users.


> On Oct 19, 2017, at 1:29 PM, Itai Ferber  wrote:
> 
> Mm, the point I’m trying to get at here is that JSON is inherently untyped 
> while Swift is strongly typed, and the two don’t line up.
> It doesn’t really make sense to ask to decode an existential because there’s 
> not enough type information to influence what you get back.
> 
> On 19 Oct 2017, at 13:20, David Sweeris wrote:
> 
> I think if you can figure that out, you’re halfway to letting protocols 
> conform to themselves.
> 
> (Syntactically, I would probably say that something like “Codable.Self” would 
> read well, but I think that already means something. Maybe the answer will 
> become clearer when we rework the reflection APIs?)
> 
> Sent from my iPhone
> 
> On Oct 19, 2017, at 13:13, Itai Ferber  > wrote:
> 
>> Even then, that wouldn’t necessarily help in the general case. If you decode 
>> {"key" : 1} as [String : Codable], what concrete type would 1 have? Int? 
>> Double? Int8? (Arguments can be made for any one of these, but the key here 
>> is that it is inherently ambiguous and there isn’t necessarily a good 
>> answer.)
>> 
>> On 19 Oct 2017, at 12:57, David Sweeris wrote:
>> 
>> On Oct 19, 2017, at 12:50 PM, David Baraff via swift-users 
>> > wrote:
>> 
>> Yes; this is a case where anywhere in the code base I want to just say
>> struct MyNewType : Codable {
>> // add codable datatypes
>> }
>> 
>> and don’t want/can’t always go to the centralized place to add it in.
>> Is there some extension-like trick I can pull off that lets me spread the 
>> implementation out over different files/libraries?
>> 
>> Ah, ok.
>> 
>> No, I don't think you'll be able to do that until/unless Swift gets more 
>> macro/metaprogramming features. Maybe if protocols ever get to conform to 
>> themselves? That's a common request, but implementing it is apparently 
>> beyond tricky. I'm pretty sure somebody's working on it, but "bigger fish" 
>> and all that...
>> 
>> - Dave Sweeris
>> 
> 

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users
Mm, the point I’m trying to get at here is that JSON is inherently 
untyped while Swift is strongly typed, and the two don’t line up.
It doesn’t really make sense to ask to decode an existential because 
there’s not enough type information to influence what you get back.


On 19 Oct 2017, at 13:20, David Sweeris wrote:

I think if you can figure that out, you’re halfway to letting 
protocols conform to themselves.


(Syntactically, I would probably say that something like 
“Codable.Self” would read well, but I think that already means 
something. Maybe the answer will become clearer when we rework the 
reflection APIs?)


Sent from my iPhone


On Oct 19, 2017, at 13:13, Itai Ferber  wrote:

Even then, that wouldn’t necessarily help in the general case. If 
you decode {"key" : 1} as [String : Codable], what concrete type 
would 1 have? Int? Double? Int8? (Arguments can be made for any one 
of these, but the key here is that it is inherently ambiguous and 
there isn’t necessarily a good answer.)


On 19 Oct 2017, at 12:57, David Sweeris wrote:

On Oct 19, 2017, at 12:50 PM, David Baraff via swift-users 
 wrote:


Yes; this is a case where anywhere in the code base I want to just 
say

struct MyNewType : Codable {
// add codable datatypes
}

and don’t want/can’t always go to the centralized place to add it 
in.
Is there some extension-like trick I can pull off that lets me spread 
the implementation out over different files/libraries?


Ah, ok.

No, I don't think you'll be able to do that until/unless Swift gets 
more macro/metaprogramming features. Maybe if protocols ever get to 
conform to themselves? That's a common request, but implementing it 
is apparently beyond tricky. I'm pretty sure somebody's working on 
it, but "bigger fish" and all that...


- Dave Sweeris




___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Sweeris via swift-users
I think if you can figure that out, you’re halfway to letting protocols conform 
to themselves.

(Syntactically, I would probably say that something like “Codable.Self” would 
read well, but I think that already means something. Maybe the answer will 
become clearer when we rework the reflection APIs?)

Sent from my iPhone

> On Oct 19, 2017, at 13:13, Itai Ferber  wrote:
> 
> Even then, that wouldn’t necessarily help in the general case. If you decode 
> {"key" : 1} as [String : Codable], what concrete type would 1 have? Int? 
> Double? Int8? (Arguments can be made for any one of these, but the key here 
> is that it is inherently ambiguous and there isn’t necessarily a good answer.)
> 
> On 19 Oct 2017, at 12:57, David Sweeris wrote:
> 
> On Oct 19, 2017, at 12:50 PM, David Baraff via swift-users 
>  wrote:
> 
> Yes; this is a case where anywhere in the code base I want to just say
> struct MyNewType : Codable {
> // add codable datatypes
> }
> 
> and don’t want/can’t always go to the centralized place to add it in.
> Is there some extension-like trick I can pull off that lets me spread the 
> implementation out over different files/libraries?
> 
> Ah, ok.
> 
> No, I don't think you'll be able to do that until/unless Swift gets more 
> macro/metaprogramming features. Maybe if protocols ever get to conform to 
> themselves? That's a common request, but implementing it is apparently beyond 
> tricky. I'm pretty sure somebody's working on it, but "bigger fish" and all 
> that...
> 
> - Dave Sweeris
> 
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users
Even then, that wouldn’t necessarily help in the general case. If you 
decode `{"key" : 1}` as `[String : Codable]`, what concrete type would 
`1` have? `Int`? `Double`? `Int8`? (Arguments can be made for any one of 
these, but the key here is that it is inherently ambiguous and there 
isn’t necessarily a good answer.)


On 19 Oct 2017, at 12:57, David Sweeris wrote:

On Oct 19, 2017, at 12:50 PM, David Baraff via swift-users 
 wrote:


Yes; this is a case where anywhere in the code base I want to just 
say

struct MyNewType : Codable {
// add codable datatypes
}

and don’t want/can’t always go to the centralized place to add it 
in.
Is there some extension-like trick I can pull off that lets me spread 
the implementation out over different files/libraries?


Ah, ok.

No, I don't think you'll be able to do that until/unless Swift gets 
more macro/metaprogramming features. Maybe if protocols ever get to 
conform to themselves? That's a common request, but implementing it is 
apparently beyond tricky. I'm pretty sure somebody's working on it, 
but "bigger fish" and all that...


- Dave Sweeris
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users
Then no, this wouldn’t be possible unless you could somehow express 
something like:


```swift
// Cribbing some C++-style syntax here
enum OneOf : Codable where T… : Codable {
cases t…(T…)
}
```

where someone would be able to express to you that they want to store a 
`OneOf` through your enum, or something like 
that.


You could do that in a non-extensible way with something like

```swift
enum MyEnum : Codable /* where T : Codable */ /* <- when conditional 
conformance arrives */ {

case int(Int)
case string(String)
case custom(T)
case list([MyEnum])
case dictionary([String : MyEnum])
}
```

but that’s not truly heterogeneous without extending with more generic 
types.


If you don’t know the type you need to decode, then you won’t be 
able to do this unless the encoder/decoder supports somehow mapping the 
type to and from data in the payload.


On 19 Oct 2017, at 12:52, David Baraff wrote:

An even bigger “no can’t do that”: the enum would be in some 
base/low-level library, and thus can’t know about new types that 
exist in higher-up libraries.
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Sweeris via swift-users

> On Oct 19, 2017, at 12:50 PM, David Baraff via swift-users 
>  wrote:
> 
> Yes; this is a case where anywhere in the code base I want to just say
>   struct MyNewType : Codable {
>   // add codable datatypes
>   }
> 
> and don’t want/can’t always go to the centralized place to add it in.
> Is there some extension-like trick I can pull off that lets me spread the 
> implementation out over different files/libraries?

Ah, ok.

No, I don't think you'll be able to do that until/unless Swift gets more 
macro/metaprogramming features. Maybe if protocols ever get to conform to 
themselves? That's a common request, but implementing it is apparently beyond 
tricky. I'm pretty sure somebody's working on it, but "bigger fish" and all 
that...

- Dave Sweeris
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Baraff via swift-users
Yes; this is a case where anywhere in the code base I want to just say
struct MyNewType : Codable {
// add codable datatypes
}

and don’t want/can’t always go to the centralized place to add it in.
Is there some extension-like trick I can pull off that lets me spread the 
implementation out over different files/libraries?

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users

David,

Is there an issue with extending the enum as necessary with new cases to 
support what you need?


```swift
enum MyType : Codable {
case int(Int)
case string(String)
case newThingy(NewThingy)
case list([MyType])
case dictionary([String : MyType])

// …
}
```

`NewThingy` can still be declared on its own and have a synthesized 
`Codable` implementation.


— Itai

On 19 Oct 2017, at 12:14, David Baraff wrote:

My apologies.  I misstated the problem: I don’t want to just limit 
to Int, String, [Int], etc. but also allow structures where


struct NewThingy : Codable {
let data1: T1
let data2: T2
}

where T1 and T2 are themselves Codable.

So basically, back to wanting to let the compiler do the work, when I 
make new structures, while still allowing for heterogenous containers.






Begin forwarded message:


From: Itai Ferber 
Subject: Re: [swift-users] dealing with heterogenous lists/dictionary 
with Codable

Date: October 19, 2017 at 10:40:28 AM PDT
To: David Baraff 
Cc: Geordie Jay , swift-users 



Why are you stuck? I think the following matches your needs, no?

import Foundation

enum MyType : Codable, Equatable {
case int(Int)
case string(String)
case list([MyType])
case dictionary([String : MyType])

public init(from decoder: Decoder) throws {
// Can be made prettier, but as a simple example:
let container = try decoder.singleValueContainer()
do {
self = .int(try container.decode(Int.self))
} catch DecodingError.typeMismatch {
do {
self = .string(try container.decode(String.self))
} catch DecodingError.typeMismatch {
do {
self = .list(try container.decode([MyType].self))
} catch DecodingError.typeMismatch {
self = .dictionary(try container.decode([String : 
MyType].self))

}
}
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let int): try container.encode(int)
case .string(let string): try container.encode(string)
case .list(let list): try container.encode(list)
case .dictionary(let dictionary): try 
container.encode(dictionary)

}
}

static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
switch (lhs, rhs) {
case (.int(let int1), .int(let int2)): return int1 == int2
case (.string(let string1), .string(let string2)): return 
string1 == string2
case (.list(let list1), .list(let list2)): return list1 == 
list2
case (.dictionary(let dict1), .dictionary(let dict2)): return 
dict1 == dict2

default: return false
}
}
}

let values: MyType = .list([.int(42), .string("hello!"), 
.list([.int(9), .string("hi")]), .dictionary(["zero": .int(0), "one": 
.int(1)])])

print(values)

let encoder = JSONEncoder()
let data = try encoder.encode(values)
print(String(data: data, encoding: .utf8)!) // => 
[42,"hello!",[9,"hi"],{"zero":0,"one":1}]


let decoder = JSONDecoder()
let decoded = try decoder.decode(MyType.self, from: data)
print(decoded)

print(values == decoded) // => true
On 19 Oct 2017, at 20:15, David Baraff wrote:

Begin forwarded message:


From: Itai Ferber >
Subject: Re: [swift-users] dealing with heterogenous 
lists/dictionary with Codable

Date: October 19, 2017 at 9:39:25 AM PDT
To: David Baraff >
Cc: Geordie Jay >, 
swift-users >


Hi David and Geordie,

That approach won’t work — encoders and decoders only work 
directly with concrete Codable types (e.g. String, Int, MyFoo [where 
MyFoo is Codable], etc.).
This is by design: since there is no type information stored in the 
JSON payload, there isn’t necessarily a way to tell how to decode 
the type you’re looking at, so asking for a generalCodable` 
isn’t helpful.


Since it’s unlikely that what you truly need is a [String : Any] 
but really a [String : ], one easy 
way to decode this type is to create a wrapper enum or similar which 
overrides init(from:) to be able to decode from one of those types. 
You can then ask to decode a [String : MyWrapperType] and use that 
instead.


What types are you expecting in the dictionary?




The problem is that I want to be able to encode types T where
(a) T is String, Int
(b) lists of T
(c ) dictionaries of type 

The problem is the recursive nature: yes, my types are simple (say 
only base types String and Int) but the “nesting” level may be 
quite deep (a list of list of dictionaries of 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Baraff via swift-users
> 
> 
> 
> Sure, but I don’t want to give a dictionary of unknown types: i’m very happy 
> to say that my dictionary is
>   [String : Codable]
> 
> but
>   struct Foo : Codable {
>   let d: [String : Codable]
>   }
> 
> doesn’t work; the d inside F is not itself Codable.
> 
> That’s strange.

I don’t think it is.  I would completely expect Swift to handle a dictionary of 
a concrete type: that’s not a heteregenous container then.  When you use the 
protocol Codable, then it becomes heterogenous, which is the issue.


> We’re actually doing exactly this and it works for us (although we are using 
> a concrete Codable type rather than the Codable metatype itself).
> 
> Maybe it’s worth filing a bug on Jira
> 
> Good luck.
> 
> 
>> 
>> 
>> So basically, back to wanting to let the compiler do the work, when I make 
>> new structures, while still allowing for heterogenous containers.
>> 
>> It’s also possible to give the compiler hints as to what decodes into what. 
>> Have you looked at the docs on the Apple foundation page?
>> 
>> https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
>>  
>> 
>> 
>> Geordie
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> Begin forwarded message:
>> 
>> 
>>> From: Itai Ferber >
>>> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
>>> Codable
>> 
>>> Date: October 19, 2017 at 10:40:28 AM PDT
>> 
>>> To: David Baraff >
>>> Cc: Geordie Jay >, swift-users 
>>> >
>>> 
>> 
>>> Why are you stuck? I think the following matches your needs, no?
>>> 
>>> import Foundation
>>> 
>>> enum MyType : Codable, Equatable {
>>> case int(Int)
>>> case string(String)
>>> case list([MyType])
>>> case dictionary([String : MyType])
>>> 
>>> public init(from decoder: Decoder) throws {
>>> // Can be made prettier, but as a simple example:
>>> let container = try decoder.singleValueContainer()
>>> do {
>>> self = .int(try container.decode(Int.self))
>>> } catch DecodingError.typeMismatch {
>>> do {
>>> self = .string(try container.decode(String.self))
>>> } catch DecodingError.typeMismatch {
>>> do {
>>> self = .list(try container.decode([MyType].self))
>>> } catch DecodingError.typeMismatch {
>>> self = .dictionary(try container.decode([String : 
>>> MyType].self))
>>> }
>>> }
>>> }
>>> }
>>> 
>>> public func encode(to encoder: Encoder) throws {
>>> var container = encoder.singleValueContainer()
>>> switch self {
>>> case .int(let int): try container.encode(int)
>>> case .string(let string): try container.encode(string)
>>> case .list(let list): try container.encode(list)
>>> case .dictionary(let dictionary): try container.encode(dictionary)
>>> }
>>> }
>>> 
>>> static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
>>> switch (lhs, rhs) {
>>> case (.int(let int1), .int(let int2)): return int1 == int2
>>> case (.string(let string1), .string(let string2)): return string1 
>>> == string2
>>> case (.list(let list1), .list(let list2)): return list1 == list2
>>> case (.dictionary(let dict1), .dictionary(let dict2)): return dict1 
>>> == dict2
>>> default: return false
>>> }
>>> }
>>> }
>>> 
>>> let values: MyType = .list([.int(42), .string("hello!"), .list([.int(9), 
>>> .string("hi")]), .dictionary(["zero": .int(0), "one": .int(1)])])
>>> print(values)
>>> 
>>> let encoder = JSONEncoder()
>>> let data = try encoder.encode(values)
>>> print(String(data: data, encoding: .utf8)!) // => 
>>> [42,"hello!",[9,"hi"],{"zero":0,"one":1}]
>>> 
>>> let decoder = JSONDecoder()
>>> let decoded = try decoder.decode(MyType.self, from: data)
>>> print(decoded)
>>> 
>>> print(values == decoded) // => true
>>> On 19 Oct 2017, at 20:15, David Baraff wrote:
>>> 
>>> Begin forwarded message:
>>> 
 From: Itai Ferber >
 Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
 Codable
 Date: October 19, 2017 at 9:39:25 AM PDT
 To: David Baraff >
 Cc: Geordie Jay >, swift-users 
 >
 
 Hi David and Geordie,
 
 That approach won’t work — encoders and decoders only work directly with 
 concrete Codable types (e.g. String, Int, MyFoo 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users

Hi Geordie,

Yep, that’s the difference here — you can’t decode something with 
an existential type; it has to be concrete (like you’re doing).
The reason for this is that it’s simply not possible to determine what 
type to decode just from the structure of the payload.


Consider the following:

```swift
let json = """
{"name": "Itai", "email": "ifer...@apple.com"}
""".data(using: .utf8)!

let thing = try decoder.decode(Codable.self, from: json)
```

What should the type of `thing` be? Is it `[String : String]` because 
that’s what’s in the JSON?

What if I expected it to be `Person`, which is defined as

```swift
struct Person : Codable {
let name: String
let email: String
}
```

There’s no difference whether the `Codable` thing is at the top level 
or in a dictionary — if I try to decode `[String : Codable]`, I would 
run into the same issue.
The type needs to be concrete so we can figure out what initializer to 
call; if you write your own type (like an `enum`, which is what is 
almost always appropriate in this case), you can supply that type as the 
concrete type to attempt.


— Itai

On 19 Oct 2017, at 12:38, Geordie Jay wrote:

David Baraff  schrieb am Do. 19. Okt. 2017 um 
21:35:





Begin forwarded message:

From: Geordie Jay 

Subject: Re: [swift-users] dealing with heterogenous lists/dictionary 
with

Codable

Date: October 19, 2017 at 12:24:44 PM PDT

To: David Baraff , Itai Ferber 



Cc: swift-users 




David Baraff  schrieb am Do. 19. Okt. 2017 um
21:14:

My apologies.  I misstated the problem: I don’t want to just limit 
to

Int, String, [Int], etc. but also allow structures where

struct NewThingy : Codable {
let data1: T1
let data2: T2
}

where T1 and T2 are themselves Codable.



This is already possible, just not with dictionaries of unknown types
(because they’re not known to be Codable)


Sure, but I don’t want to give a dictionary of unknown types: i’m 
very

happy to say that my dictionary is
[String : Codable]

but
struct Foo : Codable {
let d: [String : Codable]
}

doesn’t work; the d inside F is not itself Codable.



That’s strange. We’re actually doing exactly this and it works for 
us

(although we are using a concrete Codable type rather than the Codable
metatype itself).

Maybe it’s worth filing a bug on Jira

Good luck.





So basically, back to wanting to let the compiler do the work, when 
I
make new structures, while still allowing for heterogenous 
containers.




It’s also possible to give the compiler hints as to what decodes 
into

what. Have you looked at the docs on the Apple foundation page?


https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

Geordie









Begin forwarded message:

From: Itai Ferber 

Subject: Re: [swift-users] dealing with heterogenous 
lists/dictionary

with Codable

Date: October 19, 2017 at 10:40:28 AM PDT

To: David Baraff 

Cc: Geordie Jay , swift-users 




Why are you stuck? I think the following matches your needs, no?

import Foundation
enum MyType : Codable, Equatable {
case int(Int)
case string(String)
case list([MyType])
case dictionary([String : MyType])

public init(from decoder: Decoder) throws {
// Can be made prettier, but as a simple example:
let container = try decoder.singleValueContainer()
do {
self = .int(try container.decode(Int.self))
} catch DecodingError.typeMismatch {
do {
self = .string(try container.decode(String.self))
} catch DecodingError.typeMismatch {
do {
self = .list(try 
container.decode([MyType].self))

} catch DecodingError.typeMismatch {
self = .dictionary(try container.decode([String 
: MyType].self))

}
}
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let int): try container.encode(int)
case .string(let string): try container.encode(string)
case .list(let list): try container.encode(list)
case .dictionary(let dictionary): try 
container.encode(dictionary)

}
}

static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
switch (lhs, rhs) {
case (.int(let int1), .int(let int2)): return int1 == int2
case (.string(let string1), .string(let string2)): return 
string1 == string2
case (.list(let list1), .list(let list2)): return list1 == 
list2
case (.dictionary(let dict1), .dictionary(let dict2)): 
return dict1 == dict2

default: return false
}
}
}
let values: MyType = .list([.int(42), .string("hello!"), 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Geordie Jay via swift-users
David Baraff  schrieb am Do. 19. Okt. 2017 um 21:35:

>
>
> Begin forwarded message:
>
> From: Geordie Jay 
>
> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with
> Codable
>
> Date: October 19, 2017 at 12:24:44 PM PDT
>
> To: David Baraff , Itai Ferber 
>
> Cc: swift-users 
>
>
>
>
> David Baraff  schrieb am Do. 19. Okt. 2017 um
> 21:14:
>
>> My apologies.  I misstated the problem: I don’t want to just limit to
>> Int, String, [Int], etc. but also allow structures where
>>
>> struct NewThingy : Codable {
>> let data1: T1
>> let data2: T2
>> }
>>
>> where T1 and T2 are themselves Codable.
>>
>
> This is already possible, just not with dictionaries of unknown types
> (because they’re not known to be Codable)
>
>
> Sure, but I don’t want to give a dictionary of unknown types: i’m very
> happy to say that my dictionary is
> [String : Codable]
>
> but
> struct Foo : Codable {
> let d: [String : Codable]
> }
>
> doesn’t work; the d inside F is not itself Codable.
>

That’s strange. We’re actually doing exactly this and it works for us
(although we are using a concrete Codable type rather than the Codable
metatype itself).

Maybe it’s worth filing a bug on Jira

Good luck.


>
>
>> So basically, back to wanting to let the compiler do the work, when I
>> make new structures, while still allowing for heterogenous containers.
>>
>
> It’s also possible to give the compiler hints as to what decodes into
> what. Have you looked at the docs on the Apple foundation page?
>
>
> https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
>
> Geordie
>
>
>
>
>>
>>
>>
>>
>> Begin forwarded message:
>>
>> From: Itai Ferber 
>>
>> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary
>> with Codable
>>
>> Date: October 19, 2017 at 10:40:28 AM PDT
>>
>> To: David Baraff 
>>
>> Cc: Geordie Jay , swift-users 
>>
>>
>> Why are you stuck? I think the following matches your needs, no?
>>
>> import Foundation
>> enum MyType : Codable, Equatable {
>> case int(Int)
>> case string(String)
>> case list([MyType])
>> case dictionary([String : MyType])
>>
>> public init(from decoder: Decoder) throws {
>> // Can be made prettier, but as a simple example:
>> let container = try decoder.singleValueContainer()
>> do {
>> self = .int(try container.decode(Int.self))
>> } catch DecodingError.typeMismatch {
>> do {
>> self = .string(try container.decode(String.self))
>> } catch DecodingError.typeMismatch {
>> do {
>> self = .list(try container.decode([MyType].self))
>> } catch DecodingError.typeMismatch {
>> self = .dictionary(try container.decode([String : 
>> MyType].self))
>> }
>> }
>> }
>> }
>>
>> public func encode(to encoder: Encoder) throws {
>> var container = encoder.singleValueContainer()
>> switch self {
>> case .int(let int): try container.encode(int)
>> case .string(let string): try container.encode(string)
>> case .list(let list): try container.encode(list)
>> case .dictionary(let dictionary): try container.encode(dictionary)
>> }
>> }
>>
>> static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
>> switch (lhs, rhs) {
>> case (.int(let int1), .int(let int2)): return int1 == int2
>> case (.string(let string1), .string(let string2)): return string1 == 
>> string2
>> case (.list(let list1), .list(let list2)): return list1 == list2
>> case (.dictionary(let dict1), .dictionary(let dict2)): return dict1 
>> == dict2
>> default: return false
>> }
>> }
>> }
>> let values: MyType = .list([.int(42), .string("hello!"), .list([.int(9), 
>> .string("hi")]), .dictionary(["zero": .int(0), "one": 
>> .int(1)])])print(values)
>> let encoder = JSONEncoder()let data = try 
>> encoder.encode(values)print(String(data: data, encoding: .utf8)!) // => 
>> [42,"hello!",[9,"hi"],{"zero":0,"one":1}]
>> let decoder = JSONDecoder()let decoded = try decoder.decode(MyType.self, 
>> from: data)print(decoded)
>> print(values == decoded) // => true
>>
>> On 19 Oct 2017, at 20:15, David Baraff wrote:
>>
>> Begin forwarded message:
>>
>> From: Itai Ferber 
>>
>> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary
>> with Codable
>>
>> Date: October 19, 2017 at 9:39:25 AM PDT
>>
>> To: David Baraff 
>>
>> Cc: Geordie Jay , swift-users 
>>
>>
>> Hi David and Geordie,
>>
>> That approach won’t work — encoders and decoders only work 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Baraff via swift-users


Begin forwarded message:

> From: Geordie Jay 
> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
> Codable
> Date: October 19, 2017 at 12:24:44 PM PDT
> To: David Baraff , Itai Ferber 
> Cc: swift-users 
> 
> 
> 
> David Baraff > schrieb 
> am Do. 19. Okt. 2017 um 21:14:
> My apologies.  I misstated the problem: I don’t want to just limit to Int, 
> String, [Int], etc. but also allow structures where
> 
>   struct NewThingy : Codable {
>   let data1: T1
>   let data2: T2
>   }
> 
> where T1 and T2 are themselves Codable.
> 
> This is already possible, just not with dictionaries of unknown types 
> (because they’re not known to be Codable) 

Sure, but I don’t want to give a dictionary of unknown types: i’m very happy to 
say that my dictionary is
[String : Codable]

but
struct Foo : Codable {
let d: [String : Codable]
}

doesn’t work; the d inside F is not itself Codable.

> 
> 
> So basically, back to wanting to let the compiler do the work, when I make 
> new structures, while still allowing for heterogenous containers.
> 
> It’s also possible to give the compiler hints as to what decodes into what. 
> Have you looked at the docs on the Apple foundation page?
> 
> https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
>  
> 
> 
> Geordie
> 
> 
> 
> 
> 
> 
> 
> 
> Begin forwarded message:
> 
> 
>> From: Itai Ferber >
>> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
>> Codable
> 
>> Date: October 19, 2017 at 10:40:28 AM PDT
> 
>> To: David Baraff >
>> Cc: Geordie Jay >, swift-users 
>> >
>> 
> 
>> Why are you stuck? I think the following matches your needs, no?
>> 
>> import Foundation
>> 
>> enum MyType : Codable, Equatable {
>> case int(Int)
>> case string(String)
>> case list([MyType])
>> case dictionary([String : MyType])
>> 
>> public init(from decoder: Decoder) throws {
>> // Can be made prettier, but as a simple example:
>> let container = try decoder.singleValueContainer()
>> do {
>> self = .int(try container.decode(Int.self))
>> } catch DecodingError.typeMismatch {
>> do {
>> self = .string(try container.decode(String.self))
>> } catch DecodingError.typeMismatch {
>> do {
>> self = .list(try container.decode([MyType].self))
>> } catch DecodingError.typeMismatch {
>> self = .dictionary(try container.decode([String : 
>> MyType].self))
>> }
>> }
>> }
>> }
>> 
>> public func encode(to encoder: Encoder) throws {
>> var container = encoder.singleValueContainer()
>> switch self {
>> case .int(let int): try container.encode(int)
>> case .string(let string): try container.encode(string)
>> case .list(let list): try container.encode(list)
>> case .dictionary(let dictionary): try container.encode(dictionary)
>> }
>> }
>> 
>> static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
>> switch (lhs, rhs) {
>> case (.int(let int1), .int(let int2)): return int1 == int2
>> case (.string(let string1), .string(let string2)): return string1 == 
>> string2
>> case (.list(let list1), .list(let list2)): return list1 == list2
>> case (.dictionary(let dict1), .dictionary(let dict2)): return dict1 
>> == dict2
>> default: return false
>> }
>> }
>> }
>> 
>> let values: MyType = .list([.int(42), .string("hello!"), .list([.int(9), 
>> .string("hi")]), .dictionary(["zero": .int(0), "one": .int(1)])])
>> print(values)
>> 
>> let encoder = JSONEncoder()
>> let data = try encoder.encode(values)
>> print(String(data: data, encoding: .utf8)!) // => 
>> [42,"hello!",[9,"hi"],{"zero":0,"one":1}]
>> 
>> let decoder = JSONDecoder()
>> let decoded = try decoder.decode(MyType.self, from: data)
>> print(decoded)
>> 
>> print(values == decoded) // => true
>> On 19 Oct 2017, at 20:15, David Baraff wrote:
>> 
>> Begin forwarded message:
>> 
>>> From: Itai Ferber >
>>> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
>>> Codable
>>> Date: October 19, 2017 at 9:39:25 AM PDT
>>> To: David Baraff >
>>> Cc: Geordie Jay 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Geordie Jay via swift-users
David Baraff  schrieb am Do. 19. Okt. 2017 um 21:14:

> My apologies.  I misstated the problem: I don’t want to just limit to Int,
> String, [Int], etc. but also allow structures where
>
> struct NewThingy : Codable {
> let data1: T1
> let data2: T2
> }
>
> where T1 and T2 are themselves Codable.
>

This is already possible, just not with dictionaries of unknown types
(because they’re not known to be Codable)


> So basically, back to wanting to let the compiler do the work, when I make
> new structures, while still allowing for heterogenous containers.
>

It’s also possible to give the compiler hints as to what decodes into what.
Have you looked at the docs on the Apple foundation page?

https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

Geordie




>
>
>
>
> Begin forwarded message:
>
> From: Itai Ferber 
>
> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with
> Codable
>
> Date: October 19, 2017 at 10:40:28 AM PDT
>
> To: David Baraff 
>
> Cc: Geordie Jay , swift-users 
>
>
> Why are you stuck? I think the following matches your needs, no?
>
> import Foundation
> enum MyType : Codable, Equatable {
> case int(Int)
> case string(String)
> case list([MyType])
> case dictionary([String : MyType])
>
> public init(from decoder: Decoder) throws {
> // Can be made prettier, but as a simple example:
> let container = try decoder.singleValueContainer()
> do {
> self = .int(try container.decode(Int.self))
> } catch DecodingError.typeMismatch {
> do {
> self = .string(try container.decode(String.self))
> } catch DecodingError.typeMismatch {
> do {
> self = .list(try container.decode([MyType].self))
> } catch DecodingError.typeMismatch {
> self = .dictionary(try container.decode([String : 
> MyType].self))
> }
> }
> }
> }
>
> public func encode(to encoder: Encoder) throws {
> var container = encoder.singleValueContainer()
> switch self {
> case .int(let int): try container.encode(int)
> case .string(let string): try container.encode(string)
> case .list(let list): try container.encode(list)
> case .dictionary(let dictionary): try container.encode(dictionary)
> }
> }
>
> static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
> switch (lhs, rhs) {
> case (.int(let int1), .int(let int2)): return int1 == int2
> case (.string(let string1), .string(let string2)): return string1 == 
> string2
> case (.list(let list1), .list(let list2)): return list1 == list2
> case (.dictionary(let dict1), .dictionary(let dict2)): return dict1 
> == dict2
> default: return false
> }
> }
> }
> let values: MyType = .list([.int(42), .string("hello!"), .list([.int(9), 
> .string("hi")]), .dictionary(["zero": .int(0), "one": .int(1)])])print(values)
> let encoder = JSONEncoder()let data = try 
> encoder.encode(values)print(String(data: data, encoding: .utf8)!) // => 
> [42,"hello!",[9,"hi"],{"zero":0,"one":1}]
> let decoder = JSONDecoder()let decoded = try decoder.decode(MyType.self, 
> from: data)print(decoded)
> print(values == decoded) // => true
>
> On 19 Oct 2017, at 20:15, David Baraff wrote:
>
> Begin forwarded message:
>
> From: Itai Ferber 
>
> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with
> Codable
>
> Date: October 19, 2017 at 9:39:25 AM PDT
>
> To: David Baraff 
>
> Cc: Geordie Jay , swift-users 
>
>
> Hi David and Geordie,
>
> That approach won’t work — encoders and decoders only work directly with
> concrete Codable types (e.g. String, Int, MyFoo [where MyFoo is Codable],
> etc.).
> This is by design: since there is no type information stored in the JSON
> payload, there isn’t necessarily a way to tell how to decode the type
> you’re looking at, so asking for a generalCodable` isn’t helpful.
>
> Since it’s unlikely that what you truly need is a [String : Any] but
> really a [String : ], one easy way to
> decode this type is to create a wrapper enum or similar which overrides
> init(from:) to be able to decode from one of those types. You can then
> ask to decode a [String : MyWrapperType] and use that instead.
>
> What types are you expecting in the dictionary?
>
>
> The problem is that I want to be able to encode types T where
> (a) T is String, Int
> (b) lists of T
> (c ) dictionaries of type 
>
> The problem is the recursive nature: yes, my types are simple (say only
> base types String and Int) but the “nesting” level may be quite deep (a
> list of list of dictionaries of 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Baraff via swift-users
My apologies.  I misstated the problem: I don’t want to just limit to Int, 
String, [Int], etc. but also allow structures where

struct NewThingy : Codable {
let data1: T1
let data2: T2
}

where T1 and T2 are themselves Codable.

So basically, back to wanting to let the compiler do the work, when I make new 
structures, while still allowing for heterogenous containers.





Begin forwarded message:

> From: Itai Ferber 
> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
> Codable
> Date: October 19, 2017 at 10:40:28 AM PDT
> To: David Baraff 
> Cc: Geordie Jay , swift-users 
> 
> Why are you stuck? I think the following matches your needs, no?
> 
> import Foundation
> 
> enum MyType : Codable, Equatable {
> case int(Int)
> case string(String)
> case list([MyType])
> case dictionary([String : MyType])
> 
> public init(from decoder: Decoder) throws {
> // Can be made prettier, but as a simple example:
> let container = try decoder.singleValueContainer()
> do {
> self = .int(try container.decode(Int.self))
> } catch DecodingError.typeMismatch {
> do {
> self = .string(try container.decode(String.self))
> } catch DecodingError.typeMismatch {
> do {
> self = .list(try container.decode([MyType].self))
> } catch DecodingError.typeMismatch {
> self = .dictionary(try container.decode([String : 
> MyType].self))
> }
> }
> }
> }
> 
> public func encode(to encoder: Encoder) throws {
> var container = encoder.singleValueContainer()
> switch self {
> case .int(let int): try container.encode(int)
> case .string(let string): try container.encode(string)
> case .list(let list): try container.encode(list)
> case .dictionary(let dictionary): try container.encode(dictionary)
> }
> }
> 
> static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
> switch (lhs, rhs) {
> case (.int(let int1), .int(let int2)): return int1 == int2
> case (.string(let string1), .string(let string2)): return string1 == 
> string2
> case (.list(let list1), .list(let list2)): return list1 == list2
> case (.dictionary(let dict1), .dictionary(let dict2)): return dict1 
> == dict2
> default: return false
> }
> }
> }
> 
> let values: MyType = .list([.int(42), .string("hello!"), .list([.int(9), 
> .string("hi")]), .dictionary(["zero": .int(0), "one": .int(1)])])
> print(values)
> 
> let encoder = JSONEncoder()
> let data = try encoder.encode(values)
> print(String(data: data, encoding: .utf8)!) // => 
> [42,"hello!",[9,"hi"],{"zero":0,"one":1}]
> 
> let decoder = JSONDecoder()
> let decoded = try decoder.decode(MyType.self, from: data)
> print(decoded)
> 
> print(values == decoded) // => true
> On 19 Oct 2017, at 20:15, David Baraff wrote:
> 
> Begin forwarded message:
> 
>> From: Itai Ferber >
>> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
>> Codable
>> Date: October 19, 2017 at 9:39:25 AM PDT
>> To: David Baraff >
>> Cc: Geordie Jay >, swift-users 
>> >
>> 
>> Hi David and Geordie,
>> 
>> That approach won’t work — encoders and decoders only work directly with 
>> concrete Codable types (e.g. String, Int, MyFoo [where MyFoo is Codable], 
>> etc.).
>> This is by design: since there is no type information stored in the JSON 
>> payload, there isn’t necessarily a way to tell how to decode the type you’re 
>> looking at, so asking for a generalCodable` isn’t helpful.
>> 
>> Since it’s unlikely that what you truly need is a [String : Any] but really 
>> a [String : ], one easy way to decode this 
>> type is to create a wrapper enum or similar which overrides init(from:) to 
>> be able to decode from one of those types. You can then ask to decode a 
>> [String : MyWrapperType] and use that instead.
>> 
>> What types are you expecting in the dictionary?
>> 
>> 
> 
> The problem is that I want to be able to encode types T where
>   (a) T is String, Int
>   (b) lists of T
>   (c ) dictionaries of type 
> 
> The problem is the recursive nature: yes, my types are simple (say only base 
> types String and Int) but the “nesting” level may be quite deep (a list of 
> list of dictionaries of  
> 
> Let’s turn this around:  in addition to the JSONEncoder, one can also use the 
> PropertyListEncoder.  
> 
> Are we saying that something one could pull from a property list file (which 
> is pretty much what i want: arbitrary deep 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users

Why are you stuck? I think the following matches your needs, no?

```swift
import Foundation

enum MyType : Codable, Equatable {
case int(Int)
case string(String)
case list([MyType])
case dictionary([String : MyType])

public init(from decoder: Decoder) throws {
// Can be made prettier, but as a simple example:
let container = try decoder.singleValueContainer()
do {
self = .int(try container.decode(Int.self))
} catch DecodingError.typeMismatch {
do {
self = .string(try container.decode(String.self))
} catch DecodingError.typeMismatch {
do {
self = .list(try container.decode([MyType].self))
} catch DecodingError.typeMismatch {
self = .dictionary(try container.decode([String : 
MyType].self))

}
}
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let int): try container.encode(int)
case .string(let string): try container.encode(string)
case .list(let list): try container.encode(list)
case .dictionary(let dictionary): try 
container.encode(dictionary)

}
}

static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
switch (lhs, rhs) {
case (.int(let int1), .int(let int2)): return int1 == int2
case (.string(let string1), .string(let string2)): return 
string1 == string2
case (.list(let list1), .list(let list2)): return list1 == 
list2
case (.dictionary(let dict1), .dictionary(let dict2)): return 
dict1 == dict2

default: return false
}
}
}

let values: MyType = .list([.int(42), .string("hello!"), .list([.int(9), 
.string("hi")]), .dictionary(["zero": .int(0), "one": .int(1)])])

print(values)

let encoder = JSONEncoder()
let data = try encoder.encode(values)
print(String(data: data, encoding: .utf8)!) // => 
[42,"hello!",[9,"hi"],{"zero":0,"one":1}]


let decoder = JSONDecoder()
let decoded = try decoder.decode(MyType.self, from: data)
print(decoded)

print(values == decoded) // => true
```

On 19 Oct 2017, at 20:15, David Baraff wrote:


Begin forwarded message:


From: Itai Ferber 
Subject: Re: [swift-users] dealing with heterogenous lists/dictionary 
with Codable

Date: October 19, 2017 at 9:39:25 AM PDT
To: David Baraff 
Cc: Geordie Jay , swift-users 



Hi David and Geordie,

That approach won’t work — encoders and decoders only work 
directly with concrete Codable types (e.g. String, Int, MyFoo [where 
MyFoo is Codable], etc.).
This is by design: since there is no type information stored in the 
JSON payload, there isn’t necessarily a way to tell how to decode 
the type you’re looking at, so asking for a generalCodable` isn’t 
helpful.


Since it’s unlikely that what you truly need is a [String : Any] 
but really a [String : ], one easy 
way to decode this type is to create a wrapper enum or similar which 
overrides init(from:) to be able to decode from one of those types. 
You can then ask to decode a [String : MyWrapperType] and use that 
instead.


What types are you expecting in the dictionary?




The problem is that I want to be able to encode types T where
(a) T is String, Int
(b) lists of T
(c ) dictionaries of type 

The problem is the recursive nature: yes, my types are simple (say 
only base types String and Int) but the “nesting” level may be 
quite deep (a list of list of dictionaries of > wrote:



I mean can you do something along the lines of

let codableDict = stringAnyDict as? [String : Codable]

?

I’m not at a computer to test it myself




David Baraff > 
schrieb am Do. 19. Okt. 2017 um 15:45:
That’s exactly what I want.  The ironic part is that I got my 
dictionary by decoding a Json file.  If that’s where my dictionary 
came from, is there a simple way of coercing the Json serialization 
routines to give me back codables, rather than Anys?



Sent from my iPad

On Oct 19, 2017, at 3:38 AM, Geordie Jay > 

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Baraff via swift-users
Begin forwarded message:

> From: Itai Ferber 
> Subject: Re: [swift-users] dealing with heterogenous lists/dictionary with 
> Codable
> Date: October 19, 2017 at 9:39:25 AM PDT
> To: David Baraff 
> Cc: Geordie Jay , swift-users 
> 
> Hi David and Geordie,
> 
> That approach won’t work — encoders and decoders only work directly with 
> concrete Codable types (e.g. String, Int, MyFoo [where MyFoo is Codable], 
> etc.).
> This is by design: since there is no type information stored in the JSON 
> payload, there isn’t necessarily a way to tell how to decode the type you’re 
> looking at, so asking for a generalCodable` isn’t helpful.
> 
> Since it’s unlikely that what you truly need is a [String : Any] but really a 
> [String : ], one easy way to decode this 
> type is to create a wrapper enum or similar which overrides init(from:) to be 
> able to decode from one of those types. You can then ask to decode a [String 
> : MyWrapperType] and use that instead.
> 
> What types are you expecting in the dictionary?
> 
> 

The problem is that I want to be able to encode types T where
(a) T is String, Int
(b) lists of T
(c ) dictionaries of type 

The problem is the recursive nature: yes, my types are simple (say only base 
types String and Int) but the “nesting” level may be quite deep (a list of list 
of dictionaries of  — Itai
> 
> On 19 Oct 2017, at 18:11, David Baraff via swift-users wrote:
> 
> I’ll try.  Is that cast smart enough to apply recursively? We shall see.
> 
> Sent from my iPad
> 
> On Oct 19, 2017, at 7:34 AM, Geordie Jay  > wrote:
> 
>> I mean can you do something along the lines of
>> 
>> let codableDict = stringAnyDict as? [String : Codable]
>> 
>> ?
>> 
>> I’m not at a computer to test it myself
>> 
>> 
>> 
>> 
>> David Baraff > schrieb 
>> am Do. 19. Okt. 2017 um 15:45:
>> That’s exactly what I want.  The ironic part is that I got my dictionary by 
>> decoding a Json file.  If that’s where my dictionary came from, is there a 
>> simple way of coercing the Json serialization routines to give me back 
>> codables, rather than Anys?
>> 
>> 
>> Sent from my iPad
>> 
>> On Oct 19, 2017, at 3:38 AM, Geordie Jay > > wrote:
>> 
>>> 
>>> David Baraff via swift-users >> > schrieb am Do. 19. Okt. 2017 um 03:47:
>>> So I have simple structs like this:
>>> 
>>> struct Library: Codable {
>>> let domain: String
>>> let unit: String
>>> }
>>> 
>>> and it’s super-simple to serialize.  Yay.
>>> 
>>> But:
>>> 
>>> struct LibraryGroup : Codable { // I wish...
>>>let libraries: [Library]
>>>let someDict: [String : Any]
>>> }
>>> 
>>> I haven’t tried this, but is it possible to have a dictionary of [String : 
>>> Codable] ? Because that’s exactly the type requirements you’re describing, 
>>> no?
>>> 
>>> Geordie
>>> 
>>> 
>>> So what I’m looking for is something where if the values in someDict are 
>>> themselves Codable, I can serialize things, and if they’re not, I can’t.  
>>> In my previous scheme, I was using NSKeyedArchiver to serialize everything, 
>>> manualy, including someDict; in trying to switch to Codable I ran smack 
>>> into the fact that Codable wants to know what all the types are, in advance.
>>> 
>>> Am I just stuck?  How do I get the best of both worlds, where the compiler 
>>> can make use of the fact that it can see the data types of my structures, 
>>> while still being able to serialize heterogenous data like is found in 
>>> LibraryGroup?
>>> 
>>> Is my only alternative to write a custom coder for LibraryGroup?  Is there 
>>> any hope I could teach Codable what to do with
>>> [String: Any]
>>> 
>>> ?
>>> 
>>> 
>>> ___
>>> swift-users mailing list
>>> swift-users@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-users 
>>> 
> 
> ___
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users 
> 
___
swift-users mailing list
swift-users@swift.org

Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Itai Ferber via swift-users

Hi David and Geordie,

That approach won’t work — encoders and decoders only work directly 
with concrete `Codable` types (e.g. `String`, `Int`, `MyFoo` [where 
`MyFoo` is `Codable], etc.).
This is by design: since there is no type information stored in the JSON 
payload, there isn’t necessarily a way to tell how to decode the type 
you’re looking at, so asking for a general `Codable` isn’t helpful.


Since it’s unlikely that what you truly need is a `[String : Any]` but 
really a `[String : ]`, one easy way to 
decode this type is to create a wrapper `enum` or similar which 
overrides `init(from:)` to be able to decode from one of those types. 
You can then ask to decode a `[String : MyWrapperType]` and use that 
instead.


What types are you expecting in the dictionary?

— Itai

On 19 Oct 2017, at 18:11, David Baraff via swift-users wrote:

I’ll try.  Is that cast smart enough to apply recursively? We shall 
see.


Sent from my iPad


On Oct 19, 2017, at 7:34 AM, Geordie Jay  wrote:

I mean can you do something along the lines of

let codableDict = stringAnyDict as? [String : Codable]

?

I’m not at a computer to test it myself




David Baraff  schrieb am Do. 19. Okt. 2017 um 
15:45:
That’s exactly what I want.  The ironic part is that I got my 
dictionary by decoding a Json file.  If that’s where my dictionary 
came from, is there a simple way of coercing the Json serialization 
routines to give me back codables, rather than Anys?



Sent from my iPad


On Oct 19, 2017, at 3:38 AM, Geordie Jay  wrote:


David Baraff via swift-users  schrieb am Do. 
19. Okt. 2017 um 03:47:

So I have simple structs like this:

struct Library: Codable {
let domain: String
let unit: String
}

and it’s super-simple to serialize.  Yay.

But:

struct LibraryGroup : Codable { // I wish...
   let libraries: [Library]
   let someDict: [String : Any]
}


I haven’t tried this, but is it possible to have a dictionary of 
[String : Codable] ? Because that’s exactly the type requirements 
you’re describing, no?


Geordie



So what I’m looking for is something where if the values in 
someDict are themselves Codable, I can serialize things, and if 
they’re not, I can’t.  In my previous scheme, I was using 
NSKeyedArchiver to serialize everything, manualy, including 
someDict; in trying to switch to Codable I ran smack into the fact 
that Codable wants to know what all the types are, in advance.


Am I just stuck?  How do I get the best of both worlds, where the 
compiler can make use of the fact that it can see the data types 
of my structures, while still being able to serialize heterogenous 
data like is found in LibraryGroup?


Is my only alternative to write a custom coder for LibraryGroup?  
Is there any hope I could teach Codable what to do with

[String: Any]

?


___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users




___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Baraff via swift-users
I’ll try.  Is that cast smart enough to apply recursively? We shall see.

Sent from my iPad

> On Oct 19, 2017, at 7:34 AM, Geordie Jay  wrote:
> 
> I mean can you do something along the lines of
> 
> let codableDict = stringAnyDict as? [String : Codable]
> 
> ?
> 
> I’m not at a computer to test it myself
> 
> 
> 
> 
> David Baraff  schrieb am Do. 19. Okt. 2017 um 15:45:
>> That’s exactly what I want.  The ironic part is that I got my dictionary by 
>> decoding a Json file.  If that’s where my dictionary came from, is there a 
>> simple way of coercing the Json serialization routines to give me back 
>> codables, rather than Anys?
>> 
>> 
>> Sent from my iPad
>> 
>>> On Oct 19, 2017, at 3:38 AM, Geordie Jay  wrote:
>>> 
>>> 
>>> David Baraff via swift-users  schrieb am Do. 19. 
>>> Okt. 2017 um 03:47:
 So I have simple structs like this:
 
 struct Library: Codable {
 let domain: String
 let unit: String
 }
 
 and it’s super-simple to serialize.  Yay.
 
 But:
 
 struct LibraryGroup : Codable { // I wish...
let libraries: [Library]
let someDict: [String : Any]
 }
>>> 
>>> I haven’t tried this, but is it possible to have a dictionary of [String : 
>>> Codable] ? Because that’s exactly the type requirements you’re describing, 
>>> no?
>>> 
>>> Geordie
>>> 
 
 So what I’m looking for is something where if the values in someDict are 
 themselves Codable, I can serialize things, and if they’re not, I can’t.  
 In my previous scheme, I was using NSKeyedArchiver to serialize 
 everything, manualy, including someDict; in trying to switch to Codable I 
 ran smack into the fact that Codable wants to know what all the types are, 
 in advance.
 
 Am I just stuck?  How do I get the best of both worlds, where the compiler 
 can make use of the fact that it can see the data types of my structures, 
 while still being able to serialize heterogenous data like is found in 
 LibraryGroup?
 
 Is my only alternative to write a custom coder for LibraryGroup?  Is there 
 any hope I could teach Codable what to do with
 [String: Any]
 
 ?
 
 
 ___
 swift-users mailing list
 swift-users@swift.org
 https://lists.swift.org/mailman/listinfo/swift-users
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Geordie Jay via swift-users
I mean can you do something along the lines of

let codableDict = stringAnyDict as? [String : Codable]

?

I’m not at a computer to test it myself




David Baraff  schrieb am Do. 19. Okt. 2017 um 15:45:

> That’s exactly what I want.  The ironic part is that I got my dictionary
> by decoding a Json file.  If that’s where my dictionary came from, is there
> a simple way of coercing the Json serialization routines to give me back
> codables, rather than Anys?
>
>
> Sent from my iPad
>
> On Oct 19, 2017, at 3:38 AM, Geordie Jay  wrote:
>
>
> David Baraff via swift-users  schrieb am Do. 19.
> Okt. 2017 um 03:47:
>
>> So I have simple structs like this:
>>
>> struct Library: Codable {
>> let domain: String
>> let unit: String
>> }
>>
>> and it’s super-simple to serialize.  Yay.
>>
>> But:
>>
>> struct LibraryGroup : Codable { // I wish...
>>let libraries: [Library]
>>let someDict: [String : Any]
>> }
>>
>
> I haven’t tried this, but is it possible to have a dictionary of [String :
> Codable] ? Because that’s exactly the type requirements you’re describing,
> no?
>
> Geordie
>
>
>> So what I’m looking for is something where if the values in someDict are
>> themselves Codable, I can serialize things, and if they’re not, I can’t.
>> In my previous scheme, I was using NSKeyedArchiver to serialize everything,
>> manualy, including someDict; in trying to switch to Codable I ran smack
>> into the fact that Codable wants to know what all the types are, in advance.
>>
>> Am I just stuck?  How do I get the best of both worlds, where the
>> compiler can make use of the fact that it can see the data types of my
>> structures, while still being able to serialize heterogenous data like is
>> found in LibraryGroup?
>>
>> Is my only alternative to write a custom coder for LibraryGroup?  Is
>> there any hope I could teach Codable what to do with
>> [String: Any]
>>
>> ?
>>
>>
>> ___
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread David Baraff via swift-users
That’s exactly what I want.  The ironic part is that I got my dictionary by 
decoding a Json file.  If that’s where my dictionary came from, is there a 
simple way of coercing the Json serialization routines to give me back 
codables, rather than Anys?


Sent from my iPad

> On Oct 19, 2017, at 3:38 AM, Geordie Jay  wrote:
> 
> 
> David Baraff via swift-users  schrieb am Do. 19. Okt. 
> 2017 um 03:47:
>> So I have simple structs like this:
>> 
>> struct Library: Codable {
>> let domain: String
>> let unit: String
>> }
>> 
>> and it’s super-simple to serialize.  Yay.
>> 
>> But:
>> 
>> struct LibraryGroup : Codable { // I wish...
>>let libraries: [Library]
>>let someDict: [String : Any]
>> }
> 
> I haven’t tried this, but is it possible to have a dictionary of [String : 
> Codable] ? Because that’s exactly the type requirements you’re describing, no?
> 
> Geordie
> 
>> 
>> So what I’m looking for is something where if the values in someDict are 
>> themselves Codable, I can serialize things, and if they’re not, I can’t.  In 
>> my previous scheme, I was using NSKeyedArchiver to serialize everything, 
>> manualy, including someDict; in trying to switch to Codable I ran smack into 
>> the fact that Codable wants to know what all the types are, in advance.
>> 
>> Am I just stuck?  How do I get the best of both worlds, where the compiler 
>> can make use of the fact that it can see the data types of my structures, 
>> while still being able to serialize heterogenous data like is found in 
>> LibraryGroup?
>> 
>> Is my only alternative to write a custom coder for LibraryGroup?  Is there 
>> any hope I could teach Codable what to do with
>> [String: Any]
>> 
>> ?
>> 
>> 
>> ___
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Restrict parameter to value type

2017-10-19 Thread Quinn "The Eskimo!" via swift-users

On 19 Oct 2017, at 11:47, Martin Knabbe via swift-users  
wrote:

> I'm curious why AnyValue is missing. Can someone answer this?

This question has come up a number of times, including this recent thread on 
swift-dev.



Make sure to follow it over into the next week’s archive.



Share and Enjoy
--
Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware


___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


[swift-users] Restrict parameter to value type

2017-10-19 Thread Martin Knabbe via swift-users
Is there a way to restrict the type of a parameter to value types only
(struct)? I know of Any and AnyObject, but I'm missing AnyValue.

How can I achieve something like the following, to make sure that the
parameter is immutable and has copy-on-write feature?

protocol Actor: class {
func send(message: AnyValue)
}

I'm curious why AnyValue is missing. Can someone answer this?

Thanks in advance.

-- 
Board of Directors: Andrew Pinnington, Alistair McCann, Jonas Gumny
Commercial Register: HRB 110377

The information and attached file(s) (if any) contained in this email is 
confidential and may be legally privileged. It is intended solely for the 
addressee. Any access to this email by persons other than the addressee is 
prohibited. If you are not the addressee for whom this email is intended, 
you may not disclose, copy, distribute or store this email. If you receive 
this in error, please delete and email confirmation to the sender. Thank 
you for your cooperation.
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] dealing with heterogenous lists/dictionary with Codable

2017-10-19 Thread Geordie Jay via swift-users
David Baraff via swift-users  schrieb am Do. 19.
Okt. 2017 um 03:47:

> So I have simple structs like this:
>
> struct Library: Codable {
> let domain: String
> let unit: String
> }
>
> and it’s super-simple to serialize.  Yay.
>
> But:
>
> struct LibraryGroup : Codable { // I wish...
>let libraries: [Library]
>let someDict: [String : Any]
> }
>

I haven’t tried this, but is it possible to have a dictionary of [String :
Codable] ? Because that’s exactly the type requirements you’re describing,
no?

Geordie


> So what I’m looking for is something where if the values in someDict are
> themselves Codable, I can serialize things, and if they’re not, I can’t.
> In my previous scheme, I was using NSKeyedArchiver to serialize everything,
> manualy, including someDict; in trying to switch to Codable I ran smack
> into the fact that Codable wants to know what all the types are, in advance.
>
> Am I just stuck?  How do I get the best of both worlds, where the compiler
> can make use of the fact that it can see the data types of my structures,
> while still being able to serialize heterogenous data like is found in
> LibraryGroup?
>
> Is my only alternative to write a custom coder for LibraryGroup?  Is there
> any hope I could teach Codable what to do with
> [String: Any]
>
> ?
>
>
> ___
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users