I think a better solution than just adding a TreeLiteral (and the accompanying TreeLiteralConvertible protocol) would be to allow user-defined literal types using regex (or something similar). This would not only allow for tremendous flexibility, but it’d remove some compiler magic as well.
There’d have to be some rules regarding overlapping definitions… The simplest I can think of is make it an error to not do type annotation when there’s more than one way to parse a literal, but I’m not sure that’s necessarily the best. - Dave Sweeris > On Apr 14, 2016, at 11:27 AM, Milos Rankovic via swift-evolution > <swift-evolution@swift.org> wrote: > > In Swift, we cannot compile: > > _ = [[], 1, [2, 3], [[4, 5], [6, 7], [8, 9]]] > > The reason for the compile-time error is that we are not in fact creating an > array, but a tree – a more general structure of which arrays are only a > special case. Given the well-deserved and growing reputation of Swift, one > would hope that in this instance the compiler would be able to default to > something like a: > > enum Tree<Value> { > case Leaf(Value) > case Branches([Tree]) > } > > extension Tree : ArrayLiteralConvertible { > init(arrayLiteral elements: Tree...) { > self = .Branches(elements) > } > } > > For this to work in the playground, however, we must manually lift the values > into the world of trees first. And to make that chore in turn easier on the > eye we can introduce a: > > prefix operator ◊ {} // looks a bit like a leaf (us/uk kbd: ⎇⇧V) > prefix func ◊ <T> (leaf: T) -> Tree<T> { return .Leaf(leaf) } > > let tree: Tree<Int> = [[], ◊1, [◊2, ◊3], [[◊4, ◊5], [◊6, ◊7], [◊8, ◊9]]] > > The point here is that if adding such a fundamental type to the Standard > Library would not be a priority at present, it is not the end of the world > since we can easily enough write it ourselves… What we cannot do ourselves, > however, is to get rid of the need for that operator in the common scenario > of initialising with literal values. For this we need a literal-convertible > protocol requiring two initialisers: > > protocol TreeLiteralConvertible { > associatedtype LeafValue > init(literal: Self.LeafValue...) > init(literal: Self...) > } > > Then we could simply: > > let tree: Tree<Int> = [[], 1, [2, 3], [[4, 5], [6, 7], [8, 9]]] > > And, whilst we are at it, we could also get rid of the need for that operator > in the case of nested associative arrays (again, you can try this in the > playground): > > enum DictionaryTree<Key, Value> { > case Leaf(Value) > case Branches([(Key, DictionaryTree)]) > } > > extension DictionaryTree : DictionaryLiteralConvertible { > init(dictionaryLiteral pairs: (Key, DictionaryTree)...) { > self = .Branches(pairs) > } > } > > prefix func ◊ <Key, Value> (leaf: Value) -> DictionaryTree<Key, Value> { > return .Leaf(leaf) } > > let map: DictionaryTree<String,Int> = [ > "A" : [:], > "B" : [ > "Ba" : ◊0, > "Bb" : ◊0, > "Bc" : [ > "Bc1" : ◊0, > "Bc2" : ◊0, > "Bc3" : ◊0 > ] > ] > ] > > … by introducing an analogous protocol: > > protocol DictionaryTreeLiteralConvertible { > associatedtype Key > associatedtype LeafValue > init(literal: Self.LeafValue...) > init(literal: (Key, Self)...) > } > > Please note: I do understand that fleshing out these structures (along with > all the juicy methods, operators and lazy alternatives) may not currently be > a priority for Swift. The two literal-convertible protocols however, may be a > much less daunting task, which would open to us some very useful programming > idioms… > > milos > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution