> On Mar 13, 2017, at 8:55 AM, Dimitri Racordon via swift-evolution 
> <swift-evolut...@swift.org> wrote:
> Hello fellow evolutionists,
> 
> I’m not sure this list is the best place to talk about this, so please 
> redirect me if it should be discussed elsewhere.

More of a swift-dev topic.  CC'ing there, BCC'ing evolution.

> While trying to implement algebraic data types in Swift, I stumble upon an 
> interesting problem. Let’s consider the following example:
> 
> protocol Term {}
> 
> struct Zero: Term {}
> struct Succ: Term {
>     let pred: Term
> }
> 
> 
> var term: Term = Zero()
> for _ in 0 ..< 20000 {
>     term = Succ(pred: term)
> }
> 
> This code will take forever to execute (about 1 minute on my mbp late 2013), 
> whereas if I replace the structures with reference types it will finish 
> almost instantly, which is what one would expect from such a simple data 
> structure. Most likely, the problem lays in the fact that a deep copy is 
> produced every time a new level of recursion is created. However, I guess 
> this case could be detected by the compiler, as the `term` variable passed as 
> parameter is immediately affected to the rvalue of the expression using it.
> 
> An even more powerful approach would be to keep track of the reference on the 
> original `term` value under the hood, and update it if necessary in a 
> copy-on-write fashion. As I understand it, this would enable this code to be 
> efficiently executed as well:

Yes, this is something we're already looking at doing in general for this kind 
of "existential" use of a protocol, precisely because of this kind of 
nested-type problem.

> protocol Term {}
> 
> struct Leaf: Term {}
> struct Tree: Term {
>     let left: Term
>     let right: Term
> }
> 
> var tree: Term = Leaf()
> for _ in 0 ..< 20000 {
>     tree = Tree(left: tree, right: tree)
> }
> 
> Interestingly, while enumerations are value types, indirect enumerations 
> don’t suffer the performance issue of the above examples. Note however that 
> the issue will reappear if the enum isn’t marked `indirect`.
> 
> protocol Term {}
> 
> indirect enum Nat: Term {
>     case zero
>     case succ(Term)
> }

I do have to note that this is a very strange of writing Nat.  Why recurse 
through a protocol type instead of recursing concretely?

John.

> 
> var term = Nat.zero
> for _ in 0 ..< 20000 {
>     term = .succ(term)
> }
> 
> Thanks,
> Dimitri Racordon
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolut...@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to