How to combine two sequences cumulatively in RxSwift? - swift

I have two sequences and I'd like to combine them so that any results coming into the second sequence would be cumulatively combined with the latest result from the first sequence.
A---------------B----------------------C------------- ...
-------1-2-----------3-------------------------------- ...
So that the result would be:
A-----A+1--A+1+2---B----B+3--------------C-------------
How might I do that in Rx? (I'm using RxSwift)

You can use combineLatest + bufferWhen
https://stackblitz.com/edit/typescript-s1pemu
import {bufferWhen} from 'rxjs/operators';
import { timer, interval,combineLatest , } from 'rxjs';
// timerOne emits first value at 1s, then once every 4s
const timerOne$ = interval( 4000);
// timerTwo emits first value at 2s, then once every 4s
const timerTwo$ = interval(1000);
// timerThree emits first value at 3s, then once every 4s
// when one timer emits, emit the latest values from each timer as an array
combineLatest(
timerOne$,
timerTwo$.pipe(bufferWhen(()=>timerOne$)),
)
.subscribe(
([timerValOne, timerValTwo]) => {
console.log(
`Timer One Latest: ${timerValOne},
Timer Two Latest: ${timerValTwo}`,
);
console.log('Total:', timerValOne+timerValTwo.reduce((acc,curr)=>acc+curr))
}
);

Here you go. Hopefully, you can use this as a template on how to write a test to establish what you want and then write the code that produces it.
enum Action<A, B> {
case a(A)
case b(B)
}
func example<A, B>(_ a: Observable<A>, _ b: Observable<B>) -> Observable<(A?, [B])> {
return Observable.merge(a.map(Action.a), b.map(Action.b))
.scan((A?.none, [B]())) { current, next in
switch next {
case .a(let a):
return (a, [])
case .b(let b):
return (current.0, current.1 + [b])
}
}
}
And here is a test to prove it works:
class RxSandboxTests: XCTestCase {
func testExample() {
let scheduler = TestScheduler(initialClock: 0)
let a = scheduler.createColdObservable([.next(0, "A"), .next(16, "B"), .next(39, "C")])
let b = scheduler.createColdObservable([.next(7, 1), .next(9, 2), .next(21, 3)])
let result = scheduler.start {
example(a.asObservable(), b.asObservable())
.map { Result(a: $0.0, b: $0.1) }
}
XCTAssertEqual(
result.events,
[
.next(200, Result(a: "A", b: [])),
.next(207, Result(a: "A", b: [1])),
.next(209, Result(a: "A", b: [1, 2])),
.next(216, Result(a: "B", b: [])),
.next(221, Result(a: "B", b: [3])),
.next(239, Result(a: "C", b: []))
]
)
}
}
struct Result: Equatable {
let a: String?
let b: [Int]
}

Related

How to get count of NSCountedSet?

I'm trying to get count of values from NSCountedSet using loop and have no idea how to get these.
for item in set {
}
I'll be grateful for any help!
You would call count(for:) on the set:
import Foundation
let set: NSCountedSet = ["a", "b", "b", "c", "c", "c"]
for item in set {
print("\(set.count(for: item)) x \"\(item)\"")
}
Prints:
1 x "a"
2 x "b"
3 x "c"
Use method count(for:)
let mySet = NSCountedSet()
mySet.add(1)
mySet.add(2)
mySet.add(2)
for value in mySet {
let count = mySet.count(for: value)
print("Count for \(value) is \(count)")
}
However, note that NSCountedSet is untyped (it's an old Objective-C class), therefore it is not very well suited for Swift.
Luckily, we can implement the same using a simple [T: Int] dictionary.
For example:
struct MyCountedSet<T: Hashable>: Sequence {
typealias Element = T
private var counts: [T: Int] = [:]
mutating func add(_ value: T) {
counts[value, default: 0] += 1
}
func count(for value: T) -> Int {
return counts[value, default: 0]
}
func makeIterator() -> AnyIterator<T> {
return AnyIterator<T>(counts.keys.makeIterator())
}
}
var myCountedSet = MyCountedSet<Int>()
myCountedSet.add(1)
myCountedSet.add(2)
myCountedSet.add(2)
for value in myCountedSet {
let count = myCountedSet.count(for: value)
print("Count for \(value) is \(count)")
}

How to impl From<AStruct> for a tokio_postgres::Row

I've successfully impl From<tokio_postgres::Row> for AStruct, but is it possible to (1) impl From<AStruct> to tokio_postgres::Row and (2) subsequently insert the created tokio_postgres::Row into a table? I've looked at tokio_postgres::Row (see bellow), and also tried to impl tokio_postgres::types::ToSql as well as
tokio_postgres::types::FromSql.
I'd really like to exclusively use Tokio-Postgres for this project, if it's possible.
I have written up a minimal code example bellow to show what I am trying to do.
Let me know if I can clarify my question in any way.
#[derive(ToSql, FromSql, Debug)]
enum E {
A,
B,
}
#[derive(ToSql, FromSql, Debug)]
struct AStruct {
i: i32,
e: E,
d: DateTime<Utc>
}
impl From<Row> for AStruct {
fn from(row: Row) -> Self {
Self {
i: row.get(0),
e: row.get(1),
d: row.get(2),
}
}
}
// TODO
impl From<AStruct> for Row {
fn from(s: S) -> Self {
Self {
statement: ...?,
body: ...?,
ranges: ...?,
}
}
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let (client, _) = tokio_postgres::connect(database_url, NoTls).await?;
let s = AStruct {
i: 1,
e: E::A,
d: Utc::now(),
};
// This works!
let s: AStruct = client
.query("SELECT * FROM structs WHERE id = $1", &[&id])
.await?
.into_iter()
.next()
.unwrap()
.into();
// This does not work :(
let row: Row = s.into();
Ok(())
}

Is there a high-order function to convert a linked list to an array?

Imagine I have a simple linked list:
class Node {
var parent: Node?
}
// Create the chain: a <- b <- c
let a = Node()
let b = Node(parent: a)
let c = Node(parent: b)
Now I want to convert c into an array ([c, b, a]) so I can use other high-order functions like map.
What is a method that produces an array from a linked list typically called?
Is there a way to use other high-order functions to implement this and not use a loop?
The only implementation I could think of falls back to using a loop:
func chain<T>(_ initial: T, _ next: (T) -> T?) -> [T] {
var result = [initial]
while let n = next(result.last!) {
result.append(n)
}
return result
}
chain(c) { $0.parent } // == [c, b, a]
I'm wondering if there is a built-in way to use functions like map/reduce/etc. to get the same results.
You can use sequence(first:next:) to make a Sequence and then Array() to turn that sequence into an array:
let result = Array(sequence(first: c, next: { $0.parent }))
or equivalently:
let result = Array(sequence(first: c, next: \.parent))
You could use it to implement chain:
func chain<T>(_ initial: T, _ next: #escaping (T) -> T?) -> [T] {
Array(sequence(first: initial, next: next))
}
But I'd just use it directly.
Note: If you just want to call map, you don't need to turn the sequence into an Array. You can just apply .map to the sequence.
For example, here is a useless map that represents each node in the linked list with a 1:
let result = sequence(first: c, next: \.parent).map { _ in 1 }
You could make Node be a "denaturated" sequence, this will automatically bring all high-order functions: map, filter, reduce, flatMap, etc.
class Node {
var parent: Node?
var value: String
init(parent: Node? = nil, value: String = "") {
self.parent = parent
self.value = value
}
}
extension Node: Sequence {
struct NodeIterator: IteratorProtocol {
var node: Node?
mutating func next() -> Node? {
let result = node
node = node?.parent
return result
}
}
func makeIterator() -> NodeIterator {
NodeIterator(node: self)
}
}
// Create the chain: a <- b <- c
let a = Node(value: "a")
let b = Node(parent: a, value: "b")
let c = Node(parent: b, value: "c")
// each node behaves like its own sequence
print(c.map { $0.value }) // ["c", "b", "a"]
print(b.map { $0.value }) // ["b", "a"]

Swift - check if function parameter was passed

Let's say I have the following function:
func update(a a: String? = nil, b: String? = nil) {
if a.notDefaultValue /* or something like that */ {
// ...
}
if b.notDefaultValue {
// ...
}
}
And I can call it in those ways (expecting to do as in the comments):
update() // Should do nothing
update(a: nil) // Should only go into first 'if' statement
update(b: nil) // Should only go into second 'if' statement
update(a: nil, b: nil) // Should go into both 'if' statements
update(a: "A") // Should only go into first 'if' statement
update(b: "B") // Should only go into second 'if' statement
update(a: "A", b: "B") // Should go into both 'if' statements
How can I achieve this?
EDIT:
The only way I could think of doing this is with method overload, but that is unfeasible when you have many parameters (don't even have to be that many, 4 will already need 17 methods).
I'm not sure why you would want to do this, but you can do it in this way:
let argumentPlaceholder = "__some_string_value__"
func update(a a: String? = argumentPlaceholder, b: String? = argumentPlaceholder) {
if a == argumentPlaceholder {
// Default argument was passed, treat it as nil.
}
if b == argumentPlaceholder {
// Default argument was passed, treat it as nil.
}
}
func update(a a: String?, b: String?) {
if let a = a, b = b {
print("a = \(a), b = \(b). a and b are not nil")
} else if let a = a {
print("a = \(a). b is nil")
} else if let b = b {
print("b = \(b). a is nil")
} else {
print("a and b are nil")
}
}
func update() {
print("no parameters")
}
update() // "no parameters\n"
update(a: nil, b: nil) // "a and b are nil\n"
update(a: nil, b: "Y") // "b = Y. a is nil\n"
update(a: "X", b: nil) // "a = X. b is nil\n"
update(a: "X", b: "Y") // "a = X, b = Y. a and b are not nil\n"
Also try to write something like this:
func hello() {
print("hello")
}
func hello(name: String) {
print("hello \(name)")
}
func hello(name: String, last: String) {
print("hello \(name) \(last)")
}
hello()
hello("arsen")
hello("arsen", last: "gasparyan")
It's more functional way

Function that return either of two generics

I'm trying to implement either function, which accepts two generic container and return either of them:
func either<A,B>(a: Container<A>, b: Container<B>) -> ?either Container<A> or Container<B>? {
// choose any of container
return chosen
}
Looks like I need a protocol, that Container must conforms to, so that my either's return type should be of this protocol.
Is this right solution?
protocol ContainerProtocol
struct Container<T>: ContainerProtocol
func either<A: ContainerProtocol, B:ContainerProtocol, C:ContainerProtocol>(a: A, b: B) -> C {
// choose any of container
return chosen
}
UPDATE
ok so I've implemented the EitherContainer enum and the final code is following:
struct Container<T>: Unique {
typealias UnderlyingObject = T
var object: UnderlyingObject
var uniqueId: String
}
enum EitherContainer<A,B> {
case a(container: Container<A>)
case b(container: Container<B>)
}
func wrappedInput<A,B>(wra: Container<A>, wrb: Container<B>, paramClosure: (Container<A>, Container<B>) -> EitherContainer<A,B>) -> EitherContainer<A,B> {
//do some work here
return paramClosure(wra, wrb)
}
func rawInput<A, B>(a: A, b: B) -> Any {
let wrappedA = Container(object: a, uniqueId: "a")
let wrappedB = Container(object: b, uniqueId: "b")
let wrappedRes = wrappedInput(wrappedA, wrb: wrappedB) {
(a1: Container, a2: Container) -> EitherContainer<A,B> in
// do some work here
return EitherContainer.a(container: a1)
}
var rawRes: Any
switch wrappedRes {
case .a(let container):
rawRes = container.object
case .b(let container):
rawRes = container.object
}
return rawRes
}
what bothers me now, is Any type, which shuts the compiler up, but for me looks like a weak crutch. Again same problem rawInput<A, B>(a: A, b: B) -> Any . rawInput should return either A or B, but I'm forced to use Any instead. Should I add another enum for raw options? Any thoughts?
The traditional Either type looks like this:
enum Either<A, B>
{
case Left(A)
case Right(B)
}
and is more useful, as it's not limited to your Container type.
(Either is the "canonical" sum type.)
It would be used like this:
func wrappedInput<A, B> (
a : Container<A>,
b: Container<B>,
paramClosure: (Container<A>, Container<B>) -> Either<Container<A>,Container<B>>
) -> Either<Container<A>, Container<B>>
{
return Either.Left(a) // Dummy
}
func rawInput<A, B>(a: A, b: B) -> Either<A,B> {
let wrappedA = Container(object: a, uniqueId: "a")
let wrappedB = Container(object: b, uniqueId: "b")
let wrappedRes = wrappedInput(wrappedA, b: wrappedB) {
(a1: Container, a2: Container) -> Either<Container<A>, Container<B>> in
// do some work here
return Either.Left(a1)
}
switch wrappedRes {
case .Left(let container):
return Either.Left(container.object)
case .Right(let container):
return Either.Right(container.object)
}
}