An alternative to "while" for making repeated requests to a server - scala

I have a function which should return a result either from the db or a server. But the server might fail and return nothing and in that case I need to repeat the server request until it returns the result:
def getToken() =
getTokenFromDb orElse getTokenFromServer() map { t =>
saveTokenToDb(t)
t
}
What is a sensible solution for repetitive requests to getTokenFromServer() until I get a good response from it except using while loop? Of maybe using while is a good solution?

This may sound insane, but you could create a stream of infinite server-requests, and then use "takeWhile + isDefined" :) I think that may actually be quite easy to implement. If I get to my code-machine, I'll whip something up :)

Well, as far as you have no specific requirements on how many attempts you want it to try the server, just use recursion. This is in fact almost the same as while loop :) but in more functional style.
So make the getTokenFromServer() recursive.
But do not forget about the tail-recursion, i.e. the recursive call to the getTokenFromServer() from within itself must be a last code statement in it's code. That way you will not get any troubles with stack overflowing.

Related

Why is ".map" slower then "while/for loop" in Dart(Flutter)

I saw this article:
https://itnext.io/comparing-darts-loops-which-is-the-fastest-731a03ad42a2
It says that ".map" is slow with benchmark result
But I don't understand why slower than while/for loop
How does it work in low level?
I think it's because .map is called an unnamed method like this (_){ }
Can you explain that in detail?
Its because mapping an array will create a copy of each value than modify the original array.
Since a while/for loop does not copy the values but rather just accesses them using their index, it is a lot faster.
Can you explain that in detail?
It's like saying "I don't understand why hitchhiking on the back of a construction truck is so much slower than taking the high speed train to my destination".
The only detail that is important is that map is not a loop. map() internally probably uses a loop of some kind.
This person is misusing a method call that is meant for something else, just because a side-effect of that call when combining it with a call materializing the iterable, like toList(), is that it loops through the iterable given. It doesn't even have the side effect on it's own.
Stop reading "tutorials" or "tips" of people misusing language features. map() is not a loop. If you need a loop, use a loop. The same goes for the ternary operator. It's not an if, if you need an if, use it.
Use language features for what they are meant, stop misusing language features because their side-effect does what you want and then wondering why they don't work as well as the feature actually meant for it.
Sorry if this seems a bit ranty, but I have seen countless examples by now. I don't know where it comes from. My personal guess is "internet tutorials". Because everybody can write one. Please don't read them. Read a good book. It was written by professionals, proofread, edited, and checked. Internet tutorials are free, written by random people and about worth as much as they cost.

What is the benefit of effect system (e.g. ZIO)?

