I'm writing a program in Racket, which I'm running with racket foo.rkt. This works, except that the result of every expression at the program top-level gets printed, even though no print function was called. It's as if the program were entered line by line to the REPL, but in this case I'm not trying to use the REPL at all, I'm just trying to run a program from the command line.
How do you get Racket to not print things?
#lang racket, the default language in the Racket implementation, prints top level statements except (void), that returns a value that is always ignored by the REPL, and (values), which return zero values back and thus REPL has nothing to print. This means you can make a main function that ends with either one of them and it will have no output from the REPL.
statement-1
statement-2
statement-3
And change this to:
(define (main)
statement-1
statement-2
statement-3
(void)) ; or (values)
Forms like define and set! returns the same value as (void) for th exact same purpose.
Not all languages supported by racket prints top level statements. The actual Scheme language #!r6rs, does not print top level statements.
Related
I'm trying to learn Common Lisp, and found something unexpected (to me) when trying something out in the repl. Based on order of execution in most programming languages, and the great first class function support I'd always heard about from lisp, I'd think the following should work:
((if t 'format) t "test")
In Ruby I can do:
if true
Object.method(:puts)
end.call("test")
My thinking in how the above lisp code should work is that it should evaluate the inner lisp form, return format, then begin evaluating the outer lisp form, with format then being the first atom. I'd read that the first form needs to be a symbol, so I also tried ((if t format) t "test") even though my initial thought was that this would try to evaluate format before returning from the inner form.
I've noticed that sometimes lisp forms need to be preceded by #' in order for their results to be callable, but using (#'(if t 'format) t "test") doesn't work either. I'm sure I'm just misunderstanding something basic as I'm pretty new to lisp, but what's going on here?
Common Lisp doesn't evaluate the first element of an expression normally. It has to be either a literal symbol naming a function, or a lambda expression.
If you want to call a function determined dynamically, you need to use the FUNCALL function:
(funcall (if t 'format) t "test")
This is analogous to the need to use the .call() method in Ruby.
What you tried would work in some other Lisp dialects, such as Scheme.
The Common Lisp Hyperspec page for print mentions this:
print is just like prin1 except that the printed representation of object is preceded by a newline and followed by a space.
This is the first time I've seen a function like this, and it threw me off the first time I used it, because I never expected that a function with such a common name might include an uncommon feature.
I'm looking for the original reason. I know it might simply be because that's how another then-common lisp might have done it, and common-lisp simply adopted it, but if that's the case I'm looking for the design reason in that other lisp.
I imagine it might have something to do with ensuring that the output is always readable with read straight out of print. Though I would've preferred a newline for this, I can guess that the trailing space might be so that in a stream, read can know that it's the end of an object and return it immediately without having to wait for the rest of the stream (the following prints). However, I still can't figure out the purpose behind the preceeding newline.
I've been looking through the HyperSpec, but I can't find a reason mentioned.
EDIT:
I looked into Common-Lisp's predecessors, specifically InterLisp, MacLisp, and MacLisp's predecessor Lisp 1.5.
Interlisp's (page 145 in this pdf) and Lisp 1.5's (page 140 in this pdf) print function print the object followed by a newline.
It seems it was MacLisp that introduced this difference. I didn't find a reason in the original reference manual, and I only found the following on this revised reference manual:
Like PRIN1, PRINT outputs object to file in a form that can be understood by READ. However, object is output preceded by newline and followed by a space so that repeated calls to PRINT can be done without having the end of one object run into the begining of the next.
Of course, the trailing newline in the original definition would've sufficed for that purpose, so this reason doesn't seem valid.
EDIT 2:
As shown by Rainer Joswig's answer, it seems that this change appeared in Lisp 1.6 before MacLisp.
See for example: PDP-6 LISP (LISP 1.6) Revised. (January 1967)
My guess would be that this variant of PRINT (which writes a newline, then the s-expression in readable format and then a space) entered the MIT branch of Lisp because of its use in the Read Eval Print Loop. See page 1 and 17 of above. From PDP-6 Lisp 1.6 it moved into what was then called Maclisp and beyond.
Jon L White would know it.
Look at the example for the REPL, the read eval PRINT loop, on page 1.
Here I use a LispWorks Lisp listener, where the last closing parenthesis already makes READ accept the s-expression and no further enter is necessary:
CL-USER 25 > (PROG NIL
A
(TERPRI)
(PRINT (EVAL (READ)))
(GO A))
(+ 12 12)
24
(+ 45 (*
34
12
12))
4941
Each result is on its own line. This is btw. also like the interaction on a MIT Lisp Machine - the last closing parenthesis enters the s-expression, the expression is evaluated and the value(s) printed.
Now imagine that it is defined to not print a newline first:
CL-USER 27 > (PROG NIL
A
(TERPRI)
(PRIN1 (EVAL (READ)))
(terpri)
(GO A))
(+ 1 2)3
(* 23 (+ 1
1
3))115
The result would be printed directly after the last closing parenthesis.
Peter Norvig gives the same reasoning in his book Paradigms of Artificial Intelligence Programming, page 231/232 (as noted by user dkim):
In Lisp, however, the function print puts in a newline before the object to be printed, and a space after. ... In UNIX there was only one reasonable policy, because all input to the UNIX interpreter (the shell) is terminated by newlines, so there is no need for a newline-before. In some Lisp interpreters, however, input can be terminated by a matching right parenthesis. In that case, a newline-before is needed, lest the output appear on the same line as the input.
Basically this is a REPL-only function, something along the lines of "poor man's trace or debug".
It's use case is something like
(map nil #'print list)
or, more generally,
(complex-traversal-map #'print weird-structure)
It inserts whitespace around the printed object to avoid interference
with the output of other print calls.
What kind of whitespace is emitted has evolved over the decades.
It should have been called print-on-a-separate-line but it had to be
short and easily guessable.
It's essentially "legacy" functionality, like rplaca and rplacd.
#lang racket/base
(module x scribble/text
#(display 123))
It seems like #lang statements are not valid in nested sub-modules, and the expanded module version above is missing something:
error: module: no #%module-begin binding in the module's language
update:
looks like this more or less works, but is there a better way? does scribble do something with output ports that isn't being handled?
#lang racket/base
(module x scribble/text/lang
(#%module-begin
#reader scribble/reader #list{
hi
#(+ 1 456)
}))
First, your code has a redundant #%module-begin which can be removed.
#lang does several things -- one is control the semantics of the file
by determining the set of initially imported bindings, and that's
something that the module form has done before #lang came up. With
submodules, it became possible to use module for parts of a file too.
However, #lang can also determine the reader that parses the file, and
that's not possible to do with submodules, so you're stuck with only one
toplevel #lang to set the parser for the whole file.
(Sidenote: There is a technical reason for that. A #lang reader reads
the rest of the file until it reaches an eof value, so a nested
#lang would require getting an eof value before getting the end of
the file, or adding a new kind of eof-like value. That means that it's
a change that should be done carefully -- it's possible to do, of
course, but the need didn't come up often enough. Hopefully it will, in
the future.)
But in your case you don't want a completely new concrete syntax, just
an extension for s-expressions -- and an extension that was chosen to
have a minimal impact on regular code. So in almost all cases it's fine
to just enable the #-form syntax for the whole file, and then use
#-forms where you want it. Since it's just an alternative way for
reading sexprs, you can even use that with module, leading to this
code that doesn't need to use #reader:
#lang at-exp racket/base
#module[x scribble/text/lang]{
hi
#(+ 1 456)
}
(require 'x)
One thing that is a bit strange here is using scribble/text/lang and
not just scribble/text. Usually, #lang foo is exactly the same as
(module x foo ...) after reading the code with foos reader. But in
the case of the scribble/text language there is another difference:
using it as a #lang makes the semantics of the module body be "output
each thing". The idea is that as a language you'll want to spit out
mostly-text files, but as a library you'll want to write code in it
and do the printout yourself.
Since this code uses module, using scribble/text means that you're
not getting the spit-all-out functionality, which is why you need to
explicitly switch to scribble/text/lang. But you could have instead
just do the spitting yourself using the language's output, which would
give you this code:
#lang at-exp racket/base
(module x racket/base
(require scribble/text)
(output #list{
hi
#(+ 1 456)}))
(require 'x)
Note that scribble/text is not used as a language here, since it
doesn't provide enough stuff to be one when used (outside of a #lang).
(Which you've found out, leading to that redundant #%module-begin...)
This version is slightly more verbose, but I'm guessing that it makes
more sense in your case, since using it for some part of the code means
that you want to use it as a library.
Finally, if you really don't want to read the whole file with the #
syntax, only some parts, then the #reader that you've found is
perfectly fine. (And this is made simple with scribble/text that
treats lists as concatenated outputs, so you need just one wrapper for
each chunk of text.)
I'm learning about macros in Racket (language successor of Scheme). There is no mentioning of when the macro expansion is performed. On page 17 of this document I found a paragraph that says it happens before type-checking, evaluation and compiling.
So if I understand correctly, macro expansion occurs right after building the abstract syntax tree (AST)?
Although a Racket expert might correct me, my understanding is that the main stages are:
A read pass that processes the input characters into a syntax object.
An expansion pass that recursively expands the syntax object, including using user-defined macros.
Evaluation. (JIT compilation happens during evaluation, whenever a not-yet-compiled function is called.)
In other words the REPL (read eval print loop) is really more like a REEPL (read expand eval print loop).
For an extreme level of detail see Language Model including e.g. the Syntax Model section.
You mentioned "type-checking".
Plain Racket (e.g. #lang racket) is dynamically typed and checking is done at runtime.
Typed Racket (e.g. #lang typed/racket) does static type-checking during expansion: the Typed Racket system is implemented via macros. See Section 10, "Implementation", of Sam Tobin-Hochstadt's dissertation.
(Edited to note the JIT is actually part of evaluation, not a separate stage.)
There are languages other than Lisp (ruby, scala) that say they use REPL (Read, Eval, Print, Loop), but it is unclear whether what is meant by REPL is the same as in Lisp. How is Lisp REPL different from non-Lisp REPL?
The idea of a REPL comes from the Lisp community. There are other forms of textual interactive interfaces, for example the command line interface. Some textual interfaces also allow a subset of some kind of programming language to be executed.
REPL stands for READ EVAL PRINT LOOP: (loop (print (eval (read)))).
Each of the four above functions are primitive Lisp functions.
In Lisp the REPL is not a command line interpreter (CLI). READ does not read commands and the REPL does not execute commands. READ reads input data in s-expression format and converts it to internal data. Thus the READ function can read all kinds of s-expressions - not just Lisp code.
READ reads a s-expression. This is a data-format that also supports encoding source code. READ returns Lisp data.
EVAL takes Lisp source code in the form of Lisp data and evaluates it. Side effects can happen and EVAL returns one or more values. How EVAL is implemented, with an interpreter or a compiler, is not defined. Implementations use different strategies.
PRINT takes Lisp data and prints it to the output stream as s-expressions.
LOOP just loops around this. In real-life a REPL is more complicated and includes error handling and sub-loops, so-called break loops. In case of an error one gets just another REPL, with added debug commands, in the context of the error. The value produced in one iteration also can be reused as input for the next evaluation.
Since Lisp is both using code-as-data and functional elements, there are slight differences to other programming languages.
Languages that are similar, those will provide also similar interactive interfaces. Smalltalk for example also allows interactive execution, but it does not use a data-format for I/O like Lisp does. Same for any Ruby/Python/... interactive interface.
Question:
So how significant is the original idea of READing EXPRESSIONS, EVALuating them and PRINTing their values? Is that important in relation to what other languages do: reading text, parsing it, executing it, optionally print something and optionally printing a return value? Often the return value is not really used.
So there are two possible answers:
a Lisp REPL is different to most other textual interactive interfaces, because it is based on the idea of data I/O of s-expressions and evaluating these.
a REPL is a general term describing textual interactive interfaces to programming language implementations or subsets of those.
REPLs in Lisp
In real implementations Lisp REPLs have a complex implementation and provide a lot of services, up to clickable presentations (Symbolics, CLIM, SLIME) of input and output objects. Advanced REPL implementations are for example available in SLIME (a popular Emacs-based IDE for Common Lisp), McCLIM, LispWorks and Allegro CL.
Example for a Lisp REPL interaction:
a list of products and prices:
CL-USER 1 > (setf *products* '((shoe (100 euro))
(shirt (20 euro))
(cap (10 euro))))
((SHOE (100 EURO)) (SHIRT (20 EURO)) (CAP (10 EURO)))
an order, a list of product and amount:
CL-USER 2 > '((3 shoe) (4 cap))
((3 SHOE) (4 CAP))
The price for the order, * is a variable containing the last REPL value. It does not contain this value as a string, but the real actual data.
CL-USER 3 > (loop for (n product) in *
sum (* n (first (second (find product *products*
:key 'first)))))
340
But you can also compute Lisp code:
Let's take a function which adds the squares of its two args:
CL-USER 4 > '(defun foo (a b) (+ (* a a) (* b b)))
(DEFUN FOO (A B) (+ (* A A) (* B B)))
The fourth element is just the arithmetic expression. * refers to the last value:
CL-USER 5 > (fourth *)
(+ (* A A) (* B B))
Now we add some code around it to bind the variables a and b to some numbers. We are using the Lisp function LIST to create a new list.
CL-USER 6 > (list 'let '((a 12) (b 10)) *)
(LET ((A 12) (B 10)) (+ (* A A) (* B B)))
Then we evaluate the above expression. Again, * refers to the last value.
CL-USER 7 > (eval *)
244
There are several variables which are updated with each REPL interaction. Examples are *, ** and *** for the previous values. There is also + for the previous input. These variables have as values not strings, but data objects. + will contain the last result of the read operation of the REPL. Example:
What is the value of the variable *print-length*?
CL-USER 8 > *print-length*
NIL
Let's see how a list gets read and printed:
CL-USER 9 > '(1 2 3 4 5)
(1 2 3 4 5)
Now let's set the above symbol *print-length* to 3. ++ refers to the second previous input read, as data. SET sets a symbols value.
CL-USER 10 > (set ++ 3)
3
Then above list prints differently. ** refers to the second previous result - data, not text.
CL-USER 11 > **
(1 2 3 ...)
Seeing as the concept of a REPL is to just Read, Eval, Print & Loop it's not too suprising that there are REPLs for many languages:
C/C++
C#/LINQ
Erlang
Haskell (on windows)
Java
Javascript
Julia
Perl
Python
Ruby
Scala
Smalltalk -- I learned it on a REPL!
I think it is interesting to compare two approaches. A bare bones REPL loop in a Lisp system would look like this:
(loop (print (eval (read))))
Here are two actual Forth implementations of a REPL loop. I'm leaving nothing out here -- this is the full code to these loops.
: DO-QUIT ( -- ) ( R: i*x -- )
EMPTYR
0 >IN CELL+ ! \ set SOURCE-ID to 0
POSTPONE [
BEGIN \ The loop starts here
REFILL \ READ from standard input
WHILE
INTERPRET \ EVALUATE what was read
STATE # 0= IF ." OK" THEN \ PRINT
CR
REPEAT
;
: quit
sp0 # 'tib !
blk off
[compile] [
begin
rp0 # rp!
status
query \ READ
run \ EVALUATE
state # not
if ." ok" then \ PRINT
again \ LOOP
;
Lisp and Forth do completely different things, particularly in the EVAL part, but also in the PRINT part. Yet, they share the fact that a program in both languages is run by feeding its source code to their respective loops, and in both cases code is just data (though in Forth case it is more like data is also code).
I suspect what anyone saying only LISP has a REPL is that the READ loop reads DATA, which is parsed by EVAL, and a program is created because CODE is also DATA. This distinction is interesting in many respects about the difference between Lisp and other languages, but as far as REPL goes, it doesn't matter at all.
Let's consider this from the outside:
READ -- returns input from stdin
EVAL -- process said input as an expression in the language
PRINT -- print EVAL's result
LOOP -- go back to READ
Without going into implementation details, one can't distinguish a Lisp REPL from, for example, a Ruby REPL. As functions, they are the same.
I guess you could say that Scala's "REPL" is an "RCRPL": Read, Compile, Run, Print. But since the compiler is kept "hot" in memory, it's pretty fast for ongoing interactions--it just takes a few seconds to start up.
There are a number of people that consider a REPL to needs to behave exactly like it does in LISP, or it's not a true REPL. Rather, they consider it something different, like a CLI (command line interpreter). Honestly, I tend to think that if it follows the basic flow of:
read input from the user
evaluate that input
print the output
loop back to the read
then it's a REPL. As noted, there are a lot of languages that have the above capability.
See this reddit thread for an example of such a discussion.
How is Lisp REPL different from non-Lisp REPL?
Let's compare Common Lisp's REPL with Python's IPython.
The main two points are:
Lisp is an image-based language. There is no need to restart the process/the REPL/the whole app after a change. We compile our code function by function (with compiler warnings etc).
we don't loose state. Even more, when we update class definitions, our objects in the REPL are also updated, following rules we have control upon. That way we can hot-reload code in a running system.
In Python, typically, you start IPython or you are dropped into ipdb. You define some data until you try out your new function. You edit your source, and you want to try again, so you quit IPython and you start the whole process again. In Lisp (Common Lisp mainly), not at all, it's all more interactive.
There's a nice project called multi-repl which exposes various REPLs via Node.JS:
https://github.com/evilhackerdude/multi-repl
If you look at the list of supported languages, it's quite clear that not only Lisp has the concept of a REPL.
clj (clojure)
ghci (ghc)
ipython
irb (ruby)
js (spidermonkey)
node
python
sbcl
v8
In fact implementing a trivial one in Ruby is fairly easy:
repl = -> prompt { print prompt; puts(" => %s" % eval(gets.chomp!)) }
loop { repl[">> "] }