• Aucun résultat trouvé

Tail Recursion (Hunk O)

==================================================================

Hunk O starts here:

==================================================================

Many Scheme programs rely heavily on recursion, and Scheme makes it easy to use recursion in ways that aren't feasible in most other languages. In particular, you can write recursive procedures which call themselves instead of looping.

When a procedure calls itself in a way that is equivalent to iterating a loop, Scheme automatically

"optimizes" it so that it doesn't need extra stack space. You can use recursion anywhere you could use a loop in a conventional language. Technically, loop-like recursion is called tail recursion, which we'll explain in detail in a later chapter.

The basic idea is that you never have to return to a procedure if all that procedure will do is return the same value ot its caller. For example, consider the following procedure definition:

(define (foo) (bar)

(baz))

When foo calls baz, it is a tail call, because on return from baz, foo will do nothing except return the returned value to its caller. That is, the return to foo from baz will be immediately followed by a return to whatever procedure called foo. There's really no need to do two returns, passing through foo on the way back. Instead, Scheme avoids saving foo's state before the call to baz, so that baz can return directly to foo's caller, without actually coming back to foo.

Tail-calling allows recursion to be used for looping, because a tail call that acts to iterates a loop doesn't save the caller's state on a stack.

Scheme systems can implement such tail calls as a kind of GOTO that passes arguments, without saving the state of the caller. This is not unsafe, like language-level GOTO's, because it's only done when the result would be the same as doing the extra returns.

Some compilers for languages such as Common Lisp and C perform a limited form of "tail call optimization," but Scheme's treatment of tail calls, is more general, and standardized, so you can use recursion more freely in your programs, without fear of stack overflow if you code your routines

tail-http://www.federated.com/~jim/schintro-v14/schintro_73.html (1 of 2)11/3/2006 9:03:43 PM

An Introduction to Scheme and its Implementation - Tail Recursion

recursively.

And of course, you can use recursion the way you would in most languages, as well as for loops, so recursion can do both jobs. While Scheme has conventional-looking looping constructs, they're defined in terms of recursion.

Go to the first, previous, next, last section, table of contents.

http://www.federated.com/~jim/schintro-v14/schintro_73.html (2 of 2)11/3/2006 9:03:43 PM

An Introduction to Scheme and its Implementation - Macros

Go to the first, previous, next, last section, table of contents.

Macros

Scheme is very procedure-oriented, but procedures can't do everything, at least not in a way that is syntactically pretty and efficient.

Sometimes you want to define your own control structures and data-defining expressions that can't be clearly and efficiently expressed as procedures, and for this Scheme provides a syntactic extension or macro facility.

With macros, you can define stereotyped pieces of code, and how to transform them for different purposes.

You might have had bad experiences with macros in other languages, like C, but Scheme's macro system is special. It's an extremely powerful mechanism for abstracting over programs and putting things

together in special ways.

As we'll see in a later chapter, with Scheme macros you can effectively reprogram the compiler to change the language and its implementation. This is not something you'll need to do often--most of the time you'll do fine with normal programming and higher-order procedures--but sometimes it's extremely useful for building your own extended version of Scheme to solve particular kinds of problems, or for automating tedious and repetitive aspects of program construction.

Go to the first, previous, next, last section, table of contents.

http://www.federated.com/~jim/schintro-v14/schintro_74.html11/3/2006 9:03:47 PM

An Introduction to Scheme and its Implementation - Continuations

Go to the first, previous, next, last section, table of contents.

Continuations

Scheme has the usual control constructs that most languages have--conditionals (if statements), loops, and recursion--but it also has a very special control structure called

call-with-current-continuation.

(Warning: call-with-current-continuation is weird.)

call-with-current-continuation allows you to save the state of a computation, package it up as a data structure, and go off and do something else. Whenever you want, you can restore the old saved state, abandoning the current computation and and picking up where the saved computation left off.

This is far more powerful than normal procedure calling and returning, and allows you to implement advanced control structures such as backtracking, cooperative multitasking, and custom exception-handling.

You won't use call-with-current-continuation most of the time, because more

conventional control structures are usually sufficient. But if you need to customize Scheme with a special control structure to solve a particular kind of problem, you can do it with call-with-current-continuation.

==================================================================

This is the end of Hunk O.

TIME TO TRY IT OUT

At this point, you should go read Hunk P of the next chapter and work through the examples using a running Scheme system.

Then return here and resume this chapter.

==================================================================

(Go to Hunk P, which starts at section Basic Programming Examples (Hunk P).)

Go to the first, previous, next, last section, table of contents.

http://www.federated.com/~jim/schintro-v14/schintro_75.html11/3/2006 9:03:53 PM

An Introduction to Scheme and its Implementation - Iteration Constructs

Go to the first, previous, next, last section, table of contents.