While optional, unwrap if contains something - swift

The context : I have a generic stack of objects. The stack responds to pop() (returns an optional) and I have a function that needs to process the stack
If the stack is empty, throw an error
Otherwise, repeat repeat operation until next optional is not unwrappable
So far
guard var nextVar = myStack.pop() else {
throw MyError.EmptyStack
}
repeat {
// Process nextVar
} while nextVar = myStack.pop()
Problem : the first nextVar is NOT an Optional, therefore my while call fails. How can I rewrite so that the while checks whether the optional contains something AND if that succeeds, assign the content to the variable ? ()

You should modify your stack type to include an isEmpty property. Then you won't need to duplicate the pop call, and this will be a simple while-let loop.
guard !myStack.isEmpty else {
throw MyError.EmptyStack
}
while let nextVar = myStack.pop() {
// Process nextVar
}
You can also convert this into a SequenceType, but then iterating won't consume the stack. Then this would just be:
guard !myStack.isEmpty else {
throw MyError.EmptyStack
}
for nextVar in myStack {
// Process nextVar
}
Since pop is exactly the needed implementation of GeneratorType.next(), it should be easy to turn this into a GeneratorType and a SequenceType (by returning self in generate()).
But since Stack is a value type, iterating over it with for-in will make a copy and then consume that copy, rather than consuming the original stack. That could be good or bad.
Here's a sketch of what I mean:
struct Stack<Element> {
private var stack: [Element] = []
mutating func push(element: Element) {
stack.append(element)
}
mutating func pop() -> Element? {
guard let result = stack.last else { return nil }
stack.removeLast()
return result
}
var isEmpty: Bool { return stack.isEmpty }
}
extension Stack: GeneratorType {
mutating func next() -> Element? {
return pop()
}
}
extension Stack: SequenceType {
func generate() -> Stack {
return self
}
}

Related

Extends Set's insert in swift for custom logic

I need to have custom logic in a Set that defines when a Hashable can be insert or not.
First I tried to solve this with a observer
var Tenants: Set<Tenant> = [] {
willSet {
// to the business logic here
// ...
But in an observer i can not return an error. So I tried to extend Set to overwrite the insert method.
extension Set where Element == Tenant {
#inlinable mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element){
// .... do my logic here ...
return (true, newMember)
}
}
That works so far and the method will be called. I can return true and if my logic did not pass even a false. Ok, but how do I add the Element into the Set? super.insert(). The return is correct, but the Set is empty. How to add the elements into the concrete set?
Implementation so far
/// Global set of known tenants
var Tenants: Set<Tenant> = [] {
willSet {
let newTenants = newValue.symmetricDifference(Tenants)
guard let newTenant = newTenants.first else {
Logging.main.error("Can not find tenant to add.")
return
}
Logging.main.info("Will add new Tenant \(newTenant.name) [\(newTenant.ident)]")
}
}
extension Set where Element == Tenant {
#inlinable mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element){
print("Check to add...")
// .... do my logic here ...
// ok
return (true, newMember)
}
}
The result is:
Check to add...
error : Can not find tenant to add.
Check to add...
error : Can not find tenant to add.
This seems to work for "do my logic here"
self = self.union([newMember])
Edit: Because this breaks the semantics of Set, I think it is better to write it as something like this:
struct CheckedSet<T: Hashable> {
private(set) var wrappedSet: Set<T> = []
var shouldInsert: (T) -> Bool = { _ in true }
mutating func maybeInsert(_ t: T) {
guard shouldInsert(t) else { return }
wrappedSet.insert(t)
}
}
var cs = CheckedSet<String>()
cs.shouldInsert = { str in str.allSatisfy(\.isLowercase) }
cs.maybeInsert("HELLO")
cs.wrappedSet // []
cs.maybeInsert("hello")
cs.wrappedSet // ["hello"]
I would do it with a property wrapper:
#propertyWrapper
struct TenantsSet {
var wrappedSet: Set<Tenant>
struct Projected {
let error: Bool
}
var projectedValue = Projected(error: false)
var wrappedValue: Set<Tenant> {
get { wrappedSet }
set {
print("some custom logic")
// set projectedValue appropriately
wrappedSet = newValue
}
}
init(wrappedValue: Set<Tenant>) {
wrappedSet = wrappedValue
}
}
This allows error-reporting by checking the error property on the projected value:
#TenantsSet var tenants = []
func f() {
tenants = [Tenant()]
if $tenants.error {
}
}
As the Swift Guide says:
Extensions add new functionality to an existing class, structure, enumeration, or protocol type.
You are not supposed to use them to modify existing behaviour. It would be very confusing to readers of your code. If you want to use an extension to do this, you should declare a new method, with a different signature. Perhaps call it insert(newTenant:)?

