Warning: foreach() argument must be of type array|object, bool given in /var/www/html/web/app/themes/studypress-core-theme/template-parts/header/mobile-offcanvas.php on line 20

Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures: (define \((\mathrm{p})(\mathrm{p}))\) (define (test \(\mathrm{x} \mathrm{y}\) ) (if \((=\mathrm{x} 0)\) 0 \(\mathrm{y})\) ) Then he evaluates the expression (test \(0(\mathrm{p}))\) What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normalorder evaluation? Explain your answer. (Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)

Short Answer

Expert verified
Applicative-order causes infinite loop; normal-order returns 0.

Step by step solution

01

Understanding Applicative-Order Evaluation

In applicative-order evaluation, an interpreter evaluates the arguments of a function before applying the function itself. This means that in the expression \(\text{(test 0 (p))}\), it will first try to evaluate \(\text{(p)}\) before applying it to the \(\text{test}\) function. Since \(\text{p}\) is defined as \(\text{((\text{p})(\text{p}))}\), this leads to an infinite loop or non-terminating computation as \(\text{p}\) calls itself indefinitely.
02

Understanding Normal-Order Evaluation

In normal-order evaluation, the interpreter delays the evaluation of arguments until their values are actually needed. In the expression \(\text{(test 0 (p))}\), the interpreter will first evaluate the predicate \(\text{(= x 0)}\), which is true since \(x\) is 0. Because the if statement evaluates the consequent without needing the value of \((\text{p})\), the expression correctly returns \(0\) without evaluating \(\text{(p)}\). Thus, no error or infinite loop occurs.

Unlock Step-by-Step Solutions & Ace Your Exams!

  • Full Textbook Solutions

    Get detailed explanations and key concepts

  • Unlimited Al creation

    Al flashcards, explanations, exams and more...

  • Ads-free access

    To over 500 millions flashcards

  • Money-back guarantee

    We refund you if you fail your exam.

Over 30 million students worldwide already upgrade their learning with Vaia!

Key Concepts

These are the key concepts you need to understand to accurately answer the question.

Applicative-Order Evaluation
In applicative-order evaluation, the order of operations is important.
This type of evaluation means that an interpreter evaluates all function arguments before it actually applies the function itself.
Consider the analogy of cooking: it's like gathering all your ingredients before you start cooking.Let's look at the expression \[\text{(test 0 (p))}\] given in the original exercise: - Here, the interpreter would try to evaluate both arguments of `(test)`.
It looks at `0` and tries to evaluate `(p)`.- But, `(p)` is a recursive procedure: it calls itself without an end, forming the expression \[\text{((p)(p))}\]- This results in an infinite loop because it continues to call `(p)` forever, without reaching a termination point. Thus, in applicative-order evaluation, the function fails to complete successfully, leading to a non-terminating computation or error.
Normal-Order Evaluation
Normal-order evaluation takes a lazy approach.
It delays the computation of the function's arguments until their values are necessary.
This can be seen as only gathering ingredients for cooking when you are at the step where they are needed.In the expression \[\text{(test 0 (p))}\] the interpreter behaves differently under normal-order evaluation:- Initially, it evaluates only the predicate of the `if` form: `(= x 0)`.
Since `x` is `0`, this evaluates to `true`.- Unlike applicative-order, it does not evaluate `(p)` upfront.
Instead, it moves to the `consequent` branch since the condition is true.
It immediately returns `0` from `test`.- The argument `(p)` remains unevaluated, and thus avoids the infinite recursion problem entirely.This behavior allows completion without errors or infinite loops, showcasing how normal-order evaluation can bypass unnecessary computations.
Interpreter Behavior
The behavior of an interpreter in implementing these evaluation orders can greatly impact program execution.
Understanding how an interpreter evaluates a code is crucial for debugging and optimizing code execution. ### Key Behaviors of Each Evaluation - **Applicative-Order Behavior:** * Focuses on evaluating arguments before executing functions. * Often used because predictable order despite risks of non-termination in recursive definitions. - **Normal-Order Behavior:** * Delays argument evaluation until absolutely necessary. * Avoids non-termination that frustrates applicative-order but can be less efficient for large expressions. Each has strengths and weaknesses: - Applicative-order is typically faster since it evaluates arguments first.
However, it can be costly if not optimized due to unnecessary evaluations. - Normal-order can handle more general recursive procedures without needing explicit termination but may have higher runtime due to delayed evaluations. Ultimately, knowing the interpreter's evaluation order helps anticipate potential issues, improve efficiency, and write clearer, more effective code.

