Hello Swift Evolution,
Its not uncommon to have to do a piece of work only once or on the first
iteration of
a loop.
Take for example producing a comma separated string from an Array:
var result = ""
let values = [1, 2, 3, 4, 5]
var gen = values.generate()
if let first = gen.next() {
result += "\(first)"
while let value = gen.next() {
result += ", "
result += "\(value)"
}
}
Since on the first iteration we want to skip putting a comma in front we
use an `if let` to grab the first element and then embed a `while let`
inside the `if let` to handle the rest.
Another way to do this could be using a bool to keep track of the first
iteration:
var first = true
while let value = gen.next() {
if first {
result += "\(value)"
first = false
continue
} else {
result += ", "
result += "\(value)"
}
}
These approaches work, but I think there may be a way to do this with less
noise.
If there was a keyword to execute a block of code only on the first
iteration of a loop I think that would make code like this more concise.
If there was a keyword like `once` then the same thing could be achieved
with something like:
while let value = gen.next() {
once {
result += "\(value)"
continue
}
result += ", "
result += "\(value)"
}
How does it sound?
- Nick
codafi
(Robert Widmann)
2
Not to doubt the usefulness of this proposal in general, but your example is subsumed by simply declaring
var result = "\(gen.next()!)"
and proceeding with the rest of the example sans `once`. I think you'll also have to address how this is any different from dispatch_once or a DSL over the same.
Cheers,
~Robert Widmann
2016/05/17 0:03、Nicholas Maccharoli via swift-evolution <swift-evolution@swift.org> のメッセージ:
···
Hello Swift Evolution,
Its not uncommon to have to do a piece of work only once or on the first iteration of
a loop.
Take for example producing a comma separated string from an Array:
var result = ""
let values = [1, 2, 3, 4, 5]
var gen = values.generate()
if let first = gen.next() {
result += "\(first)"
while let value = gen.next() {
result += ", "
result += "\(value)"
}
}
Since on the first iteration we want to skip putting a comma in front we use an `if let` to grab the first element and then embed a `while let` inside the `if let` to handle the rest.
Another way to do this could be using a bool to keep track of the first iteration:
var first = true
while let value = gen.next() {
if first {
result += "\(value)"
first = false
continue
} else {
result += ", "
result += "\(value)"
}
}
These approaches work, but I think there may be a way to do this with less noise.
If there was a keyword to execute a block of code only on the first iteration of a loop I think that would make code like this more concise.
If there was a keyword like `once` then the same thing could be achieved with something like:
while let value = gen.next() {
once {
result += "\(value)"
continue
}
result += ", "
result += "\(value)"
}
How does it sound?
- Nick
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
Hello Swift Evolution,
Its not uncommon to have to do a piece of work only once or on the first iteration of
a loop.
Take for example producing a comma separated string from an Array:
var result = ""
let values = [1, 2, 3, 4, 5]
var gen = values.generate()
if let first = gen.next() {
result += "\(first)"
while let value = gen.next() {
result += ", "
result += "\(value)"
}
}
Since on the first iteration we want to skip putting a comma in front we use an `if let` to grab the first element and then embed a `while let` inside the `if let` to handle the rest.
Another way to do this could be using a bool to keep track of the first iteration:
var first = true
while let value = gen.next() {
if first {
result += "\(value)"
first = false
continue
} else {
result += ", "
result += "\(value)"
}
}
These approaches work, but I think there may be a way to do this with less noise.
If there was a keyword to execute a block of code only on the first iteration of a loop I think that would make code like this more concise.
If there was a keyword like `once` then the same thing could be achieved with something like:
while let value = gen.next() {
once {
result += "\(value)"
continue
}
result += ", "
result += "\(value)"
}
How does it sound?
IMO, a better approach would be to write an 'interleave' combinator, like this:
func interleave<S: Sequence>(_ x: S, between: () -> (), each: S.GeneratorType.Element -> ()) {
var generator = x.generate()
if let first = generator.next() {
each(first)
while let rest = generator.next() {
between()
each(rest)
}
}
}
-Joe
···
On May 16, 2016, at 11:03 PM, Nicholas Maccharoli via swift-evolution <swift-evolution@swift.org> wrote:
- Nick
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
This only works with the example exactly as-is, I think a fairer re-write would be something like the following:
func toCSV(values:[CustomStringConvertible]) -> String {
var gen = values.generate()
var result = gen.next()?.description ?? ""
while let value = gen.next() { result += ", \(value)" }
return result
}
toCSV([1, 2, 3, 4, 5])
For brevity I opted to use nil-coalescing and a default value to handle the first (potentially nil) element cleanly.
I’m undecided about whether I want the feature or not; as shown the example can actually be handled very neatly already, so it doesn’t really highlight a need for the feature. One thing I like about it though is the ability to possibly eliminate the need for a generator and use a for in loop instead, like so:
func toCSV(values:[CustomStringConvertible]) -> String {
var result = ""
for value in values {
once { result += "\(value)"; continue }
result += ", \(value)"
}
return result
}
But this isn’t really much of a saving. I can’t think of a real-world example offhand that can better demonstrate a use for this; ideally you’d want to use several once {} blocks, or do something in the loop that requires other statements in the loop, i.e- you use the once to avoid duplicating statements in the loop while processing the first element.
···
On 17 May 2016, at 07:13, Robert Widmann via swift-evolution <swift-evolution@swift.org> wrote:
Not to doubt the usefulness of this proposal in general, but your example is subsumed by simply declaring
var result = "\(gen.next()!)"
and proceeding with the rest of the example sans `once`. I think you'll also have to address how this is any different from dispatch_once or a DSL over the same.
Cheers,
~Robert Widmann
2016/05/17 0:03、Nicholas Maccharoli via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:
Hello Swift Evolution,
Its not uncommon to have to do a piece of work only once or on the first iteration of
a loop.
Take for example producing a comma separated string from an Array:
var result = ""
let values = [1, 2, 3, 4, 5]
var gen = values.generate()
if let first = gen.next() {
result += "\(first)"
while let value = gen.next() {
result += ", "
result += "\(value)"
}
}
Since on the first iteration we want to skip putting a comma in front we use an `if let` to grab the first element and then embed a `while let` inside the `if let` to handle the rest.
Another way to do this could be using a bool to keep track of the first iteration:
var first = true
while let value = gen.next() {
if first {
result += "\(value)"
first = false
continue
} else {
result += ", "
result += "\(value)"
}
}
These approaches work, but I think there may be a way to do this with less noise.
If there was a keyword to execute a block of code only on the first iteration of a loop I think that would make code like this more concise.
If there was a keyword like `once` then the same thing could be achieved with something like:
while let value = gen.next() {
once {
result += "\(value)"
continue
}
result += ", "
result += "\(value)"
}
How does it sound?
- Nick
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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
CTMacUser
(Daryle Walker)
5
Aren’t there already methods that stick elements between others (and only between, neither before the first nor after the last)?
//=====
fun toCSV2(values: [CustomStringConvertible]) -> String {
return values.map { $0.description }.joinWithSeparator(“, “)
}
//=====
···
—
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com
On May 17, 2016, at 11:49 AM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:
This only works with the example exactly as-is, I think a fairer re-write would be something like the following:
func toCSV(values:[CustomStringConvertible]) -> String {
var gen = values.generate()
var result = gen.next()?.description ?? ""
while let value = gen.next() { result += ", \(value)" }
return result
}
toCSV([1, 2, 3, 4, 5])
For brevity I opted to use nil-coalescing and a default value to handle the first (potentially nil) element cleanly.
I’m undecided about whether I want the feature or not; as shown the example can actually be handled very neatly already, so it doesn’t really highlight a need for the feature. One thing I like about it though is the ability to possibly eliminate the need for a generator and use a for in loop instead, like so:
func toCSV(values:[CustomStringConvertible]) -> String {
var result = ""
for value in values {
once { result += "\(value)"; continue }
result += ", \(value)"
}
return result
}
But this isn’t really much of a saving. I can’t think of a real-world example offhand that can better demonstrate a use for this; ideally you’d want to use several once {} blocks, or do something in the loop that requires other statements in the loop, i.e- you use the once to avoid duplicating statements in the loop while processing the first element.
On 17 May 2016, at 07:13, Robert Widmann via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Not to doubt the usefulness of this proposal in general, but your example is subsumed by simply declaring
var result = "\(gen.next()!)"
and proceeding with the rest of the example sans `once`. I think you'll also have to address how this is any different from dispatch_once or a DSL over the same.
Cheers,
~Robert Widmann
2016/05/17 0:03、Nicholas Maccharoli via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:
Hello Swift Evolution,
Its not uncommon to have to do a piece of work only once or on the first iteration of
a loop.
Take for example producing a comma separated string from an Array:
var result = ""
let values = [1, 2, 3, 4, 5]
var gen = values.generate()
if let first = gen.next() {
result += "\(first)"
while let value = gen.next() {
result += ", "
result += "\(value)"
}
}
Since on the first iteration we want to skip putting a comma in front we use an `if let` to grab the first element and then embed a `while let` inside the `if let` to handle the rest.
Another way to do this could be using a bool to keep track of the first iteration:
var first = true
while let value = gen.next() {
if first {
result += "\(value)"
first = false
continue
} else {
result += ", "
result += "\(value)"
}
}
These approaches work, but I think there may be a way to do this with less noise.
If there was a keyword to execute a block of code only on the first iteration of a loop I think that would make code like this more concise.
If there was a keyword like `once` then the same thing could be achieved with something like:
while let value = gen.next() {
once {
result += "\(value)"
continue
}
result += ", "
result += "\(value)"
}
How does it sound?
- Nick
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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