[racket] pretty-big->#lang (was: External connection toFinndesign Liitin)

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Aug 11 00:11:39 EDT 2011

At Wed, 10 Aug 2011 17:58:44 +0300, "Jukka Tuominen" warote:
> 
> I noticed that once the environment is evaluated first, pasting and running
> all the tests in a row in the DrRacket interaction window works without
> problems. The same behaviour with or without (require (for-syntax
> racket/base)).
> 
> In a way, it's an inconvenience rather than an error, but it still would be
> nice to find a solution or atleast an explanation of what is going on.

As Matthias says, you seem to be tripping over the difference between
the environment of an expression within a module and the namespace that
`eval' uses.

Maybe you've already seen this chapter in the guide about namespaces:

  http://docs.racket-lang.org/guide/reflection.html

If not, that may be a good place to start. Meanwhile, I've been
thinking about how we can explain better what's going on and why.
Below is an attempt.


Here's a program in English prose:

 Assume that your favorite color is red. Now imagine a balloon that is
 your favorite color. Paint a canvas the same color as the balloon.

As English goes, that's a fairly clear program with a fairly well
defined result. When I read those instructions, at least, I will always
produce a red canvas (assuming that I have a canvas and some red paint,
but a potential lack of art supplies is not the point here).

I would come up with a red canvas even if I read the instructions when
surrounded by people who speak only Chinese, obviously, since I'm the
one reading the instructions. Furthermore, it would be straightforward
to translate the program to Chinese, and then a person who reads
Chinese would produce a red canvas.

A translator might even take the liberty of simplifying the program to
just

  Paint a canvas red.

The translation loses some of the poetry of the original, but the
result is the same.

The paragraph is a module. It can be compiled (i.e., translated) and
optimized (i.e., simplified). A program can be made up of multiple
modules that are written in different languages, but since each module
can be reliably translated, they can all be compiled into some common
language to run the program.


Here's a different program:

 Tell the person next to you "Assume that your favorite color is red."
 Tell the person "Now, imagine a balloon that is your favorite color."
 Tell the person "Paint canvas the same color as the balloon."

Getting a red canvas back may be a little trickier in this case. If the
person next to me speaks only Chinese, then my program may fail with a
message-not-understood error.

If I want to translate the program to Chinese, then it's not clear
whether the parts in quotes should be translated. Maybe I mean for a
person who can read Chinese but only sound out English to run the
program when surrounded by English speakers, or maybe I mean for a
Chinese person to run the program when surrounded by Chinese people.
Either way, I have to be a lot more specific to a translator. (For more
complex programs, the instructions to the translator can become complex
and fragile.)

Finally, a translator probably won't feel comfortable simplifying the
program to

 Tell the person next to you "Paint a canvas red."

because there could be all sorts of environmental conditions that make
the result different --- around people who are unwilling to accept
assumptions about their favorite colors, for example.

The paragraph with "tell the person..." is a program that uses `eval'.
It can't be compiled and optimized as well, and the language context in
which it is run may change the result. The quotes around sentences
correspond to the quote in front of an expression passed to `eval';
there's no particular reason that the language for `eval' will match
the language of the program that has the quoted text. The questions
become even more complex if you try to implement different parts of the
program in different languages.


DrRacket's interactions window has to use `eval' in the sense that it
reads an expression to evaluate and then passes it on to the program
for an answer. When you run a module in DrRacket, the interactions
window treats expressions as being in the language of the module body.
Furthermore, since the interactions window works through `eval', it
turns out that DrRacket sets `eval' globally to use the module's
language while evaluating expressions in the interactions window. In
Racket terminology, DrRacket sets the `current-namespace' parameter to
the module's namespace when it initializes the interactions window.

In contrast, while the module body is being evaluated, `eval' treats
expressions as being in the language that is empty by default. That's
why you see different results from `eval' during the module evaluation
versus the interactions windows.

You may wonder why DrRacket doesn't initialize the namespace of `eval'
to be the module's namespace, so that in-module uses of `eval' and the
interactions window behave the same. In a program that is implemented
by multiple modules, which module's language should be used? If the
language it's always the main module's language, then a module may
behave differently on its own than as part of a larger program.

Furthermore, at some level, we don't want programs that use `eval' to
work easily. Making `eval' easy means making the translator (i.e,
compiler) more conservative. Also, we've seen too many problems with
programs containing `eval' when they're shipped to China or translated
to Chinese (so to speak). DrRacket therefore goes out of its way to
make the module and `eval' languages different, so that programmers
will be forced to consider the difference. (Interaction expressions are
a different story; since interaction expression are not part of the
program and won't be "shipped to China", DrRacket can be more
accommodating.)

That's what Matthias means when he says that modules can seem like a
bother, but the advantage is huge.


Hopefully I've convinced you that `eval' creates lots of trouble ---
and yet we keep it around! Think of `eval' as a power tool. We want it
around, but we want it to be used with care. I think your context
probably needs `eval', but I agree with Matthias that you'll be better
off using modules and sorting out namespaces.



Posted on the users mailing list.