I am working through the EOPL Scheme exercises using DrRacket in Windows 7. When I switch from #lang racket to #lang eopl, the output from the definitions pane no longer shows up in the interaction pane. To be clear, as trivial example, running
#lang racket
4
produces
4
> as you would expect. But running
#lang eopl
4produces only
> Is there anything I can do to change this behavior or is there another pane I should be looking at for output? I can, of course, evaluate expressions in the interaction pane and see the output, but this is tedious when I have multiple expressions I want to evaluate multiple times.
A possible workaround: print the value in the definitions pane, so it'll show up in the interactions pane. And use newline to separate lines:
(write 4)
(newline)
(write 2)
> 4
> 2
Of course, it'll be tedious if you want to display many values, but it's an improvement.
Looks like #lang eopl uses #%plain-module-begin, which does not print results, instead of #%module-begin, which does print results.
For a quick way to switch, create the following file with the following contents:
eopl-printing.rkt:
#lang racket
(require (except-in eopl #%module-begin))
(provide (all-from-out eopl))
(provide #%module-begin)
Then use this as the language in another file:
#lang s-exp "eopl-printing.rkt"
1
2
3
produces in my DrRacket:
Welcome to DrRacket, version 5.3.4.6 [3m].
Language: s-exp "eopl-printing.rkt" [custom].
1
2
3
>
CAVEAT: If eopl was hiding the results for a reason, then you may get some spurious output, but I don't know for sure.
Related
Scheme and Racket do not protect special forms, so it's possible to redefine them. Just purely out of curiosity, is there a way to get back special forms after they have been overwritten?
Example situation:
$ racket
Welcome to Racket v6.11.
> (define define 1)
> (+ define define)
2
> (define x 3) ; How to get the original 'define' back?
; x: undefined;
; cannot reference undefined identifier
; [,bt for context]
>
If I redefine a special form, is there a way to get back the special form?
Specifically in the REPL, where definition overriding is possible, you can simply (require (only-in racket/base define)) to get define back.
Welcome to Racket v7.3.
> (define define 1)
> (+ define define)
2
> (require (only-in racket/base define))
> (define x 3)
> x
3
For Racket files/modules, a simple answer is that once you make a top-level definition, you can't redefine it. However, you can still (require (only-in racket/base [define racket:define])) (rename define from racket/base as racket:define), and then use racket:define instead. Also note that while you can't redefine a top-level definition, you can shadow it, so you can use define in the body of (let-syntax ([define (make-rename-transformer #'racket:define)]) ...) for instance.
But note that in Racket, you can override #%module-begin which has a complete control of your file/module, so you can use this feature to create a new language that allows you to redefine top-level definitions, though at that point you are no longer using the "real" Racket.
Scheme and Racket do not protect special forms, so it's possible to redefine them. Just purely out of curiosity, is there a way to get back special forms after they have been overwritten?
Example situation:
$ racket
Welcome to Racket v6.11.
> (define define 1)
> (+ define define)
2
> (define x 3) ; How to get the original 'define' back?
; x: undefined;
; cannot reference undefined identifier
; [,bt for context]
>
If I redefine a special form, is there a way to get back the special form?
Specifically in the REPL, where definition overriding is possible, you can simply (require (only-in racket/base define)) to get define back.
Welcome to Racket v7.3.
> (define define 1)
> (+ define define)
2
> (require (only-in racket/base define))
> (define x 3)
> x
3
For Racket files/modules, a simple answer is that once you make a top-level definition, you can't redefine it. However, you can still (require (only-in racket/base [define racket:define])) (rename define from racket/base as racket:define), and then use racket:define instead. Also note that while you can't redefine a top-level definition, you can shadow it, so you can use define in the body of (let-syntax ([define (make-rename-transformer #'racket:define)]) ...) for instance.
But note that in Racket, you can override #%module-begin which has a complete control of your file/module, so you can use this feature to create a new language that allows you to redefine top-level definitions, though at that point you are no longer using the "real" Racket.
I would like to redefine a standard Racket function, namely display, within a lexical scope, as in this example:
(with-custom-display (display "hello"))
This should work even when the code within the scope of with-custom-display is from a different library or even racket/* packages.
Is this possible? If so, how to do it?
EDIT:
If not possible in general, at least for the case of display and other write functions... could I somehow transform every output by parameterizing on current-output-port then redirecting the transformed output to the original port?
While its not possible1 to globally replace arbitrary functions in Racket, you absolutely CAN change the standard out port that a Racket program uses (and by extension, functions like display). In fact, this is exactly what the readline collection in racket does, except for input ports rather than output ports.
Basically, all you need to do is parameterize current-output-port globally to be your special port. Since you want to ultimately write out to the original output port (but with colors), you can also grab the original output port before changing it to the new one. Your resulting code would look something like this:
#lang racket/base ;; init.rkt
(define orig-port (current-output-port))
(define new-output-port
.... uses orig-port ....)
(current-output-port new-ouput-port)
(replacing .... uses orig-port .... with the implementation of your new colored output port)
And now, any file that requires "init.rkt" will get color in its default output port.
(Note though that if you have multiple files that do this same sort of thing, you have to be careful to make sure that they don't happen in an unsafe order.)
You can also make your with-custom-display form as a simple language extension by doing:
#lang racket ;; custom-disp.rkt
(provide with-custom-display)
(require syntax/parse/define)
(define orig-port (current-output-port))
(define new-output-port
.... uses orig-port ....)
(define-simple-macro (with-custom-display body ...)
(parameterize ([current-output-port new-output-port])
body ...))
This is the general idea of how DrRacket is able to print output to a DrRacket specific repl, rather than your consoles stdout.
1Normally anyway, there are usually ways to break things if you really want to. But that's almost always a bad idea. ;)
I'd like to be able to manipulate sentences so that I can take them as an input and return an output based on things like the individual letters. For example, an ends-e command that would return all of the words that end in "e":
(ends-e '(only the good die young))
=> '(the die)
Unfortunately, "e" is a string, and '(only the good die young) is a sentence. Scheme has trouble understanding a sentence as a data type (because it isn't one). How do I turn a sentence that the user inputs with a quote and parentheses into something I can manipulate and return in the same sentence format?
This book: https://people.eecs.berkeley.edu/~bh/ssch8/higher.html#ft1 outlines some functions that can manipulate sentences and words, but posts a footnote at the bottom saying "Like all the procedures in this book that deal with words and sentences... [the] procedures in this chapter are part of our extensions to Scheme."
How do I get those extensions? I looked in a later chapter, but my understanding of the language is too rudimentary to understand how to create those procedures myself.
These are the error messages I get when I try to turn '(h) into a datatype scheme can understand.
Welcome to DrRacket, version 6.12 [3m].
Language: sicp, with debugging; memory limit: 128 MB.
> (symbol->string '(h))
. . symbol->string: contract violation
expected: symbol?
given: (mcons 'h '())
> (list->string '(h))
. . list->string: contract violation
expected: (listof char?)
given: '(h)
> (string->list '(h))
. . string->list: contract violation
expected: string?
given: (mcons 'h '())
> (string->symbol '(h))
. . string->symbol: contract violation
expected: string?
given: (mcons 'h '())
>
This means I cant ask scheme if '(h) is equal to "h". I can't even ask it if '(h) is equal to '(h)!
> (eq? '(h) "h")
#f
> (eq? '(h) '(h))
#f
>
In DrRacket there is a Simply Scheme compatibility language
1. From the Package Manager
Open the Package Manager: in DrRacket choose the menu "File" then choose "Package Manager...".
In the tab "Do What I Mean" find the text field and enter: "simply-scheme" without the quotes.
Click the "Install" button. This produces smoe output. When you can click "close output" it's finished and you may close the window.
Test it. Make sure DrRacket has "Determine language from source" in
the bottom left corner. Write the following program and click RUN:
#lang simply-scheme
(se (butlast (bf "this"))
"world")
; ==> (hi "world")
I was a little confused since SICP and Simply Scheme are two different books. SICP has their own specified procedures from their book and in DrRacket there is a specific language, #lang sicp, for that flavor of Scheme too. I've written a similar answer on how to install sicp.
Is it possible to update the program code while it is being interpreted by csi, the Chicken Scheme Interpreter? If so, how?
So that I can interactively change part of the code and immediately see the effects of that changes.
For example, suppose I have written the following program:
(define (loop)
(print "Ciao")
(rest 1)
(loop))
(loop)
(assume (rest 1) has the effect of pausing the program for a second).
If I run this program, trough csi, it prints the string "Ciao" every second. If I change the string "Ciao" into something else, for example into "else", and I save the program code file, then csi continue interpreting the old program code, so I continuously see the string "Ciao". I'd like, in this case, that when I save the modified code with the string "Ciao" replaced by "else", csi continue its interpretation job by looking into the modified file, instead of the old file.
So that I obtain as output some "Ciao" followed by some "else": the "else" start to appear when I replace "Ciao" by "else" in the source code.
In general, the answer is "don't". The way you're supposed to use the REPL is by evaluating piecemeal changes against it, then evaluating a function or two to make sure everything went as expected. Part of this approach is structuring your program so that it can be easily tested in pieces, which implies not automatically starting any infinite loops. In the specific case you're asking about, you could instead write
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
You can now incrementally develop do-stuff, periodically evaluating new versions to your interpreter and calling them to make sure they work, then eventually calling start once you're confident that it's doing the right thing.
You may get mileage out of this similar question asked about Common Lisp.
As an aside, if you were using Common Lisp and SLIME, you could now do more or less what you proposed:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
Starting that up would start printing Ciao on separate lines in your SLIME REPL. If you changed do-stuff to
(defun do-stuff ()
(format t "else~%"))
then hit it with C-c C-c (the default binding for slime-compile-defun), you'd see your SLIME REPL start printing else lines in-flight.
CL-USER> (main-loop)
Ciao
Ciao
Ciao
; compiling (DEFUN DO-STUFF ...)else
else
else
else
else
else
; Evaluation aborted on NIL. User break.
CL-USER>
I'm not sure how to accomplish the same thing in Scheme, but I'm reasonably sure it's possible.
All that being said, you sometimes want to run a program part of which is an infinite loop. A real world example would be while testing a TCP server of some sort. If you're in such a situation, and your desired workflow is
Write file
Run csi my-file.scm
Edit file
Kill csi
Run csi my-file.scm
goto 3
and you basically just want to automate steps 4 through 6, you'll need an external tool to do it for you. Take a look at entr or hsandbox (the latter doesn't have Scheme support out of the box, but it doesn't look like it would be too hard to add).
There is no common way to make a running program check its source for changes but you there seems to be enough feratures available in Chicken to roll your own:
(use posix)
(use srfi-18)
(define (watch-reload! file)
(define (tsleep n)
(thread-sleep! (seconds->time (+ n (time->seconds (current-time))))))
(define (get-time)
(file-modification-time file))
(thread-start!
(lambda ()
(let loop ((filetime '()))
(let ((newtime (get-time)))
(when (not (equal? filetime newtime))
(load file))
(tsleep 10)
(loop newtime))))))
Now all you have to do is to use watch-reload! instead of load and it will check and reload every 10 seconds if the file has been modified.
If you save when the file is not valid scheme it stops working until you call watch-reload! on it again.
It may be that chicken programmers might have a better solution.