[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