ocaml-jupyter
ocaml-jupyter copied to clipboard
No standard input/output
No printing occurs with print_string
, print_int
, and so on:

I would expect an output like under the OCaml REPL:

Is this a known limitation, or am I doing something wrong ? In the first case, is there any workaround?
Thanks!
Hello there,
I'm not sure if it's a known bug to the authors of ocaml-jupyter, but I did encounter it many times.
Have you tried to also use flush_all()
(from Pervasives
module, see documentation)?
Or Printf.printf
See these two examples:
It's quite weird, but print_endline
forces a flush of the output.
Thanks for this neat workaround. So, if I understand correctly:
-
print_endline s
immediately printss
. -
flush_all()
prints all the characters of the buffer before the\n
character.

@laowantong yes it appears to be the behavior of jupyter-ocaml.
By chance, do you know such a workaround for read_line()
?

No, I honestly never used interactive inputs from any OCaml programs! Sorry
No problem, thanks again for your kind answer!
@Naereen Thank you for your answers.
@laowantong read_line
cannot be used on jupyter because it's not a console. Please use Jupyter_comm.Stdin.read_line
as follows:
https://akabe.github.io/ocaml-jupyter/api/jupyter/Jupyter_comm/Stdin/index.html
Could it be possible for OCaml-jupyter kernel to patch such functions, like read_line
, which are known to be unsupported functions in Jupyter environment?
It would be helpful to at least print a message saying
Warning: read_line is unsupported on Jupyter, please use [solution]
I actually don't know if OCaml-jupyter kernel has the ability to load a custom .ocamlinit
file? (see man ocaml
)
INITIALIZATION When ocaml(1) is invoked, it will read phrases from an initialization file before giving control to the user. The default file is .ocamlinit in the current directory if it exists, otherwise .ocamlinit in the user's home directory. You can specify a different initialization file by using the -init file option, and disable initialization files by using the -noinit option.
Could it be possible for OCaml-jupyter kernel to patch such functions, like read_line, which are known to be unsupported functions in Jupyter environment?
I have no idea.
I actually don't know if OCaml-jupyter kernel has the ability to load a custom .ocamlinit file? (see man ocaml)
You can specify a custom .ocamlinit file at $(opam config var share)/jupyter/kernel.json
generated by ocaml-jupyter-opam-genspec
command.
$ cat $(opam config var share)/jupyter/kernel.json
{
"display_name": "OCaml default",
"language": "OCaml",
"argv": [
"/bin/sh",
"-c",
"eval $(opam config env --switch=default) && /Users/aabe/.opam/default/bin/ocaml-jupyter-kernel \"$@\"",
"ocaml-jupyter-kernel",
"-init", "/Users/aabe/.ocamlinit",
"--merlin", "/Users/aabe/.opam/default/bin/ocamlmerlin",
"--verbosity", "app",
"--connection-file", "{connection_file}"
]
}
Re-run jupyter kernelspec install [ --user ] --name ocaml-jupyter "$(opam var share)/jupyter"
after editing a value for -init
option.
Awesome! Thank you @akabe for this workaround which works perfectly. I use Jupyter Notebook as an interactive environment in my FP course, and these IO functions are a must for programming games.
@laowantong, great if that solves the issue for you.
But are you really planning to develop a game from Jupyter notebook? Using this Jupyter_comm.Stdin.read_line
for a game will imply that the game cannot be played outside of Jupyter.
Have you had a look at https://github.com/mahsu/MariOCaml ? It's compiled to Javascript using js_of_ocaml (standard tool, it also provided the compiler interpreter at https://betterocaml.ml/editor/ or https://try.ocamlpro.com/. The MariOCaml shows what can be done in pure OCaml when you know the game frontend will be a HTML canvas.
@Naereen In fact, I do not call directly this function, but define a mutable variable with a default of:
let read = ref read_line;
This works under console. Under Jupyter Notebook, I mutate it:
read := (function () -> Jupyter_comm.Stdin.read_line "")
And for the tests, I use a stream:
read := (let x = Stream.of_list ["-10"; "500"; "10"] in function () -> Stream.next x);
This is a simple text game (dominoes), nothing as fancy as Mario. Nevertheless, thanks for the links !
Interesting! I don't know if it's possible to dynamically detect if the code is running inside Jupyter or not...
In Python/IPython, it's easy:
import IPython
def is_in_notebook(): return IPython.get_ipython() is not None
If this is possible in OCaml, it could be used to automatically change your read
function.
You can check whether a repl is on jupyter or not, by:
Filename.basename Sys.argv.(0) = "ocaml-jupyter-kernel"
This is not perfect, but I think enough in practical cases.
Or you give the following .ocamlinit
file (different from one for a standard repl):
module Sys = struct
include Sys
let read () = () [@@ocaml.deprecated "Use Jupyter_comm.Stdin.read_line instead"]
end
I don't recommend replace Sys.read
with Jupyter_comm.Stdin.read_line
because they have different types.
Oh great for the hack on Filename.basename
, that's smart!
For the [@@ocaml.deprecated "..."]
hack, I saw that in recent versions of the OCaml codebase, but I guess it doesn't work on older versions, I'm under 4.05.0 here and it does nothing special...
To be able to #use "topfind"
, I had to first do let () = Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
My OCAML_TOPLEVEL_PATH
is /home/terence/.opam/default/lib/toplevel
.
I see the kernel.json exports this env by running (opam config env --switch=default --shell=sh)
.
Is it normal I still need to use the Topdirs.dir_directory function?