A Read-Evaluate-Print-Loop, or REPL, is a common way of interfacing with computer programs. Also known as a command line interface or shell, a REPL is a way of allowing a user to type a command, and for the program to respond to that command.
J's GUI session manager (the IJX) is an example of a REPL. So is its command line equivalent, jconsole.exe. We can leverage these two interfaces to provide REPLs to programs written in J, without reinventing that wheel (e.g. writing the interface in wd, or in another language entirely, communicating with J using COM or DLL calls, etc).
J is inherently block oriented, not stream oriented, whereas REPLs are inherently stream oriented. That is, J works best when it can work on all the data at once, but a REPL can only spoon feed it a line at a time.
Furthermore, REPLs, being a user interface, occupy the top level of control in a program. Thus it is not simple to embed a REPL as a small part of a larger program (e.g. for a background application to request the user make a decision, halfway through processing).
I've provided a R_PL template for J. The E is missing because you, as an J application developer, are supposed to fill that part in. That is, my script handles reading and printing in a loop -- yours must handle evaluating the input and calculating the output.
For now, see the example script . Or a simple application.
- ^:_ exits when input matches output; so if your E is functional (identical outputs for identical inputs) then if the user types the same thing twice in a row, J will exit prematurely.
- Can't seem to catch CTRL+C (or breaks caused by jbreak; but jbreak can be avoided with 9!:47''). Even failSafe doesn't protect from this style of interrupt. I tried various tricks with 9!:(27 29) and 13!:(0 15) and ::, to no avail. I may have to resort to try. (though going explicit may cause non-trivial complications)
- You cannot call repl from within a program. That is, nothing will work along the lines of:
my_verb =: verb define user_data =: capture repl '' process user_data ) my_verb ''
The call to repl has to be the top-level invocation; it can't be wrapped. You could do something along these lines:
my_verb =: verb define capture repl '' throw. ) my_verb ''
but you couldn't return flow of execution to my_verb. You'd have to ensure capture called the appropriate verb on the accumulated data from the REPL.