[swift-evolution] Proposal: Add generator functions to the language

Kametrixom Tikara kametrixom at icloud.com
Fri Dec 11 19:58:19 CST 2015


My mistake, here is a truly lazy version (it gets a little ugly yes):

func helloGenerator(name : String?) -> LazyMapCollection<[() -> String], String> {
    return [
        { "Hello" },
        { name ?? "World" }
    ].lazy.map{ $0() }
}

I agree that this would make it very convenient. I’m +.5 on this, because I don’t like adding two more keywords for a single feature, but it seems like it has good applications

> On 12 Dec 2015, at 02:50, Kevin Wooten <kdubb at me.com> wrote:
> 
>> 
>> On Dec 11, 2015, at 6:38 PM, Kametrixom Tikara via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> What exactly is the difference to just returning a sequence?
>> 
>> func helloGenerator(name : String?) -> [String] {
>>     return [
>>         "Hello",
>>         name ?? "World"
>>     ]
>> }
>> 
>> for str in helloGenerator("David") {
>>     print(str)
>> }
>> 
>> And if you want if lazy:
>> 
>> func helloGenerator(name : String?) -> LazyCollection<[String]> {
>>     return [
>>         "Hello",
>>         name ?? "World"
>>     ].lazy
>> }
>> 
> 
> Imagine reading images from a directory and returning them lazily.  I don’t think anybody is arguing that you cannot implement it now with a special lazy collection (your version actually materializes the array fully first) but here’s how simple it could be:
> 
> func readAllImagesInDirectory(path: String) -> GeneratorType<Image> {
> 	let imagePaths = listImagesInDirectory(path)
> 	return generator func generatorImage() -> Image {
> 		for imagePath in imagePaths {
> 			yield readImageAtPath(image
> 		}
> 	}
> }
> 
> (Please forgive any errant syntax in my contrived example).  Point is it could be a very fast/compact way to create generators; although it’s possible today.
> 
>> Seems like exactly the same, except it doesn’t need two new keywords nor revamping of SequenceType/GeneratorType
>> 
>>> On 12 Dec 2015, at 01:21, David Waite via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> Looking for feedback on crafting a proposal adding generator functions to Swift. I understand this will likely be a very involved proposal at the language level, although I actually don’t know the complexity of the change within the Swift compiler itself.
>>> 
>>> This would be a function which returns multiple values, which is converted by the compiler to a function returning a SequenceType
>>> 
>>> A very basic syntax would be to add generator as a modifier to func, and likely involve a new keyword ‘yield’ to differentiate from the flow control behavior of ‘return’.
>>> 
>>> So for example:
>>> 
>>> generator func helloGenerator(name:String?) -> String {
>>>     yield “Hello”
>>>     yield name ?? “World”
>>> }
>>> 
>>> Would have the following expected usage:
>>> 
>>> for str in helloGenerator(“David") {
>>>    print str
>>> // prints:
>>> //    Hello
>>> //    David
>>> }
>>> 
>>> And for those unfamiliar to these sorts of simple cases, would have equivalent behavior to the following code:
>>> 
>>>  45> func helloGenerator(name:String?) -> HelloGenerator { 
>>>  46.   return HelloGenerator(name) 
>>>  47. } 
>>>  48.  
>>>  49. struct HelloGenerator : GeneratorType, SequenceType { 
>>>  50.    var position:Int = 0 
>>>  51.    let name:String? 
>>>  52.  
>>>  53.    private init(_ name:String?) { 
>>>  54.       self.name = name 
>>>  55.    } 
>>>  56.     
>>>  57.    func generator() -> HelloGenerator {
>>>  58.        return self 
>>>  59.    } 
>>>  60.      
>>>  61.    mutating func next() -> String? { 
>>>  62.       switch position { 
>>>  63.       case 0: 
>>>  64.           position = 1 
>>>  65.           return "Hello" 
>>>  66.       case 1: 
>>>  67.           position = 2 
>>>  68.           return name ?? "World" 
>>>  69.       default: 
>>>  70.           return nil 
>>>  71.       } 
>>>  72.    } 
>>>  73. } 
>>> 
>>> This syntax has at a bare minimum issues with generator closures and for a terse syntax for yielding over another sequence type within a generator function vs. using a loop. (possibly “yield in sequenceName”)
>>> 
>>> The interaction with the error system might involve disallowing throws from generator functions, or having the Element type be a Result<T> rather than T, as the GeneratorType next() method is not declared as throwing.
>>> 
>>> This could pair well to make for-in loops more comprehensive, especially if C-style for loops are eliminated.
>>> 
>>> This would possibly be a first step toward a coroutine-based concurrency system, although I am not proposing that sort of usage or scope here. The goal would be to emit an object compatible with SequenceType
>>> 
>>> -David Waite (DW)
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151212/ea9c2df2/attachment.html>


More information about the swift-evolution mailing list