I'm having hard time understanding what value effect systems, like ZIO or Cats Effect.
It does not make code readable, e.g.:
val wrappedB = for {
a <- getA() // : ZIO[R, E, A]
b <- getB(a) // : ZIO[R, E, B]
} yield b
is no more readable to me than:
val a = getA() // : A
val b = getB(a) // : B
I could even argue, that the latter is more straight forward, because calling a function executes it, instead of just creating an effect or execution pipeline.
Delayed execution does not sound convincing, because all examples I've encountered so far are just executing the pipeline right away anyways. Being able to execute effects in parallel or multiple time can be achieved in simpler ways IMHO, e.g. C# has Parallel.ForEach
Composability. Functions can be composed without using effects, e.g. by plain composition.
Pure functional methods. In the end the pure instructions will be executed, so it seems like it's just pretending DB access is pure. It does not help to reason, because while construction of the instructions is pure, executing them is not.
I may be missing something or just downplaying the benefits above or maybe benefits are bigger in certain situations (e.g. complex domain).
What are the biggest selling points to use effect systems?
Because it makes it easy to deal with side effects. From your example:
a <- getA() // ZIO[R, E, A] (doesn't have to be ZIO btw)
val a = getA(): A
The first getA accounts in the effect and the possibility of returning an error, a side effect. This would be like getting an A from some db where the said A may not exist or that you lack permission to access it. The second getA would be like a simple def getA = "A".
How do we put these methods together ? What if one throws an error ? Should we still proceed to the next method or just quit it ? What if one blocks your thread ?
Hopefully that addresses your second point about composability. To quickly address the rest:
Delayed execution. There are probably two reasons for this. The first is you actually don't want to accidentally start an execution. Or just because you write it it starts right away. This breaks what the cool guys refer to as referential transparency. The second is concurrent execution requires a thread pool or execution context. Normally we want to have a centralized place where we can fine tune it for the whole app. And when building a library we can't provide it ourselves. It's the users who provide it. In fact we can also defer the effect. All you do is define how the effect should behave and the users can use ZIO, Monix, etc, it's totally up to them.
Purity. Technically speaking wrapping a process in a pure effect doesn't necessarily mean the underlying process actually uses it. Only the implementation knows if it's really used or not. What we can do is lift it to make it compatible with the composition.
what makes programming with ZIO or Cats great is when it comes to concurrent programming. They are also other reasons but this one is IMHO where I got the "Ah Ah! Now I got it".
Try to write a program that monitor the content of several folders and for each files added to the folders parse their content but not more than 4 files at the same time. (Like the example in the video "What Java developpers could learn from ZIO" By Adam Fraser on youtube https://www.youtube.com/watch?v=wxpkMojvz24 .
I mean this in ZIO is really easy to write :)
The all idea behind the fact that you combine data structure (A ZIO is a data structure) in order to make bigger data structure is so easy to understand that I would not want to code without it for complex problems :)
The two examples are not comparable since an error in the first statement will mark as faulty the value equal to the objectified sequence in the first form while it will halt the whole program in the second. The second form shall then be a function definition to properly encapsulate the two statements, followed by an affectation of the result of its call.
But more than that, in order to completely mimic the first form, some additional code has to be written, to catch exceptions and build a true faulty result, while all these things are made for free by ZIO...
I think that the ability to cleanly propagate the error state between successive statements is the real value of the ZIO approach. Any composite ZIO program fragment is then fully composable itself.
That's the main benefit of any workflow based approach, anyway.
It is this modularity which gives to effect handling its real value.
Since an effect is an action which structurally may produce errors, handling effects like this is an excellent way to handle errors in a composable way. In fact, handling effects consists in handling errors !

Should a function returning a boolean be used in an if statement?

