2

Using org source blocks with OCaml, I get a blank resulting output with that code :

#+BEGIN_SRC ocaml :results output
print_string "hello"
#+END_SRC

#+RESULTS:

And without the :results value parameter :

#+RESULTS:
: () 

How to catch the output of OCaml in org source blocks ?

Edit : My init parts about ocaml

(use-package utop
  :ensure t)

(use-package merlin
  :ensure
  :config
  ;; Add opam emacs directory to the load-path
  (setq opam-share (substring (shell-command-to-string "opam config var share 2> /dev/null") 0 -1))
  (add-to-list 'load-path (concat opam-share "/emacs/site-lisp"))
  ;; Load merlin-mode
  (require 'merlin)
  ;; Start merlin on ocaml files
  (add-hook 'tuareg-mode-hook 'merlin-mode t)
  (add-hook 'caml-mode-hook 'merlin-mode t)
  ;; Make company aware of merlin
  (with-eval-after-load 'company
    (add-to-list 'company-backends 'merlin-company-backend))
  ;; Enable company on merlin managed buffers
  (add-hook 'merlin-mode-hook 'company-mode)
  ;; Or enable it globally:
                    ;(add-hook 'after-init-hook 'global-company-mode)

  ;; Use opam switch to lookup ocamlmerlin binary
  (setq merlin-command 'opam)
;;  (define-key tuareg-mode-map (kbd "C-c M-s") ')
  ;;;###autoload
  (defun tuareg-run-metaocaml ()
    "Run an OCaml toplevel process.  I/O via buffer `*ocaml-toplevel*'."
    (interactive)
    (tuareg-run-process-if-needed
     "/usr/bin/opam config exec -- metaocaml")
    (display-buffer tuareg-interactive-buffer-name))

  (add-hook 'tuareg-mode-hook
        ' (lambda ()
              (define-key tuareg-mode-map (kbd "C-c M-s")
            'tuareg-run-metaocaml)))

  (setq tuareg-interactive-program "/usr/local/bin/opam config -- exec metaocaml")
  ;;(setq merlin-use-auto-complete-mode t)
  ;;(setq merlin-error-after-save nil)
  )

(use-package tuareg
  :ensure t
  :config
  (setq auto-mode-alist (cons '("\\.ml\\w?" . tuareg-mode) auto-mode-alist))
  (autoload 'tuareg-mode "tuareg" "Mode majeur pour éditer du code Caml" t)
  (autoload 'camldebug "camldebug" "Exécuter le débogueur Caml" t) 
  (when (string= (getenv "MY_EMACS_DAEMON") "ocaml")
    (load-file "~/.emacs.d/elisp/daemon/my-tuareg-daemon.el"))
  ;; Setup environment variables using opam
  (dolist (var (car (read-from-string (shell-command-to-string "opam config env --sexp"))))
    (setenv (car var) (cadr var)))
  ;; Update the emacs path
  (setq exec-path (append (parse-colon-path (getenv "PATH"))
                        (list exec-directory)))
  ;; Update the emacs load path
  (add-to-list 'load-path (expand-file-name "../../share/emacs/site-lisp"
                        (getenv "OCAML_TOPLEVEL_PATH")))
  ;; utop top level
  (autoload 'utop "utop" "Toplevel for OCaml" t)
  (autoload 'utop-minor-mode "utop" "Minor mode for utop" t)
  (add-hook 'tuareg-mode-hook 'utop-minor-mode)
  )

I tried without utop but output remained the same.

erikstokes
  • 12,686
  • 2
  • 34
  • 56
  • [Here's](http://emacs.stackexchange.com/questions/17926/python-org-mode-source-block-output-is-always-none/17928#17928) a similar question with python, the answers have several suggestions. – user2699 Jan 18 '16 at 21:10
  • Try starting emacs with the `-Q` option, running `M-x package-initialize`, and adding `ocaml` to the list of `org-babel-load-languages`. This should give you a minimal setup to evaluate your org-src block. If you still don't get the results you expect, than maybe it has to do with the defaults of an installed package. If it does work this way, then you can try bisecting your init file to norrow down what accounts for the difference – elethan Jan 18 '16 at 21:45

3 Answers3

2

Apparently if a line is not properly (newline-) terminated it is ignored in output. The following example shows it:

#+BEGIN_SRC ocaml :results output
print_string "hello\nagain"
#+END_SRC

#+RESULTS:
: hello

I would tend to call this a bug since the documentation says (emphasis mine):

14.9.1.2 ‘:results output’

The code is passed to the interpreter as an external process, and the contents of the standard output stream are returned as text. (In certain languages this also contains the error output stream; this is an area for future work.)

However, see an interesting loosely related discussion on unix SE:

A text file, under unix, consists of a series of lines, each of which ends with a newline character (\n). A file that is not empty and does not end with a newline is therefore not a text file.

JeanPierre
  • 7,323
  • 1
  • 18
  • 37
1

You can try adding ocaml to the list of org-babel-load-languages with M-x customize-variable org-babel-load-languages, inserting a new value with INS, and then selecting Ocaml from the list.

Or you can define the list in your init file. Here is mine (plus Ocaml just for testing):

(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)
   (sh . t)
   (ocaml . t)
))

With this configuration I get the following results when I execute your example block with C-c C-c in the block:

#+BEGIN_SRC ocaml :results output
print_string "hello"
#+END_SRC

#+RESULTS:
: ()

With :results value:

#+BEGIN_SRC ocaml :results value
print_string "hello"
#+END_SRC

#+RESULTS:
: hello- : unit = ()

Also, you may find this resource helpful if you haven't seen it already.

elethan
  • 4,755
  • 3
  • 29
  • 56
  • Thanks but I already have it, that's why I get `()` when the results is set to `value` ( `()` means unit in OCaml, it is the type returned by side effects functions (and much more)). – Nicolas Scotto Di Perto Jan 18 '16 at 20:09
  • @NicolasScottoDiPerto I have updated my answer a little bit. What is the output that you are expecting? "hello"? – elethan Jan 18 '16 at 20:23
  • Yes, "hello", like the one one you get in your second example. It is bizarre, I expected the second example to results what's in the first... However for me `:results value` results in `: ()` and `:results output` in a blank result. I have tried `:results output` just after reading the same document you've shared, it says that `:result output` prints the `STDOUT` of the executed code block. – Nicolas Scotto Di Perto Jan 18 '16 at 21:20
  • @NicolasScottoDiPerto, that is bizarre. I suspect that you have some OCaml or related configuration in your init file that I don't have that might explain the difference, but I am not sure what... – elethan Jan 18 '16 at 21:26
  • I've added my emacs init code about OCaml, I have tried to disable utop but output was still the same... – Nicolas Scotto Di Perto Jan 18 '16 at 21:35
  • @NicolasScottoDiPerto, nothing jumps out at me as a possible cause, but I don't work with OCaml so it is hard for me to tell. – elethan Jan 18 '16 at 21:48
  • No problem. I hope someone will have a solution because I am not sure to be able to solve it by myself and I love this language ! But still thank you :) – Nicolas Scotto Di Perto Jan 18 '16 at 22:02
0

I tried :results verbatim (interchangeable with :results raw) and got this

#+begin_src ocaml :results verbatim
open List
let res = map (fun x -> x+1) [1;2]
#+end_src

#+RESULTS:
: val res : int list = [2; 3]


#+begin_src ocaml :results verbatim
1 + 2 * 3
#+end_src

#+RESULTS:
: - : int = 7

#+begin_src ocaml :results verbatim
print_string "hello"
#+end_src

#+RESULTS:
: hello- : unit = ()

#+begin_src ocaml :results raw
1 + true
#+end_src

#+RESULTS:
Line 1, characters 4-8:
1 | 1 + true;;
        ^^^^
Error: This expression has type bool but an expression was expected of type
         int

These results are pretty much what my Ocaml 4.11.1 REPL is giving. Also, I'm using the opam-user-setup.el and org-mode version 9.4 on Emacs 27.1. Do

opam user-setup install

and it will append opam-user-setup.el to your .emacs.d/init.el file. Move to suit.

147pm
  • 2,907
  • 1
  • 18
  • 39