One App. One Place for Learning.

All the tools & learning materials you need for study success - in one app.

Get started for free

Most popular questions from this chapter

The sine of an angle (specified in radians) can be computed by making use of the approximation \(\sin x \approx x\) if \(x\) is sufficiently small, and the trigonometric identity \(\sin x=3 \sin \frac{x}{3}-4 \sin ^{3} \frac{x}{3}\) to reduce the size of the argument of \(\sin\). (For purposes of this exercise an angle is considered "sufficiently small" if its magnitude is not greater than \(0.1\) radians.) These ideas are incorporated in the following procedures: (define (cube \(x\) ) \((* x x x)\) ) (define (p \(x\) ) \((-(* 3 x)(* 4(\) cube \(x)))\) ) (define (sine angle) (if (not (> (abs angle) 0.1)) angle (p (sine (/ angle 3.0))))) a. How many times is the procedure \(\mathrm{p}\) applied when (sine 12.15) is evaluated? b. What is the order of growth in space and number of steps (as a function of \(a\) ) used by the process generated by the sine procedure when (sine a) is evaluated?

a. An infinite continued fraction is an expression of the form $$ f=\frac{N_{1}}{D_{1}+\frac{N_{2}}{D_{2}+\frac{N_{3}}{D_{3}+\cdots}}} $$ As an example, one can show that the infinite continued fraction expansion with the \(N_{i}\) and the \(D_{i}\) all equal to 1 produces \(1 / \phi\), where \(\phi\) is the golden ratio (described in section 1.2.2). One way to approximate an infinite continued fraction is to truncate the expansion after a given number of terms. Such a truncation-a so-called \(k\)-term finite continued fraction - has the form $$ \frac{N_{1}}{D_{1}+\frac{N_{2}}{\ddots+\frac{N_{K}}{D_{K}}}} $$ Suppose that \(\mathrm{n}\) and \(\mathrm{d}\) are procedures of one argument (the term index \(i\) ) that return the \(N_{i}\) and \(D_{i}\) of the terms of the continued fraction. Define a procedure cont-frac such that evaluating (cont- frac \(\mathrm{n} \mathrm{d} \mathrm{k}\) ) computes the value of the \(k\)-term finite continued fraction. Check your procedure by approximating \(1 / \phi\) using \(\begin{aligned} \text { (cont-frac (lambda (i) } & 1.0 \text { ) } \\ &\text { (lambda (i) } 1.0) \\ & \text { k) } \end{aligned}\) for successive values of \(\mathrm{k}\). How large must you make \(\mathrm{k}\) in order to get an approximation that is accurate to 4 decimal places? b. If your cont-frac procedure generates a recursive process, write one that generates an iterative process. If it generates an iterative process, write one that generates a recursive process.

Let \(f\) and \(g\) be two one-argument functions. The composition \(f\) after \(g\) is defined to be the function \(x \mapsto f(g(x))\). Define a procedure compose that implements composition. For example, if inc is a procedure that adds 1 to its argument, ((compose square inc) 6) 49

Modify fixed-point so that it prints the sequence of approximations it generates, using the newline and display primitives shown in exercise \(1.22\). Then find a solution to \(x^{x}=1000\) by finding a fixed point of \(x \mapsto \log (1000) / \log (x)\). (Use Scheme's primitive \(\log\) procedure, which computes natural logarithms.) Compare the number of steps this takes with and without average damping. (Note that you cannot start \(\mathrm{fixed}\)-point with a guess of 1 , as this would cause division by \(\log (1)=0\).)

Several of the numerical methods described in this chapter are instances of an extremely general computational strategy known as iterative improvement. Iterative improvement says that, to compute something, we start with an initial guess for the answer, test if the guess is good enough, and otherwise improve the guess and continue the process using the improved guess as the new guess. Write a procedure iterative-improve that takes two procedures as arguments: a method for telling whether a guess is good enough and a method for improving a guess. Iterative-improve should return as its value a procedure that takes a guess as argument and keeps improving the guess until it is good enough. Rewrite the sqrt procedure of section \(1.1 .7\) and the fixed-point procedure of section \(1.3 .3\) in terms of iterative-improve.

See all solutions

Recommended explanations on Computer Science Textbooks

View all explanations

What do you think about this solution?

We value your feedback to improve our textbook solutions.

Study anywhere. Anytime. Across all devices.

Sign-up for free