If I have a function call that returns true or false as the condition of an if statement, do I have to worry about Swift forking my code for efficiency?
For example,
if (resourceIsAvailable()) { //execute code }
If checking for the resource is computationally expensive, will Xcode wait or attempt to continue on with the code?
Is this worth using a completion handler?
What if the resource check must make a database call?
Good question.
First off... can a function be used? Absolutely.
Second... should it be used?
A lot of that depends on the implementation of the function. If the function is known (to the person who wrote it) to take a long time to complete then I would expect that person to deal with that accordingly.
Thankfully with a lot of iOS things like that are taken out of the hands of the developer (mostly). CoreData and Network requests normally come with a completion handler. So any function that uses them would also need to be async and have a completion handler.
There is no fixed rule for this. My best advice would be...
If you can see the implementation of the function then try to work out what it’s doing.
If you can’t then give it a go. You could even use the time profiler in Xcode profiler to determine how long it is taking to complete.
The worst that could happen is you find it is slow and then change it for something else.

Scala future not assigned, what’s this doing?

I’m new to scala and I’m trying to make sense of what this code is doing in a codebase I want to make updates to.
Removing some of the specifics, the chunk I don’t understand is this:
I’ve seen some scala code that does things like:
val someA = something.createSomeA(....)
Future {
someA.doSomething1(....)
someA.doSomething2(.....)
}
// then log some things unrelated to the future
someA
// end of func
I don’t really understand what the future is doing in this case as it’s not assigned to anything. Could someone explain what the Future is doing here?
I know the details depend on what the doSomethings are actually doing, but could someone explain generally what this would be for? I’m only familiar with the use of Futures when they’re assigned to a variable and then checked for completion in some way at a later point.
Help would be appreciated!! (Sorry for poor formatting, I’m doing this from my phone)
Three words for you: "fire and forget".
If you understand the case, when the future is assigned to a variable, and then checked/transformed later, then you already know what's happening here: the insides of the Future are being executed asynchronously.
The only difference is that in this case it is never accessed again. Why? Probably, because nobody cares. Some operations return a result when they complete, that can be used later, others do not.
For example, if I wanted to print out a log message asynchronously, I'd write something like Future { logger.info(mymessage) } without assigning it to anything. Why? Well, I don't really care when (or even if) it completes. There is no return value I could use, and, if it fails ... well, I don't have any meaningful way to handle that, other than ignoring the error.
For an operation like this, I don't need to wait for it to complete, since it doesn't return anything useful back to me anyway. So, I can just start it, and forget. No need to assign it to anything.

ReactiveX Retry with Multiple Consumers

Quick question, because I feel like I must be missing something.
I'm using rxjs here because it's what I've got in-front of me, this is a general reactiveX question, I believe.
Let's say I have a set of Observables like so:
network_request = some_thing // An observable that produces the result of a network call
event_stream = network_request.flatMapLatest(function(v) {
return connectToThing(v) // This is another observable that needs v
}) // This uses the result of the network call to form a long-term event-based connection
So, this works ok.
Problem, though.
Sometimes the connection thing fails.
So, if I do event_stream.retry() it works great. When it fails, it redoes the network call and gets a new v to use to make a new connection.
Problem
What happens if I want two things chained off of my network_request?
Maybe I want the UI to do something every time the network call completes, like show something about v in the UI?
I can do:
shared = network_request.share() // Other implementations call this refCount
event_stream = shared.flatMapLatest(...) // same as above
ui_stream = shared.flatMapLatest(...) // Other transformation on network response
If I didn't do share then it would have made two requests, which isn't what I want, but with share, when event_stream later has an error, it doesn't retry the network request because the refcount is still at 1 (due to ui_stream), so it immediately returns completed.
What I want
This is obviously a small example I've made up to explain my confusion.
What I want is that every time the result of event_stream (that long term connection) has an error all of the following happens:
the network request is made again
the new response of that request is used to build a new connection and event_stream goes on with new events like nothing happened
that same response is also emitted in ui_stream to lead to further processing
This doesn't feel like a complicated thing, so I must just be misunderstanding something fundamental when it comes to splitting / fanning out RX things.
Workarounds I think I could do but would like to avoid
I'm looking to export these observables, so I can't just build them again and then say "Hey, here's the new thing". I want event_stream and all the downstream processing to not know there's been a disconnection.
Same for ui_stream. It just got a new value.
I could probably work something out using a Subject as a generation counter that I ping every time I want everything to restart, and put the network_request into a flatMap based on that, so that I can break the share...
But that feels like a really hacky solution, so I feel there has to be a better way than that.
What have I fundamentally misunderstood?
As I've been thinking about this more I've come to the same realization as ionoy, which is that retry just disconnects and reconnects, and upstream doesn't know it was due to an error.
When I thought about what I wanted, I realized I really wanted something like a chain, and also a spectator, so I've got this for now:
network_request = some_thing
network_shadow = new Rx.Subject()
event_stream = network_request.do(network_shadow).flatMapLatest(...)
ui_stream = network_shadow.whatever
This has the property where an retry in event_stream or downstream will cause the whole thing to restart, whereas ui_stream is its own thing.
Any errors over there don't do anything, since network_shadow isn't actually a subscriber to event_stream, but it does peel the values off so long as the main event chain is running.
I feel like this isn't ideal, but it is better than what I was concerned I would have to do, which is have a restartEverything.onNext() in an doOnError, which would have been gross.
I'm going to work with this for now, and we'll see where it bites me...
You need to make your cold observable hot by using Publish. Read http://www.introtorx.com/Content/v1.0.10621.0/14_HotAndColdObservables.html#HotAndCold for a great explanation.