Question about the conditional sentence of Observable. (RxSwift)

I tried to create a function runsample() that uses multiple observables as below.
If I meet a specific condition in the middle of the stream, I want to start from the beginning of function.
(foo1() in the example below)
In this case, how do I modify the runsample() function?
class SampleClass {
////////////////////////////////
// private
////////////////////////////////
private func foo1() -> Observable<String> {
// Do something
return .just("TEST")
}
private func foo2() -> Observable<Bool> {
// Do something
return .just(false) // or true
}
private func foo3() -> Observable<String> {
// Do something
return .just("Result")
}
////////////////////////////////
// public
////////////////////////////////
public func runSample() -> Observable<String> {
return Observable.just(())
.flatMap { [unowned self] _ in
self.foo1()
}
.flatMap { [unowned self] _ in
self.foo2()
}
// I want to retry foo1() when foo2() is false
// I want to make foo3() run only if foo2() is true.
.flatMap { [unowned self] _ in
self.foo3()
}
}
}
Based on your comment, this is what you want:
func runSample() -> Observable<String> {
struct NotValid: Error { }
return Observable.deferred {
foo1().flatMap { _ in
foo2().do(onNext: { isValid in
if !isValid { throw NotValid() }
})
}
}
.retry()
.flatMap { _ in foo3() }
}
It's a very strange requirement you have, but it's doable. I expect this is an X-Y problem though.
You really want to retry foo1()? That would imply that it failed but it obviously didn't. In any case, this will do what you want:
func runSample() -> Observable<String> {
foo1()
.flatMap { [foo2] _ in
foo2()
}
.flatMap { [foo1, foo3] isTrue in
isTrue ? foo3() : foo1()
}
}
This function will return an Observable. Every time that Observable is subscribed to, the first foo1() will be activated.
Every time the first foo1() emits a value, the value will be ignored (which is quite odd) and foo2() will be called. This will generate a new Observable which will be subscribed to.
Whenever any of the Observables generated by foo2() emit a value, if the value is true foo3() will be called, otherwise foo1() will be called. Whichever one is called, its Observable will be subscribed to.
The entire function will emit all the values that any foo1()s or foo3()s Observables emit.
Importantly for this example, you do not need to start with Observable.just(()).
Thinking about it, I'd prefer something like this:
func runSample() -> Observable<String> {
Observable.zip(foo1(), foo2())
.flatMap { $0.1 ? foo3() : .just($0.0) }
}
That way I don't have to run foo1() twice.

Using Swift generics in a RxSwift getter function - various problems

