How Do Generators Whose Element Is Optional Know When They'Ve Reached the End

For-in loop goes one-too-far and finds 'nil' while unwrapping

Basically you've done something you're not supposed to do, and thus you've stumbled on something that's probably a compiler bug (because the compiler didn't stop you). Very nice!

Now the solution. You are evidently trying to unwrap with your Int!. To unwrap safely, use for case syntax:

let list:[Int?] = [1,2,3,4,5,6,7]
for case let x? in list
{
print(x) // 1, 2, 3, 4, 5, 6, 7
}

Another way (same result):

let list:[Int?] = [1,2,3,4,5,6,7]
list.flatMap{$0}.forEach{print($0)} // 1, 2, 3, 4, 5, 6, 7

Is it possible to implement a Swift SequenceType that contains nil elements?

Here is a (quite silly) example:

struct OddSequence : SequenceType {

func generate() -> GeneratorOf<Int?> {
var current = 0
return GeneratorOf<Int?>() {
if current >= 6 {
return nil
}
current++
if current % 2 == 0 {
return current
} else {
return Optional(nil)
}
}
}
}


for x in OddSequence() {
println(x)
}

Output:

nil
Optional(2)
nil
Optional(4)
nil
Optional(6)

The generator returns an optional (which can be Optional(nil)) for each element,
and nil if the sequence is exhausted.

See also "Optionals Case Study: valuesForKeys" in the Swift blog about the difference between nil and
Optional(nil) and its applications.


Update for Swift 2:

struct OddSequence : SequenceType {

func generate() -> AnyGenerator<Int?> {
var current = 0
return anyGenerator {
if current >= 6 {
return nil
}
current++
if current % 2 == 0 {
return current
} else {
return Optional(nil)
}
}
}
}

for x in OddSequence() {
print(x)
}

How to make a function operate on a Sequence of Optional values?

Try this:

func firstValue<E, S: SequenceType where S.Generator.Element == Optional<E> >(seq: S) -> E? {
var g = seq.generate()
while let e:Optional<E> = g.next() {
if e != nil {
return e
}
}
return nil
}

let a:[Int?] = [nil,nil, 42, nil]
println(firstValue(a)) // -> 42 as Int?

I tested with Xcode Version 6.1.1 (6A2006) and Version 6.2 (6C86e)


Note

Without :Optional<E> in while condition, the compiler crashes.

And if we declare the function like this, the compiler clashes on some environment.

func firstValue<S: SequenceType, E where S.Generator.Element == Optional<E> > {
// ^^^^^^^^^^^^^^^^^^ replaced E and S

I think these are compiler bug. Please see the comments below.

EnumerateGenerator and Tuple

From "For-In Statement" in the Swift documentation:

A for-in statement allows a block of code to be executed once for each
item in a collection (or any type) that conforms to the SequenceType
protocol.

The generate method is called on the collection expression to obtain a
value of a generator type—that is, a type that conforms to the
GeneratorType protocol. The program begins executing a loop by calling
the next method on the stream. If the value returned is not None, it
is assigned to the item pattern, the program executes the statements,
and then continues execution at the beginning of the loop. Otherwise,
the program does not perform assignment or execute the statements, and
it is finished executing the for-in statement.

So

for (index, value) in enumerate([1, 2, 3, 4, 5]) {
// ...
}

is identical to

let enumGenerator = enumerate([1, 2, 3, 4, 5])
var genFunc = enumGenerator.generate()
while let (index, value) = genFunc.next() {
// ...
}
  • let enumGenerator = enumerate([1, 2, 3, 4, 5]) returns a
    EnumerateGenerator<Seq.Generator> (in this
    case a EnumerateGenerator<IndexingGenerator<Array<Int>>>). This conforms to the
    SequenceType protocol.

  • var genFunc = enumGenerator.generate() returns again a
    EnumerateGenerator<Seq.Generator> (probably a copy of the enumGenerator).
    This conforms to the GeneratorType protocol.

  • genFunc.next() returns Element? where Element is a type alias for
    (index: Int, element: Base.Element).

    In this case, next() returns (index: Int, element: Int)?. This next function
    returns optional tuples until the array is exhausted, where it returns nil.

Avoid handling all exceptions until they've reached a global handler


Is it possible to ignore f's exceptions such that they ultimately become un-handled exceptions that can be handled globally?

In a word, no. The entire point of the design of Swift's error handling is that you must explicitly acknowledge the possibility of error at every stage.

It sounds to me like you're thinking of how Objective-C deals with NSException, but Swift isn't like that (and Error is not like NSException).

Enumerate/Iterate over an array using Blocks and know when it is completed

enumerateObjectsUsingBlock executes synchronously. The enumeration is finished
when the method returns.

stop is a reference to a Boolean which can be set to true to stop further processing,
for example:

itemsArray.enumerateObjectsUsingBlock {
(object, index, stop) -> Void in

// process at most 5 elements:
if index == 4 {
stop.memory = true
}
}

Testing if stop == true inside the block does not make sense.

Difference between Python xrange and generators?

Both range and generator objects are examples of iterable objects.

A range is defined by a stopping value, with an optional starting value and optional step size allowed. The result is an iterable of integers. A range also supports operations (like containment) that are not necessarily supported by other iterables.

A generator is defined by a generator expression or a generator function, either of which results in an iterable of arbitrary values.

The iterable aspect of a range object can be simulated by a generator:

def myrange(stop, start=None, step=None):
if start is not None:
from_ = stop
to_ = start
else:
from_ = 0
to_ = stop

if step is None:
step = 1 if from_ < to_ else -1

while from_ < to_:
yield from_
from_ += step

Then

>>> list(myrange(1, 10))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1, 10))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

As Python 2 reached end-of-life nearly a year ago, there's not much reason to go into range. Suffice it to say, in Python 2 range was a function that returned a list of integers, while xrange was a type whose value represents a list of integers. Python 3 did away with the function and reused the name for the type.



Related Topics



Leave a reply



Submit