This patch implements the 2!:2 foreign function,
enabling J to spawn subprocesses and communicate with them
bidirectionally through pipes.
Patch: host-io-2_2.patch
The 2!:2 foreign function spawns an external process and
returns file handles that can be used to communicate with it:
handles =. 2!:2 'bc -l' NB. Start interactive bc calculator
handles NB. Returns: pid stdin_handle stdout_handleThis enables J to:
Implements 2!:2 as a working subprocess communication
system on Unix platforms. The original J source had this function
commented out with #if 0 and marked “doesn’t work”.
The implementation includes line buffering for real-time interactive behavior.
NB. Start a subprocess
handles =. 2!:2 'python3 -i'
'pid stdin stdout' =. handles
NB. Write to subprocess stdin
'print(2+2)\n' 1!:2 stdin
NB. Read from subprocess stdout
result =. 1!:1 stdout
NB. Wait for subprocess to finish
exit_status =. 2!:3 pid1!:1, 1!:2, etc.The implementation modifies jsrc/xh.c with a new
jthostio function:
DF1(jthostio){
// Create pipes for bidirectional communication
pipe(fi); // stdin pipe: J writes to fi[1], child reads fi[0]
pipe(fo); // stdout pipe: child writes to fo[1], J reads fo[0]
switch(fork()) {
case 0: // Child process
dup2(fi[0], STDIN_FILENO); // Redirect stdin
dup2(fo[1], STDOUT_FILENO); // Redirect stdout
execl("/bin/sh", "-c", command, NULL);
default: // Parent process
fin = fdopen(fi[1], "w"); // Write to child's stdin
fout = fdopen(fo[0], "r"); // Read from child's stdout
// Line buffered output, unbuffered input for real-time behavior
setvbuf(fin, NULL, _IOLBF, 0);
setvbuf(fout, NULL, _IONBF, 0);
// Add to J's file table...
}
}| Direction | Mode | Reason |
|---|---|---|
| J → Child | Line buffered (_IOLBF) |
Commands are typically line-based; flush on newline ensures timely delivery |
| Child → J | Unbuffered (_IONBF) |
J should see output immediately as the child produces it |
2!:3 (jtjwait): Wait for a subprocess
to exit and get its exit statusNB. Interactive session with Python
py =. 2!:2 'python3 -u' NB. -u for unbuffered Python output
'pid stdin stdout' =. py
NB. Define a function in Python
'def greet(name): return f"Hello, {name}!"\n' 1!:2 stdin
NB. Call it
'print(greet("J"))\n' 1!:2 stdin
NB. Read the response
response =. 1!:14 stdout NB. Use 1!:14 for line-trimmed read
echo response NB. "Hello, J!"
NB. Clean up
'exit()\n' 1!:2 stdin
status =. 2!:3 pid| Platform | Status |
|---|---|
| Linux | Supported |
| FreeBSD | Supported |
| macOS | Supported |
| Windows | Not implemented (returns domain error) |
cd /path/to/jsource
git apply host-io-2_2.patch