2
votes

Is 'exit' the proper way to exit a gui application in Racket using a button or is some other method best for this?

(define myfr 
    (new frame% [label "myframe"] [width 100] [height 100] ))
(new message% [label "my gui app"][parent myfr])
(define exitbutton 
    (new button% [parent myfr] [label "Exit"]
                 [callback   (lambda (b e)   (exit)  )]))
(send myfr show #t)

I find that DrRacket gives "Interactions disabled" warning message on using the exit button but there is a clean exit when closing using frame's [x] button.

I found "on-exit" method but not actual exit method on this page: https://docs.racket-lang.org/gui/frame_.html?q=frame%25 . Also nothing specific is mentioned on https://docs.racket-lang.org/reference/Exiting.html

Following statement, I believe, will only hide the frame and not close the application:

(send myfr show #f)
2
As Leif mentions "Interactions disabled" does indicate a clean exit. You stopped the program - which "includes the repl". - soegaard

2 Answers

1
votes

The exit is absolutely the way you want to end an application. The reason why the REPL in DrRacket stops when you do it, however, is because your program is no longer running, which will happen whenever you call exit, even if there is no gui in your program.

You are also correct that:

(send myfr show #f)

will hide the window but not actually quit the app.

So, one thing you could do is try to test if you are running in DrRacket or not. And if you are, rather than exiting the program, just close the window, and let DrRacket quit the application after the user clicks kill or starts a new program.

The problem with this is that in general, it is not possible to detect if you are running in a sandbox. There are some hacks you can do to test this out, but it's not very robust:

Determin if a racket program is in a sandbox

Another approach would be to create your own sandbox, and run your program in that sandbox (which is how DrRacket will run your code actually). Then, when your program exits, there will still be an available repl. Although be aware that the repl will be for the sandbox itself, rather than the repl it is in.

Here is the documentation for creating a sandbox.

1
votes

Leif already explained it fully, but I just wanted to describe it differently to a more novice audience.

"gui application" you refer in your question may mean different things depending on where you're running that code piece.

If run from DrRacket REPL, the lambda (exit) will exit from the REPL (leading to "interactions disabled" message). If this code is a piece of a script run by racket executable (for example, from the command line), it will exit that script / shell (probably what you want).

I'm not sure if you want to try in the exit code understanding if you're in a sandbox or REPL and behave differently on exit button click per environment, but again Leif also pointed to an answer for it, too.

Another reason for writing this somehow unnecessary addition to Leif's answer is, I wanted to point to your term "gui application". My apologies if I'm sounding patronizing. Showing a gui frame or other graphical interfaces in your application is a functionality that you choose to use, and doesn't make the application something different. One difference from an Operating System's perspective would be a callback function associated with a top-level frame/window. And that callback function is nicely (most probably - although I didn't examine details of racket's code for it) registered and handled by the language in our case. So I'd like to say - showing a gui or not I would consider them the same, and it will exit when you call (exit). And normally (probably) the x button of a frame will hide it by default (as you're already aware, hence you added the exit lambda function). You application can unhide it during the application lifetime.