Here's the function:
func registerFor<Element>(relayId id: String) -> Driver<Element>? {
guard let relay = relays[id] as? BehaviorRelay<Element> else { return nil }
return relay.asObservable()
.distinctUntilChanged { a, b in
return a != b
}.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: Element())
}
The distinctUntilChanged line throws the following error:
Contextual closure type '(Element) throws -> _' expects 1 argument,
but 2 were used in closure body
The asDriver line throws the following error (of course):
Non-nominal type 'Element' does not support explicit initialization
Context: I have a class that ideally has a collection of BehaviorRelays of various types (Strings, Ints, etc). Element stands in generically for these types, but that creates two problems:
distinctUntilChanged insists of having a closure (eg: if this method returned Driver<String> it would be content simply to use distinctUntilChanged() but the generic Element makes it complain about missing a closure);
onErrorJustReturn requires a concrete value, but Element is generic.
The following "workaround" might work but I suspect there are better solutions
protocol Inii {
init()
}
func registerFor(relayId id: String, def: Inii.Type) -> Driver<Inii>? {
return relays[id]?.asObservable()
.distinctUntilChanged { _, _ in
return true
}.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: def.init())
}
Although I'm still unsure what to put in the distinctUntilChanged closure.
Appendix A
I believe that the following is what is required if one is implementing the distinctUntilChanged closure for a non-generic type:
.distinctUntilChanged { previousValue, currentValue in
return previousValue == currentValue
}
However, when used with the generic Element the following error is still thrown:
Contextual closure type '(Inii) throws -> _' expects 1 argument,
but 2 were used in closure body
Appendix B
Here's another alternative with a slightly different problem:
protocol Inii {
init()
}
var relay = BehaviorRelay<String>(value: "")
func registerFor<Element>(def: Element.Type) -> Driver<Element> where Element: Inii {
return relay.asObservable()
.distinctUntilChanged { previousValue, currentValue in
return previousValue == currentValue
}.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: def.init())
}
Error in this case being:
Member 'next' in 'Event<_>' produces result of type 'Event<Element>',
but context expects 'Event<_>'
at the observer.on line
You can use distinctUntilChanged() without a closure as long as Element conforms to Equatable:
protocol EmptyInit {
init()
}
func registerFor<Element>(relayId id: String) -> Driver<Element>? where Element: Equatable, Element: EmptyInit {
guard let relay = relays[id] as? BehaviorRelay<Element> else { return nil }
return relay.asObservable()
.distinctUntilChanged()
.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: Element())
}

RxSwift unwrap optional handy function?

Currently I have created a function unwrapOptional to safely unwrap the optional input in the stream.
func unwrapOptional<T>(x: Optional<T>) -> Observable<T> {
return x.map(Observable.just) ?? Observable.empty()
}
let aOpt: String? = "aOpt"
_ = Observable.of(aOpt).flatMap(unwrapOptional).subscribeNext { x in print(x)}
let aNil: String? = nil
_ = Observable.of(aNil).flatMap(unwrapOptional).subscribeNext { x in print(x)}
let a: String = "a"
_ = Observable.of(a).flatMap(unwrapOptional).subscribeNext { x in print(x)}
// output
aOpt
a
What I want to archive is to create a handy function instead of using flatMap(unwrapOptional), for example
Observable.of(a).unwrapOptional()
Something I tried to do, but it never compiles...
extension ObservableType {
func unwrapOptional<O : ObservableConvertibleType>() -> RxSwift.Observable<O.E> {
return self.flatMap(unwrapOptional)
}
}
You want the unwrapOptional method to only work on observables that have optional type.
So you somehow have to constraint the Element of Observable to conform to the Optional protocol.
extension Observable where Element: OptionalType {
/// Returns an Observable where the nil values from the original Observable are
/// skipped
func unwrappedOptional() -> Observable<Element.Wrapped> {
return self.filter { $0.asOptional != nil }.map { $0.asOptional! }
}
}
Unfortunately, Swift does not define such a protocol (OptionalType). So you also need to define it yourself
/// Represent an optional value
///
/// This is needed to restrict our Observable extension to Observable that generate
/// .Next events with Optional payload
protocol OptionalType {
associatedtype Wrapped
var asOptional: Wrapped? { get }
}
/// Implementation of the OptionalType protocol by the Optional type
extension Optional: OptionalType {
var asOptional: Wrapped? { return self }
}
checkout unwrap at https://github.com/RxSwiftCommunity/RxSwift-Ext :)
or https://github.com/RxSwiftCommunity/RxOptional
For now, you should use RxOptional for your personal needs
However, RxSwift-Ext will be growth exponentially in next 2-3 months :)
RxSwift now supports compactMap(). So, now you can do things like:
func unwrap(_ a: Observable<Int?>) -> Observable<Int> {
return a.compactMap { $0 }
}
Here's a version without needing OptionalType (from https://stackoverflow.com/a/36788483/13000)
extension Observable {
/// Returns an `Observable` where the nil values from the original `Observable` are skipped
func unwrap<T>() -> Observable<T> where Element == T? {
self
.filter { $0 != nil }
.map { $0! }
}
}

