At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.
Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.
Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.
new-if uses applicative order evaluation because it's a function defined by Alyssa, and by default, scheme functions are evaluated using applicative order evaluation. In scheme, 'if' is a special form, which uses normal order evaluation, since that's what 'if' is supposed to do. For example consider the code snippet (if (= x 0) foo (/ foo x)) if applicative order evaluation was used, we'd get a division by zero error.
You have to be careful about distinction between special forms and procedures, and how they may work.
All procedures (in applicative order evaluation) when called (meaning when you give them arguments), they evaluate their arguments first and then do the rest of the computation.
Special forms are special forms. They have distinct rules for how they work.
define, if, cond, let, lambda etc all of them are special forms. They are NOT procedures/functions.
Now coming to normal versus applicative order evaluation, in normal order evaluation none of the arguments get evaluated unless you encounter a primitive procedure.
Although 'if' is not a procedure (but a special form), but to demonstrate the difference between if and new-if let's assume for now that 'if' is a procedure (in a normal order evaluation environment).
Since our own interpreter works with applicative order evaluation. When we define a procedure new-if, it will also necessarily work the same way.
Normal order Applicative order
suppose a, b and c are bound to some procedures in our environment,
then evaluating the following expressions would work like below:
(if (a) (b) (c)) (new-if (a) (b) (c))
since 'if' is not a primitive, on the other hand, new-if will first
(a), (b) and (c) would not get evaluate its arguments (all of them).
evaluated at this stage. Because that is how applicative order
(although there is one annoying evaluation is. The expressions (a), (b)
detail that we want the predicate (a) and (c) get evaluated first. And then by
to get evaluated so that we can checking if the value of (a) is false or not
decide which way to go) it would return the value of either (b) or
after we have checked if (a) is false (c). But do we want it to evaluate the
or not, we force the evaluation of (b) consequent and alternate both? No. We
or (c) - note that both don't get evaluated, only wanted of one them to get evaluated.
only one them gets evaluated.
Dry run this:
(define x 0)
(define y 1)
(if (= x 0) y (/ y x))
If 'if' is a procedure of normal order evaluation, it's arguments wouldn't get evaluated.
since the predicate is true, the evaluation of the consequent will be forced only.
Since y will get evaluated to 1, that will be our answer
do the same for applicative order new-if
(new-if (= x 0) y (/ y x))
Since it's applicative order, it will first evaluate all the arguments.
(= x 0) will be evaluated to true
y will get evaluated to 1
and (/ y x)'s evaluation will give an error as division by zero is not possible.
Now if you note, the for 'if' the expression (/ y x) will only get evaluated if and only if the predicate is false (meaning when x will not be zero). Since x will not be zero, the expression (/ y x) - in normal order evaluation - would never give an error.
Hope that helps!