In the bottom left hand of the screen in DrRacket click the "Choose
Language" dropdown, "Use the language declared in source" should be
selected on the left.
On the right you can choose the "Output Syntax". If you change it to
"write" then it will look how you want.
_________________________________________________
For list-related administrative tasks:
http://lists.racket-lang.org/listinfo/users
In Racket, as in Common Lisp and Clojure, the expression
'(1 2 3)
produces a list of three numbers. The only difference in this case
among the languages is how they print. Racket's default printing mode
prints values in the REPL in the same way as expressions, so it prints
the list of three numbers as
'(1 2 3)
> 2011/9/18 Racket Noob <racke...@hotmail.com>:
>> In Common Lisp or Clojure REPL, expression '(1 2 3) evaluates to (1 2 3).
No it doesn't. In CL and Clojure, '(1 2 3) evaluates to '(1 2 3) and then the printer turns it into (1 2 3).
Now imagine you wish to experiment at the REPL. (What an outrageous idea but some of us do.) In that case, you may wish to reuse a result from some REPL computation in the repl again. Just paste it back in and run. Ouch for Common Lisp. Ouch for Clojure:
function expected; given 1
This issue was clarified in a beautiful MIT dissertation around 1980 (Brian Smith) and nailed once and for all. Sadly Brian chose a horrible slogan, which the rest of the MIT lispers didn't understand and so his ideas got buried. I re-discovered them and so did many others.
Go figure why Lispers are hung up on a mistake from the 1950s.
-- Matthias
I know why you're confused. Let me see if I can help.
Here's an input program:
'(1 2 3)
Now be careful to make the following distinction:
- what it computes
- what it prints
What it computes is a list with three values. There are at least
three different ways to PRINT this:
1. (1 2 3)
2. #<list>
3. (quote (1 2 3))
The first has the disadvantage Matthias pointed out: you can't paste
the value back in in a bigger computation. The second has the same
disadvantage. The third has the advantage you can paste it back in.
You're probably concerned that pasting it back in "makes a new list".
Yes, it does. But if the expression '(1 2 3) were part of some bigger
computation -- eg,
(length '(1 2 3))
-- then no "new list" would be created. So it's only if you try
copying the output of one computation as the input of another that
there might be new allocation. But look at the word I just used:
"copy".
This isn't the full answer, but I think you need to make sure you've
got at least these steps under your belt before we go further. Do ask
questions.
Shriram
(There is, incidentally, a good reason why (+ 1 2) could, but does
not, evaluate to (+ 1 2).)
But overall, since I appear to be talking nonsense, I'll avoid
following-up and aggravating you further. Good luck.
> Saying that (quote (1 2 3)) evaluates to (quote (1 2 3)) [instead to (1 2 3)] is the same nonsanse to me like saying that (+ 1 2) evaluates to (+ 1 2) [instead to 3].
Be careful with words like "nonsense" :).
What does 3 evaluate to?
3
So, numbers evaluate to themselves. That's because numbers are "values".
In a similar way, #t evaluates to
#t
because it's also a value.
What about (list 1 2 3)? It's *also* a value. That is, (list 1 2 3) evaluates to a list containing three things, the numbers 1, 2, and 3. In Racket, this gets printed as
'(1 2 3)
... so that, like other values, its printed representation is also a legal program piece.
Does this choice make more sense now?
John
Yet another view:
(+ 1 2) evaluates to 3 is nonsense, it really evaluates to three.
(+ 1 2) evaluates to 3 is nonsense, it really evaluates to "3".
(+ 1 2) evaluates to 3 is nonsense, it really evaluates to three.
(+ 1 2) evaluates to 3 is nonsense, it really evaluates to #b00000011.
(+ 1 2) evaluates to 3 is nonsense, it really evaluates to ^C.
...
All Schemes and Lisps evaluate (list 1 2 3) into the same list,
including Racket. It just gets *printed* in some form that is
intended for human consumption.
And BTW, the different printout is not a Racket invention -- it is
used in scheme48/scsh. Or in MIT Scheme the printout is something
like ";; value: (1 2 3)" and obviously the ";;" prefix is not part of
the value.
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!
Maybe RacketNoob can start by doing this:
"In the bottom left hand of the screen in DrRacket click the "Choose
Language" dropdown, "Use the language declared in source" should be
selected on the left.
On the right you can choose the "Output Syntax". If you change it to
"write" then it will look how you want."
And then we can point him at some good things to read that will help
him make sense of all the good points and advice everyone has shared.
Perhaps: Racket reader documentation, quote documentation, Scheme
standard? That is how I learned. I loved this passage from the R6RS
spec:
``It is important to distinguish between the mathematical numbers, the
Scheme objects that attempt to model them, the machine representations
used to implement the numbers, and notations used to write numbers.''
Your attempt to use an interpreter model is commendable but falls
short. That is because you only described the READ and EVAL steps of
a REPL. The L(oop) is not relevant here, but the P(rint) is actually
the most critical part, and that's the one you left out of your
attempt at explaining what's happening.
Also, Matthias asked you about substituting answers inside bigger
expressions. You gave him a mechanical answer of why (you think) it
won't work, but you failed to understand the bigger point he was
trying to make in the first place.
Then it nicely accomplishes the task of alerting them that there are
many more surprises ahead.
(If Racket were just the same as some other Lisp, it would have no
need to exist.)
>
> > You keep thinking (1 2 3) is the canonical form of a list. It is
> > not. It's just a particular *print representation* of list. So is
> > #<list> or one of the many alternatives Eli proposed.
> >
>
> Oh, I understand that. It's just that I don't understand why you (i.e. Racket implementers) choose Racket by default prints list this way (different than all other lisps). I think this choice can confuse beginners (and all other users who switches from different lisp implementations and expects "traditional" REPL behaviour).
They partly made the choice for people like me, who didn't experience their courses or work through the the early chapters in HtDP; our group is still suffering from software I wrote before I understood the difference between the R and P in REPL (using several earlier versions of Scheme). I believe the Racket REPL would have eliminated that confusion. I also find flights over the ocean are more comfortable with turbine engines than piston engines.
rac
>
> > Your attempt to use an interpreter model is commendable but falls
> > short. That is because you only described the READ and EVAL steps of
> > a REPL. The L(oop) is not relevant here, but the P(rint) is actually
> > the most critical part, and that's the one you left out of your
> > attempt at explaining what's happening.
> >
> > Also, Matthias asked you about substituting answers inside bigger
> > expressions. You gave him a mechanical answer of why (you think) it
> > won't work, but you failed to understand the bigger point he was
> > trying to make in the first place.
> >
> > Shriram
Yes, so does that not alert you that (1 2 3) is the "nonsense" part?
There is no value that is (1 2 3).
I kindly suggest the thought that omitting the quote is precisely what
makes things harder for beginners. It seems to suggest to the
untrained that REPL is returning something that is not a value. As
Matthias and others have pointed out, you can not take the "value" (1
2 3) and use it somewhere else. What sense does that make?
I also believe John brought the point home for you. If 3 "evaluates"
to 3, then why should '(1 2 3) not "evaluate" to '(1 2 3)? They are
both constants and should exhibit similar behavior when evaluated.
--
Cheers,
Marco
FWIW, as one PL educator, I don't find that to be something I wish to
teach to the students who are beginning to learn what is important
about programming languages. I also don't think that a list is a
particularly good representation for a function application in an
implementation and as a mental device I think it can only confuse to
have two distinct concepts mapping in a single concrete thing.
Robby
I don't really see how to give a different answer to this question
than the one before.
I guess I consider myself a more general purpose educator and, IMO,
this (flawed) design decision is not worth explaining.
Don't get me wrong, there is a LOT to love about Lisp and I am
grateful for that heritage and how it shows up in Racket. I just don't
consider this particular detail to be the One True Way.
It's funny that here you're berating Robby, who's put more time into
different ways of printing than anyone I can think of in the Lisp
community. Take a look at the options offered in the "Show Details"
part of language selection. In particular, the quasiquote
representation is probably a better way to help students understand
the issues you think are vital.
Shriram
To me, speaking of real use of the language, it seems a lot less
important in Racket than it used to be, in Racket's Lisp ancestors. I
suspect it can be saved for an aside, when introducing syntax
transformers ("and here, we can get the form as a list if we want") or
maybe "eval" ("this will rock your world: data can be code. you should
probably never do this").
Unless someone finds it useful in explaining how evaluation works. I
don't have significant experience teaching intro programming, so I tend
to defer to PLT professors on what they've found worked for their intro
students.
--
http://www.neilvandyke.org/
Best wishes,
Robby
2011/9/18 Racket Noob <racke...@hotmail.com>:
> Such a cold community. :(
Cold? No way! We're *hot*. That is: we're eager to discuss, and eager to argue.
If anything, we're holding back, to avoid making you angry. Maybe we should have held back a bit more? I know it can feel a bit lonely when everyone disagrees with you.
A truly obstinate learner will continue arguing until he figures out what's going on in everyone else's brain, and why they think the way they do. This group is full of passionate people who care a *lot* about teaching!
John
Hello!
Whoa! I think you are reading a lot more aggression out of those
replies than what actually exists. Your english is fine; no one has
made a single remark about it. (Um, unless the previous sentence
counts...)
If it helps: the replies to this thread cover at least two or three
separate things.
1. They've shown you how to set up DrRacket so it prints things
the traditional Lisp way. If you adjust it in the language preference
menu, values should print exactly as they would in a traditional Lisp.
Have you been able to get this to work, or is the language preference
menu not working for you? Changing the default should be about two or
three mouse clicks, if I remember right.
2. Several people have given a justification for why the default
in Racket prints things in a way that's different from what you're
used to. The difference is not accidental: it's there by design. For
example, you can see Section 3.3 of
http://www.cs.brown.edu/~sk/Publications/Papers/Published/fffkf-drscheme-journal/paper.pdf,
as well as Section 2.1 of Wadler's "Why Calculating is Better than
Scheming" (http://www.cs.kent.ac.uk/people/staff/dat/miranda/wadler87.pdf)
So there's been a lot of thought about this, and the default in Racket
skews toward making it easier for students to think about calculating.
Admittedly, this means that Racket's default printing behavior is
deviating from traditional Lisps. But changing the default to Lisp
style should be easy to do. Is that sufficient for you, or do you
have a proposal?
3. There's a little bit of silliness on the thread because of the
situation: it's not clear from the email thread that you realize that
you're talking directly with several of the authors of DrRacket. You
have got incredible access to them on this mailing list.
Best of wishes to you!
> Yes, I got this to work. But, what if I don't want to use DrRacket, but just
> pure old console Racket.exe instead? Or emacs?
Oh! Then it should just print like Lisp mode, if I remember
correctly. Give me a sec; let me double check that.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$ racket
Welcome to Racket v5.1.2.
> (list 1 2 3)
'(1 2 3)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Oh! So I'm wrong about that. No problem. Let me just change a
parameter here...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (print-as-expression #f)
> (list 1 2 3)
(1 2 3)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Ok, now it should behave as you expect. I'm using the
print-as-expression parameter here to control the default printer.
For reference:
If you want to make that the default on your end, I think you can add
a line to your $HOME/.racketrc, so that this parameter is up
automatically when Racket's being run as a repl.
Ok, maybe this is not something that's important in other programming languages, but it *is* important in lisps. As a lisp educator, how can you *not* to teach this fundamental fact about lisp?
I don't understand why you (i.e. Racket implementers) choose Racket by default prints list this way.
Two hours ago, Danny Yoo wrote:
>
> So there's been a lot of thought about this, and the default in
> Racket skews toward making it easier for students to think about
> calculating.
I disagree with the "for students" part. It's specifically trying to
make it easier to use values printed on the *repl*, which is not where
(htdp-style) newbies should spend much time. So IMO it's something
that is useful in any context.
An hour and a half ago, Danny Yoo wrote:
> > Yes, I got this to work. But, what if I don't want to use
> > DrRacket, but just pure old console Racket.exe instead? Or emacs?
>
> [...]
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> > (print-as-expression #f)
> > (list 1 2 3)
> (1 2 3)
Even easier -- just use (current-print write), and you get the
"traditional" behavior. Here's a quick demo:
-> (current-print)
#<procedure:pretty-printer>
-> '(current-print write)
'(current-print write)
-> (current-print write)
#<void>
-> '(current-print write)
(current-print write)
Note that it also demonstrates how confusing things can be. IME,
explanations on what Lisp's "'" is doing are extremely frequent.
An hour and a half ago, Stephen Bloch wrote:
>
> Actually, in many ways I sympathize: when I first encountered Racket
> (which was then called PLT Scheme), I took a similar
> interpreter-based approach to understanding what it was doing
> (having previously encountered Lisp and learned the same
> "expressions are lists" dictum you learned). It turns out not as
> helpful as one would think.
The general principle is fine: for a language that allows
meta-facilities like macros and `eval', you obviously need access to
the structures that the implementation uses to represent code. This
*has* always been one of Lisp's core ideas. But the *implementation*
of this idea -- using *just* plain S-expressions for representing code
falls short in many ways. For example, you cannot represent source
location which is extremely important when you have a syntax error in
some big source file.
Now, in the Lisp world (mostly in CL), there is a tendency to stick
with the code == sexprs equivalence no matter what. As a result,
there are various hacks around these problems. The main one is to use
a hash table that can fake adding the extra information to the sexprs,
by mapping them into the extra information. That doesn't work with
symbols: they're interned, so you cannot distinguish two occurences of
the same symbol, and in some of these systems you can observe that
limitation of the system (for example, they won't have source
information for these cases). Also, writing well-behaved macros can
be a PITA, because such macros need to be aware of this implicit extra
information and make sure that they produce sexprs with the correct
information artifically attached in the same way.
To make things worse, in Scheme you have the issue of hygiene, which
-- again -- means that you need more than plain s-expressions to
represent code. Here too, there are solutions like the above, and
solutions where some kinds of expressions (mostly symbols) are put in
a "wrapper" that holds the extra syntactic context information. (You
can see this in Scheme implementations where syntax is "mostly
sexprs", except for identifiers that are no longer plain symbols.)
> In fact, the Racket reader does NOT represent expressions as lists;
> it represents them as "syntax objects", which (as I understand it)
> can be nested in the same way lists can, but carry some additional
> information.
Right -- Racket's solution is to dump the illusion of direct
correlation between syntax (= syntax objects) and data (s-expressions)
and instead use a new type for syntax (which, unsurprisingly, is
similar enough to s-expressions that it is trivial to convert syntax
to sexprs).
But that's not dumping the "spirit of Lisp" -- if anything, it's
*following* that spirit to the letter. The *core* idea above is the
one of "reifying" the compiler's representation in a way that is
accessible to user code -- and that was the great thing about sexprs.
As it turned out throughout the decades, plain sexprs cannot provide
sufficient information -- so instead of following what everyone else
does and cheating the additional information in, Racket chooses to
expose the *true* syntax objects to user code. Hopefully this
explains why I view this as being a more lispish solution than the one
taken by, for example, common lisp.
An additional benefit of that is that it is easier now to accomodate
new languages. You are no longer bound by the limits of plain sexprs;
your syntax representation is something that is more conveniently
treated as what it was supposed to be: the intermediate "Abstract
Syntax Tree" representation of code. In other words, it is a direct
result of sticking to the "Code is Data", and even preferring that
over "Code is Sexprs".
Yet another coincidental advantage that is more student-oriented, is
the fact that there is a better separation between representation of
code and representation of other data. You're much less likely to
confuse one for the other. It's mostly legacy that still makes the
Racket `eval' accept sexprs. It would be cleaner to make something
like (eval '(+ 1 2)) return '(+ 1 2) like any other quoted data, and
instead require (eval #'(+ 1 2)) -- or (eval (syntax (+ 1 2))) if you
want to evaluate the (+ 1 2) expression. Even better would be to make
eval throw an error when it accept anything that is not a syntax
object to begin with. That would make the difference between 123 and
#'123 more meaningful, instead of the other Lisp-inspired hack of
equating the 123 syntax with the 123 value. (And that's BTW, one of
the very nice properties of 3-Lisp, which Matthias mentioned earlier.)
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!