Implementing recursive generator for simple tree structure in Swift

I have a simple tree structure in memory based on an XML document and I am trying to write a recursive generator to support SequenceType, but I am stuck on how to actually do this.
Here was my first attempt:
#objc public class XMLNode: NSObject, SequenceType {
public weak var parentNode: XMLNode?
public var nodeName: String
public var attributes: [String: String]
public var childNodes = [XMLNode]()
public func generate() -> AnyGenerator<XMLNode> {
var childGenerator = childNodes.generate()
var returnedSelf = false
return anyGenerator {
let child = childGenerator.next()
if child != nil {
// I need to somehow recurse on child here
return child
} else if !returnedSelf {
returnedSelf = true
return self
} else {
return nil
}
}
}
}
Since childNodes is an array, I'm calling its own built-in generate() function to create a generator on the child nodes and iterating it, and then returning self at the end. The problem is it's not recursing on each child, so it only ever goes one level deep. I can't figure out how to combine two generators in that way.
I'm having a hard time wrapping my head around how to do this! What do I need to do to make a recursive generator?
I don't know if a generator itself can be recursive.
Will M proved me wrong!
Here is a possible implementation for a pre-order traversal, using a stack for the child nodes which still have to be enumerated:
extension XMLNode : SequenceType {
public func generate() -> AnyGenerator<XMLNode> {
var stack : [XMLNode] = [self]
return anyGenerator {
if let next = stack.first {
stack.removeAtIndex(0)
stack.insertContentsOf(next.childNodes, at: 0)
return next
}
return nil
}
}
}
For a level-order traversal, replace
stack.insertContentsOf(next.childNodes, at: 0)
by
stack.appendContentsOf(next.childNodes)
Here is a recursive post-order generator. Can't say I'd recommend actually using it though.
#MartinR's answer seems a bit more practical
public func generate() -> AnyGenerator<XMLNode> {
var childGenerator:AnyGenerator<XMLNode>?
var childArrayGenerator:IndexingGenerator<[XMLNode]>? = self.childNodes.generate()
var returnedSelf = false
return anyGenerator {
if let next = childGenerator?.next() {
return next
}
if let child = childArrayGenerator?.next() {
childGenerator = child.generate()
return childGenerator?.next()
} else if !returnedSelf {
returnedSelf = true
return self
} else {
return nil
}
}
}
While Martin's answer is certainly more concise, it has the downside of making a lot of using a lot of array/insert operations and is not particularly usable in lazy sequence operations. This alternative should work in those environments, I've used something similar for UIView hierarchies.
public typealias Generator = AnyGenerator<XMLNode>
public func generate() -> AnyGenerator<XMLNode> {
var childGenerator = childNodes.generate()
var subGenerator : AnyGenerator<XMLNode>?
var returnedSelf = false
return anyGenerator {
if !returnedSelf {
returnedSelf = true
return self
}
if let subGenerator = subGenerator,
let next = subGenerator.next() {
return next
}
if let child = childGenerator.next() {
subGenerator = child.generate()
return subGenerator!.next()
}
return nil
}
}
Note that this is preorder iteration, you can move the if !returnedSelf block around for post order.