[racket] pretty-big->#lang (was: External connectiontoFinndesign Liitin)
Hi Matthew,
thank you for taking the time to explain it in such detail. I believe I'm atleast closer to grasp the consepts of module and eval now. I've already understood earlier that the top level namespace is a potential place for collisions, and I can see it better now why it is so. I will still find the practice a challange, I'm afraid.
I'd like to bring in two sides to this learning story.
One is my personal and humble journey to learn new concepts in Racket and improve my skills to create fancier programs. In this case, I'll keep on reading and experimenting, usually tweak examples to better understand the moving parts, until some day I understand enough to create things from scratch. As many others have pointed out, I also find the examples very important.
Another side is my professional, usability perspective to these kind of issues. It goes very differently. It is a very bad thing for a usability expert to 'learn over' difficult parts, or start to tolerate strange or difficult characteristics.
Normally the way around is not to change the architecture, which usually is - as in this case very convincingly and passionately - good if not genious and the hard-core developers can understand and use it well. The problem usually is how to explain it to basic users without such a steep learning curve, often steep enough to make people give up or find a competitive system instead. We (Finndesign) try to solve these kind of issues through better user interfaces often involving graphical interfaces, which tend to bring it accessible and atractive to even much broader audience. So, I would try to make the concepts and individual functions more usable, or in some cases create illustrative tools to understand and use them. Sometimes these tools may be temporary, or sometimes they become daily tools.
In the case of eval/namespace, for example, I could imagine the following scenario:
Whenever you use eval command, a drop-down menu is provided to offer a list of existing namespaces to choose from (a choice is usually much more practical and usable than an empty space to figure out what is possible and in what format should I enter it). Even if you choose wrong the first time, you can easily correct it, and eventually grasp the right practise.
Additionally, you could expand the namespaces into a new window clearly listing out each namespace's definitions, and possibly even allow interaction with each of the namespaces.
BTW, I'm not planning to give up on my personal journey, I enjoy it too much. I just thought I would try to bring in a new aspect from a field more familiar to me. If you like the idea and find it possibly useful and feasible, I could try to draw a non-function GUI a la (jtu100:calculator~) to explain better what I mean. If seen desirable, it could be fleshed-out and integrated with DrRacket the same way as the Program Contour or Module Browser, for example.
br, jukka
> -----Original Message-----
> From: Matthew Flatt [mailto:mflatt at cs.utah.edu]
> Sent: 11 August 2011 07:12
> To: Jukka Tuominen
> Cc: users at racket-lang.org
> Subject: Re: [racket] pretty-big->#lang (was: External
> connectiontoFinndesign Liitin)
>
>
> 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.
>