14

Suppose I have a file like

#lang racket/base
(define (hello) (print "Hello"))
... more definitions ...

and I would like to load the definitions in the file to interactively work with them in the (X)REPL. How do I do that?

If I start the (X)REPL and (load "/tmp/hello.rkt"), then the hello function is not made available to me:

-> (hello)
; hello: undefined;

If I (require (file "/tmp/hello.rkt")), the result is the same. Now I can (enter! (file "/tmp/hello.rkt")) and then (hello) works, but this seems rather ... unintuitive and beginner-unfriendly.

Is this indeed the way this should be done and should I simply read up on modules and namespaces to easily browse and experiment with my code or is there a simpler way I'm overlooking?

N.B. I found How do you load a file into racket via command line?, but that only explains how to run the file. Not how to load it in the REPL, so you can test/debug some specific definitions, then edit, reload, etc.

Community
  • 1
  • 1
Confusion
  • 16,256
  • 8
  • 46
  • 71

2 Answers2

15

Since files that start with #lang are modules, it does nothing if you load them. (Actually it does something, but probably not something that would help you.) It is really best to avoid using load completely, just pretend that it's not there.

Now, using require is the right thing, but what it does is instantiate the module and give you access to the names that it provides. In your case, you didn't provide anything which means that you can't use your hello. To do that, you can add (provide hello) to the file. But that's likely not what you want, since it seems that you want to debug code. (Ie, you won't want to provide everything from your module just to work on things.)

So the right thing to use is enter!, or if you're using xrepl, then there's a more convenient ,en command. This will instantiate the module and make the repl use the namespace of the module, so you can access everything. (And you don't need to load or require it.) You can also use it multiple times to reload the code if you change it. But note that there were some issues with it, so you might need to install a nightly build to work with it.

Finally, you probably know that, but working with DrRacket will make things much easier in general.

Eli Barzilay
  • 29,301
  • 3
  • 67
  • 110
  • OK, so `enter!` it is. The reason I'm using the (X)REPL is that I'm using the [charterm](http://www.neilvandyke.org/racket-charterm/) package for the CLI interface of my program and that package can't be used in DrRacket (which makes sense, because DrRacket doesn't provide a tty). – Confusion Feb 17 '13 at 10:49
  • It is used like this btw: `(enter! "file.rkt")` or use the simple version without need for parens and quotes: `,en file.rkt` – vlz Jul 02 '20 at 15:11
3

Putting the #lang racket/base at the top of your file is marking the file as a module form (this is the #lang shorthand); thus loading the file is just adding a module definition for (file "/tmp/hello.rkt"), as you have discovered when you required that path.

If you just want to experiment with a set of definitions and try loading them interactively, you might try removing the #lang racket/base from the top of the file. I illustrate this here on a pair of "Racket toplevel" (rktl) files:

% cat hello-unhashed.rktl
(define (hello) (print "Hello") (newline))
% cat hello2-unhashed.rktl
(define (hello) (print "Hello2") (newline))
% racket
Welcome to Racket v5.3.2.
> (load "hello-unhashed.rktl")
> (hello)
"Hello"
> (load "hello2-unhashed.rktl")
> (hello)
"Hello2"
> (load "hello-unhashed.rktl")
> (hello)
"Hello"
> (exit)
% 

Note that there are plenty of pitfalls when working at the top-level in the manner illustrated above. To get a feeling for what I am talking about, try googling "racket top level is hopeless" or "plt scheme top level is hopeless"

pnkfelix
  • 3,770
  • 29
  • 45
  • This gist from one of the Racket developers also provides a nice index of the "toplevel is hopeless" meme: https://gist.github.com/samth/3083053 – pnkfelix Feb 16 '13 at 12:07
  • `load` should never be recommended. Never. Just like `eval`, it's something that people who might find it useful are people who would know enough to not ask about it -- so by just asking about it you should know that it's not something to suggest... (And BTW, since such "toplevel" files are so different, we use `.rktl` as a suffix for them.) – Eli Barzilay Feb 16 '13 at 17:47
  • ah, I did not know about the `.rktl` convention. I'll edit my answer to at least use that for the files I made. The original question started off by using `load`, and I was just following through with that; I'll let the questioner decide which approach of the two we've given answered their question. – pnkfelix Feb 17 '13 at 01:59
  • 2
    My opinion about it is that `load` is as bad as `eval`. On one hand it's often less abused which makes it better, but OTOH it's something that people jump on without the inhibitions that they get for `eval`... In any case, using `load` in Racket is guaranteed to be a mistake for people who would ask about it. (That is, there are some valid uses for it, but those are things that only experts would do.) – Eli Barzilay Feb 19 '13 at 09:24