# How to make top-level depend on module-begin's success?

**URL:** <https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232>\
**Category:** Questions & Answers\
**Created:** [October 14, 2024, 3:34pm UTC](https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232 "2024-10-14T15:34:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![JoeyEremondi](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/joeyeremondi/32/1834_2.png) [@JoeyEremondi](https://racket.discourse.group/u/JoeyEremondi)\
**Post date:** [October 14, 2024, 3:34pm UTC](https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232/1 "2024-10-14T15:34:55Z")

</div>

Does anyone understand the interaction between `#%module-begin` and `#%top-interaction` in Racket? E.g. if I do:

```scheme
#lang racket
(if x y) ;; syntax error, missing else case

```

And hit "Run" in Dr. Racket, it gives a syntax error about the `if`, but still gives you a REPL that you can type in.

Is there a way to make it so that you can't get a REPL unless the current file successfully loads?

---

<div class="post-metadata">

**Author:** ![shhyou](https://avatars.discourse-cdn.com/v4/letter/s/ccd318/32.png) [@shhyou](https://racket.discourse.group/u/shhyou)\
**Post date:** [October 19, 2024, 9:16pm UTC](https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232/2 "2024-10-19T21:16:41Z")

</div>

My guess is that this behavior is hard-coded in DrRacket, so there's no way to work around it.

> <https://github.com/racket/drracket/blob/799151772d141f4bd2e53ddd5380b7ab5014cd74/drracket/drracket/private/module-language.rkt#L471-L480>

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [October 19, 2024, 10:02pm UTC](https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232/3 "2024-10-19T22:02:42Z")

</div>

Based on @shhyou's digging, here's a way to do it by arranging for the `#%top-interaction` to be different if the module is successfully expanded. A more robust implementation could still allow modules written in the language to define `#%top-interaction`. You can try this with `#lang s-exp`.

```scheme
#lang racket
(provide (except-out (all-from-out racket)
                     #%top-interaction
                     #%module-begin)
         (rename-out [no-top-interaction #%top-interaction]
                     [modbegin #%module-begin]))
(define-syntax (no-top-interaction stx)
  (syntax-case stx ()
    [(_ . form)
     (raise-syntax-error #f "interactions disabled for invalid module" stx #'form)]))
(define-for-syntax (yes-top-interaction stx)
  (syntax-case stx ()
    [(_ . form)
     #`(#%top-interaction . form)]))
(define-syntax (modbegin stx)
  (syntax-case stx ()
    [(_ body ...)
     #`(#%module-begin
        (define-syntax #,(datum->syntax stx '#%top-interaction)
          yes-top-interaction)
        body ...)]))

```

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [October 20, 2024, 9:44pm UTC](https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232/4 "2024-10-20T21:44:51Z")

</div>

FWIW, Captain Obvious, maybe not important:

IIRC DrRacket and Racket Mode already show a message and disable the REPL when `#%top-interaction` isn't defined at all -- when it's not in `namespace-mapped-symbols` for a namespace "inside" the module (from `module->namespace`). Some langs like `#lang info` (IIRC) do this, always.

So I think it would also work for an expansion conditionally not to define `#%top-interaction` at all.

Having said that, I think an advantage of your approach is your `raise-syntax-error` can supply a more precise/informative error message ("no REPL available because your program failed to type check" or whatever). This makes it clearer it's related to the particular user program, not a feature of the module for all user programs.

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [October 22, 2024, 6:38am UTC](https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232/5 "2024-10-22T06:38:23Z")

</div>

> [@greghendershott](#):
>
> Some langs like `#lang info` (IIRC) do this, always.

I've wished `#lang info` would define `#%top-interaction`!

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [October 22, 2024, 3:13pm UTC](https://racket.discourse.group/t/how-to-make-top-level-depend-on-module-begins-success/3232/6 "2024-10-22T15:13:01Z")

</div>

It has never bothered me, because I misbelieved `#lang info` was supposed to the moral equivalent of a dictionary or hash-table, where the values are all simple string, number, and list values. At least, that's all that I've done myself, or noticed in examples. Given that, what could the REPL show, that isn't self-evident in the source?

But just now I re-checked [the docs](https://docs.racket-lang.org/raco/info_rkt.html) and noticed the grammar has a whole section of `info-primitive` items. So it could be handy to view the resulting values in a REPL, without needing to fire up `get-info`.

p.s. I suppose the Racket Mode REPL could inject, when missing, a `#%top-interaction` like [the one for racket](https://github.com/racket/racket/blob/e088ab881632494e5ad7b83fd12a86a6ef1d0f53/racket/collects/racket/private/top-int.rkt#L4). But I suspect that would be one of those things where it's 2 minutes to implement the feature itself... and hours to work out how users configure/control/understand when that magic happens, or not. 🙂
