What is going on here? I didn't understand how we got that output.
for (var i = 1; i <=4; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
},j*1000);
})(i)
}
// output: undefined, log 1, 2, 3, 4 with a second interval.
for (var i = 1; i <=4; i++) {
...
}
makes a loop that iterates four times. The value of i is 1 in the first iteration, then 2, then 3, then 4.
(function(j) {
...
})(i)
creates an anonymous function with one parameter, j, and immediately invokes it by passing the value i. This is called IIFE, and you can read more about it at What is the (function() { } )() construct in JavaScript?. As a result, j is the value of i, but it will not change as i changes.
setTimeout(function() {
...
},j*1000);
sets a timeout for a certain number of milliseconds, and execute the function when the timeout expires. Note that setTimeout exits immediately, it only schedules the function to be executed later. In JavaScript world, this is called asynchronous execution.
console.log(j);
prints 1, 2, 3 or 4 on the console. Remember that due to setTimeout, this will happen 1, 2, 3 or 4 seconds later.
As a result, for executes almost instantaneously, as the only job it does is to schedule four functions for the future. The value of this execution is undefined, which is what will be printed to the console if you execute the snippet there. 1000ms after the snippet exits, the first scheduled function is triggered, and prints the value of its local variable j (which is 1). 2000ms after the loop (1 second after 1 is printed), the next scheduled function is executed, printing 2. This happens two more times.
Related
I tried this example code to see if it actually work
--This example is from Programming in Lua Second Edition
function values (t)
local i = 0
return function ()
i = i + 1
return t[i]
end
end
t = {10, 20, 30}
iter = values(t)
while true do
local element = iter()
-- calls the iterator
if element == nil then
break
end
print(element) --> 10, 20, 30
end
I decided to change it a bit, I thought the code will get the same result but I think I was wrong
--This example is from Programming in Lua Second Edition
function values (t)
local i = 0
return function ()
i = i + 1
return t[i]
end
end
t = {10, 20, 30}
while true do
local element = values(t)()
-- calls the iterator
if element == nil then
break
end
print(element) --> This will print 10 forever if I don't stop the IDE
end
Why is iter important that much?
When you do local element = values(t)(), you are actually creating an iterator function every single time your loop is running. Take a note of your values function, see that it has a local variable called i. Every single time you are running this function, a local variable is initialized and sent to your inner function which handles the iteration. The original example is perfectly fine, however if you want to practice local and global variables, you may change the local i to a global variable i, or a different name and move it outside your function so it will not get called every time you run your iterate function (You may keep it local still, so the scope will be limited to current file). However, that is totally not recommended, since your value may be re-used some time later by another function or file, also it will limit you to one full iteration per run (Unless you set the value back to zero before retrying to iterate.)
local i = 0 -- Notice that the variable is taken out of the function.
-- With your example, the problem was that this variable was set to 0 for every
-- time you called the function.
function values (t)
return function ()
i = i + 1
return t[i]
end
end
t = {10, 20, 30}
while true do
local element = values(t)()
-- calls the iterator
if element == nil then
break
end
print(element) --> This will print 10 forever if I don't stop the IDE
end
Also keep performance in your mind, as every time you are iterating with your example, a function is being created, called, and then destroyed by the garbage collection. This is why the original example created an iterator function only once, and then called it multiple times, whereas your example creates an iterator function every time it is looping.
If all you need to do is to iterate through elements of a table, then lua already has generic for loop (pairs), check here and here. Example in your case (which also shortens your code by a lot):
local t = {10, 20, 30}
-- We don't need key in this case, but if you do, replace _ with k or
-- any other variable name you want.
for _, element in pairs(t) do
print(element)
end
getRandom () {
echo $RANDOM
}
getRandomFromGetRandom () {
echo $(getRandom)
}
Calling getRandom does the expected every time, it returns some random number on each call.
What I'd expect is the same from getRandomFromGetRandom, that a random number being called every time I call getRandomFromGetRandom, but that's not the case. Every time that function is called it returns a constant which changes only when I open another instance of the terminal.
man zshparam says:
The values of RANDOM form an intentionally-repeatable pseudo-random sequence; subshells that reference RANDOM will result in identical pseudo-random values unless the value of RANDOM is referenced or seeded in the parent shell in between subshell invocations.
Since command substitution is performed in a subshell, this explains the repetitive values getRandomFromGetRandom prints. To fix it, reference RANDOM before echoing $(getRandom), like
getRandomFromGetRandom () {
: $RANDOM
echo $(getRandom)
}
Or seed it (zsh-only; won't work on yash)
getRandomFromGetRandom () {
RANDOM= echo $(getRandom)
}
(Almost) All Random implementations are based on saved state. Calculating the value of the next random number depends only on the state, and will modify the state so that the next call will yield different number. When a process is forked, the state of the parent is copied into the state of the children.
In the posted code, the getRandom is calculated in a sub-shell (because of $(getRandom)). As a result, the code repeated uses the inherit state from the parent, which is never updated. The next call therefore will use the same (parent) state, and will result in the same number.
The first two iterations will look like:
Iteration 1:
Parent initialize parent_state to S0
Parent fork, child_state set to S0 (copied from parent_state)
Child calculate first random using S0, result is R0, modified child_state = S1
Child exit, returns R1 to parent (via stdout, print with echo)
Iteration 2:
Parent fork agin, child set set to S0 (copied from parent_state)
Child calculate second random using S0, result is R0, modified child_state = S1
Child exit, returns R1 to parent (via stdout, print with echo)
The following shows how to get similar logic to work
getRandom () {
my_random=$RANDOM
}
getRandomFromGetRandom () {
getRandom
echo "$my_random"
}
getRandomFromGetRandom
getRandomFromGetRandom
I'm a bit confused about the rxjs operator delay.
When I test it with a fake observable created with from, then I only see an initial delay:
const { from } = Rx;
const { delay, tap } = RxOperators;
from([1, 2, 3, 4]).pipe(
tap(console.log),
delay(1000));
(You can copy & paste this code snippet into rxviz.)
I placed a tap in there to make sure from actually emits the array items as separate values instead of a single array value.
An initial delay is not what I expected, but at least that's what the docs say:
[...] this operator time shifts the source Observable by that amount of time expressed in milliseconds. The relative time intervals between the values are preserved.
However, when I test it with an observable created from an event, then I see a delay before each emitted value:
const { fromEvent } = Rx;
const { delay } = RxOperators;
fromEvent(document, 'click')
.pipe(delay(1000))
What's going on here? Why is delay behaving differently in both cases?
All delay does is what it says: whenever it receives a value, it holds on to that value for the delay period, then emits it. It does the same thing for each value it receives. delay does not change the relative timings between items in the stream.
So, when you do from([1,2,3,4]).pipe(delay(1000)), what happens is:
Time 0: from emits 1
Time 0: delay sees 1 and starts timer1
Time 0: from emits 2
Time 0: delay sees 2 and starts timer2
...
Time 1000: timer1 completes and delay emits 1
Time 1000: timer2 completes and delay emits 2
...
So because all 4 values were emitted in rapid succession, you really only see an initial delay and then all 4 values get emitted downstream. In reality, each value was delayed by 1 second from when it was originally emitted.
If you want to "spread apart" the items so that they are at least 1 second apart, then you could do something like:
const source = from([1, 2, 3, 4])
const spread = source.pipe(concatMap(value => of(value).pipe(delay(1000))));
spread.subscribe(value => console.log(value));
This converts each individual value into an observable that emits the value after a delay, then concatenates these observables. This means the timer for each item will not start ticking until the previous item's timer finishes.
You tap the stream and get the values that are emitted then you pipe them into delay which emits them one second later. Each function in the pipe returns a new observable which emits a value to the next function in the pipe. Tap returns the same observable that has not been delayed yet and delay returns an observable that emits one second later.
const { from } = rxjs;
const { delay, tap } = rxjs.operators;
from([1, 2, 3, 4]).pipe(
tap(val => { console.log(`Tap: ${val}`); }),
delay(1000)).subscribe(val => { console.log(`Sub: ${val}`); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js"></script>
If you put the tap after the delay then you see them after the delay.
const { from } = rxjs;
const { delay, tap } = rxjs.operators;
from([1, 2, 3, 4]).pipe(
delay(1000),
tap(val => { console.log(`Tap: ${val}`); })).subscribe(val => { console.log(`Sub: ${val}`); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js"></script>
In first code snippet you are emitting an array element by element. First delay, then array elements are handled.
'from' and 'pipe' make 'delay' perform once. Pipe sequences processing, first delay, then tap, tap, tap, tap.
In second code snippet you are emitting objects (they arrive), so delay happens once for each object.
'fromEvent' and 'pipe' make 'delay' per event. Pipe sequences processing of delay before each event.
I'm trying to create a hot range observable. This means that when I have an observer observering the observable after a certain timeout, it should not receive the values that have already been published. I have created the following program:
import Rx from "rxjs/Rx";
var x = Rx.Observable.range(1,10).share()
x.subscribe(x => {
print('1: ' + x);
});
setTimeout(() => {
x.subscribe(x => {
print('2: ' + x);
});
}, 1000);
function print(x) {
const element = document.createElement('div');
element.innerText = x;
document.body.appendChild(element)
}
I expect this program to print 1 to 10, and then the second observable to print nothing, since the values 1 to 10 are produced within the first second. The expected output is shown below.
1: 1
1: 2
..
1:10
However, I see that it also prints all the values. Eventhough I have put the share() operator behind it. The output is shown below.
1: 1
..
1: 10
2: 1
..
2: 10
Can somebody explain this to me?
share returns an observable that's reference counted for subscriptions. When the reference count goes from zero to one, the shared observable subscribes to the source - in your case, to the range observable. And when the reference count drops back to zero, it unsubscribes from the source.
The key point in your snippet is that range emits it's values synchronously and then completes. And the completion effects an unsubscription from the shared observable and that sees the reference count drop back to zero - which sees the shared observable unsubscribe from its source.
If you replace share with publish you should see the behaviour you expected:
var x = Rx.Observable.range(1,10).publish();
x.subscribe(x => print('1: ' + x));
x.connect();
publish returns a ConnectableObservable which is not reference counted and provides a connect method that can be called to explicitly connect - i.e. subscribe - to the source.
What is the best way to model a poller with a timeout, where a certain condition causes an early-exit as 'reactive streams'?
e.g.
If I had an observable which produced a decreasing sequence of positive integers every second
9,8,7,6,5,4,3,2,1,0
What is the best way to write a consumer which takes the latest single event after 5 seconds OR the '0' event if it produced earlier than the timeout.
This is my code as it stands at the moment: (Example in Java)
int intialValue = 10;
AtomicInteger counter = new AtomicInteger(intialValue);
Integer val = Observable.interval(1, TimeUnit.SECONDS)
.map(tick -> counter.decrementAndGet())
.takeUntil(it -> it == 0)
.takeUntil(Observable.timer(5, TimeUnit.SECONDS))
.lastElement()
.blockingGet();
System.out.println(val);
if initialValue = 10, I expect 6 to print. if initialValue = 2, i expect 0 to print before the 5 second timeout expires.
I'm interested if there is a better way to do this.
I don't think there is really a much better way than what you did. You have to have the following:
An interval to emit on (interval)
An aggregator to decrement and store the last value (scan)
A termination condition on the value (takeWhile)
A termination condition on time (takeUntil(timer(...)))
Get the last value on completion (last)
Each one is represented by an operator. You can't do much to get around that. I used a few different operators (scan for aggregation and takeWhile for termination on value) but it is the same number of operators.
const { interval, timer } = rxjs;
const { scan, takeWhile, takeUntil, last, tap } = rxjs.operators;
function poll(start) {
console.log('start', start);
interval(1000).pipe(
scan((x) => x - 1, start),
takeWhile((x) => x >= 0),
takeUntil(timer(5000)),
tap((x) => { console.log('tap', x); }),
last()
).subscribe(
(x) => { console.log('next', x); },
(e) => { console.log('error', e); },
() => { console.log('complete'); }
);
}
poll(10);
setTimeout(() => { poll(2); }, 6000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.1.0/rxjs.umd.min.js"></script>
I'm not clear on how you expect it to function on the boundaries. In your example you always decrement before emiting so if your initial value is 10 then you emit 9, 8, 7, 6 (4 values). If you wanted to start with 10 then . you could do scan(..., start + 1) but that would end you at 7 because the timer in the takeUntil(...) aligns with the source interval so that 6 would be excluded. If you want to emit 5 values then you could do takeUntil(timer(5001)). Also, if you don't want to wait a second to emit the first value then you could put startWith(start) right after the scan(...). Or you could do timer(0, 1000) with scan(..., start + 1) instead of the source interval.
Also note that the termination on value (takeWhile) will not terminate till the invalid value is produced (-1). So it will continue for a second after receiving the termination value (0). It seems that most of the termination operators work that way where if they terminate on some value then they wont let the others through.
You could do a take(5) instead of takeUntil(timer(5000)) because you know it fires on a matching interval if that works for your scenario. That would also get around the issue of excluding the last value because of the timers lining up.