[] in pinescript is called History Referencing Operator. It refers to previous values of the variable.
When you say f[1], it returns whatever f's value is one bar ago.
It is good that you are using nz() with [], because for the very first bar, no variable has a previous value. So, when you try to access a historical value of a variable for the first time, the result will be NaN and nz() will convert NaN to 0.
Another thing to know is that your code will get executed for each bar.
Let's look at your code now.
f = 0.0 d = 0.0
You declare f and d at the beginning and assign 0 to them. We can neglect this step since you are reassigning another value to them.
First Bar
d := nz(f[1])
Assign f's value on the previous bar to d. f has no previous value for the first bar, so nz() will return 0. So, d = 0.
f := d+1
f = 0 + 1 -> f = 1
Second Bar
d := nz(f[1])
Assign f's value on the previous bar to d. f's value on the first bar is 1. So, d = 1.
f := d+1
f = 1 + 1 -> f = 2
Third Bar
d := nz(f[1])
Assign f's value on the previous bar to d. f's value on the second bar is 2. So, d = 2.
f := d+1
f = 2 + 1 -> f = 3
Note: Try running the following code and you will see that it behaves exactly the same.
//@version=4 study('test') f = 550.0 d = 0.0 d := nz(f[1]) f := d+1 plot(d) plot(f)
The reason is, it doesn't matter what value f initially has. d := nz(f[1]) will assign f's value on the previous bar to d and for the very first bar, f has no previous value. Hence, nz() will return 0.
Then what happens for the very first bar is:
d := nz(f[1]) // d = 0 f := d+1 // f = 1
And so on..