How to show error message from eval in Scheme? - scheme

I'm trying to create code that evaluates expression and return error as string for error:
(cond-expand
(gambit)
(gauche)
(kawa)
(guile
(import (rnrs base)
(rnrs exceptions)
(rnrs conditions))
(define (error-object-message cond)
(condition-message cond))))
(define (evaluate expr env)
(call-with-current-continuation
(lambda (exit)
(with-exception-handler
(lambda (e)
(exit (error-object-message e)))
(lambda ()
(eval expr env))))))
;; trigger error
(display (evaluate 'xxx (interaction-environment)))
(newline)
I've got
Guile message Unbound variable: ~S how to get actual error message and not a template?
Kawa exception: Argument #1 'unbound location: xxx' to 'error-object-message' has wrong type (gnu.mapping.UnboundLocationException) (gnu.mapping.UnboundLocationException cannot be cast to kawa.lang.NamedException)
Gauche core dump
Gambit freezes
NOTE: this is part of REPL that I'm testing in all Scheme implementations that I have on my system. It almost work, it can run itself, but I would like to show proper error message when exception happen, instead of exiting the REPL.

The reason you get an infinite loop with Gambit is that the variable xxx is unbound so the exception handler (lambda (e) (exit (error-object-message e))) is called with an unbound-global-exception object and this causes error-object-message to be called but the parameter is not an error-object (which is specific to the exceptions raised by a call to the error procedure) so this raises a type-exception object that causes the same exception handler to be called, and so on forever.
If you want an exception handling that "pops" the current exception handler, use with-exception-catcher instead of with-exception-handler. This will avoid the infinite loop.
Converting an exception object to a string can be done in Gambit this way:
(define (exception->string exc)
(with-output-to-string
(lambda ()
(display-exception exc))))
It works for error-objects and other kinds of exceptions, and also any non-exception object.
This is a more portable solution (superficially tested):
(import (scheme base)
(scheme r5rs))
(cond-expand
((or lips kawa gauche)
(define (exception->string exc)
(error-object-message exc)))
(gambit
(define (exception->string exc)
(with-output-to-string
(lambda ()
(display-exception exc)))))
(guile
(import (rnrs base)
(rnrs exceptions)
(rnrs conditions))
(define (exception->string exc)
(condition-message exc))))
(define (evaluate expr env)
(call-with-current-continuation
(lambda (exit)
(with-exception-handler
(lambda (e)
(exit (exception->string e)))
(lambda ()
(eval expr env))))))
(display (evaluate 'xxx (interaction-environment)))
(newline)

Gauche core dump
Oops. It's not ideal, for sure, but it can be explained.
By default, Gauche's with-exception-handler is SRFI-18's, not R7RS's, because of a historical reason. That means the exception handler is called in the dynamic environment where the exception occurs, including exception handler settings. If an exception occurs within the exception handler, the same exception handler is invoked, causing unbounded recursion. Apparently Gauche's runtime eats up C stack or something.
error-object-message is not defined in Gauche's default namespace. So that triggers an exception in the first place.
Add
(import (scheme base) (scheme write) (scheme r5rs))
at the beginning of code makes the program run in R7RS bindings. Then you'll get:
unbound variable: xxx
Actually, your code is not a valid R7RS program (which should begin with at least one import declaration), so anything can happen, depending on the default interpretation of the non-conforming code in the implementation.
[Edit] IMHO, with-exception-handler should be considered as the lowest level construct on which easy-to-use utilities are built, and thus should be used with extra care. In general use case, guard provides a good abstraction.

For Kawa:
(define (exception->string exc)
(call-with-port (open-output-string)
(lambda (port)
(display exc port)
(get-output-string port)))))
This will convert exception to string and get error message

Related

edebug-trace ceased to exist

In Emacs 25.2, suddenly the variable edebug-trace ceased to exist. When I set it with setq, it has no effect (the trace buffer does not appear). What could have happened and how can I fix it?
In the meanwhile, is there another way to know which function gets called when I click on an org-mode link
You could use trace.el to trace all org functions like so (I suggest not evaluating this until you're ready to click the link).
(mapatoms
(lambda (sym)
(and (fboundp sym)
(string-prefix-p "org-" (symbol-name sym))
(trace-function-foreground sym))))
Afterwards, you can remove the traces with:
M-x untrace-all RET
Edit: We could also convert that into a command ala elp-instrument-package:
(defun my-trace-package (prefix)
"Trace all functions which start with PREFIX.
For example, to trace all ELP functions, do the following:
\\[my-trace-package] RET elp- RET"
(interactive ;; derived from `elp-instrument-package'.
(list (completing-read "Prefix of package to trace: "
obarray 'my-traceable-p)))
(if (zerop (length prefix))
(error "Tracing all Emacs functions would render Emacs unusable"))
(mapc (lambda (name)
(trace-function-foreground (intern name)))
(all-completions prefix obarray 'my-traceable-p))
(message "Use %s to cease tracing."
(substitute-command-keys "\\[untrace-all]")))
(defun my-traceable-p (fun)
"Predicate for `my-trace-package'."
(or (functionp fun) (macrop fun)))

How to display results in a dedicated buffer?

If my current buffer is foo, and I run C-x C-b (aka list-buffers), my Emacs window splits in two, with foo occupying one of the two resulting windows, and a dedicated *Buffer List* buffer occupying the other one. At the end of this operation, foo remains the active buffer, and point remains were it was before C-x C-b was executed.
I want to write an interactive function that displays a multi-page output in a similar way: split window if necessary, bring up a dedicated buffer, leave the active buffer as it was before the function was run.
The best I've managed to do is a function with the following structure:
(defun my-func ()
(interactive)
(let ((this-buffer (current-buffer))
(other-buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(switch-to-buffer-other-window other-buffer)
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(beginning-of-buffer)
(switch-to-buffer-other-window this-buffer)))
This works, more or less, but I thought that Emacs already had built-in syntax to streamline such code.
IOW, I thought there was a special form analogous to the (fictional) WITH-BUFFER-OTHER-WINDOW in the snippet below:
(defun my-func ()
(interactive)
(let ((other-buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(WITH-BUFFER-OTHER-WINDOW other-buffer
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(beginning-of-buffer))))
or maybe even
(defun my-func ()
(interactive)
(let ((other-buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(WITH-BUFFER-OTHER-WINDOW other-buffer
(compute-pages-and-pages-of-stuff))))
I've tried forms like save-excursion and save-current-buffer, but they don't reproduce the desired behavior.
Is there a built-in way to carry out the operation described above?
This is the shortest you can get by leveraging the built-ins display-buffer and with-current-buffer:
(defun my-func ()
(interactive)
(let ((buffer (get-buffer-create "*my-func's Dedicated Buffer*")))
(with-current-buffer buffer
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(goto-char (point-min)))
(display-buffer buffer)))
If you use this pattern so much that it starts annoying you, feel free to define a helper macro:
(defmacro my-setup-and-display-buffer (name &rest body)
(declare (indent 1))
(let ((buffer (make-symbol "buffer")))
`(let ((,buffer (get-buffer-create ,name)))
(with-current-buffer ,buffer
,#body)
(display-buffer ,buffer))))
(my-setup-and-display-buffer "*my-func's Dedicated Buffer*"
(erase-buffer)
(insert (compute-pages-and-pages-of-stuff))
(goto-char (point-min)))

Elisp/texi2dvi: How to call texi2dvi from Emacs?

I try to write a function based on the code from: Latex, Emacs: automatically open *TeX Help* buffer on error and close it after correction of the error?
I would like to replace latexmk by texi2dvi, but TeX-master-file does not contain the file ending .tex (which seems to be required for texi2dvi). I found out that one can add .tex by using TeX-master-file t. However, I can't make it work (I'm not an elisp programmer). Here is what I tried:
;; texi2dvi
(defun run-texi2dvi ()
(interactive)
(let ((TeX-save-query nil)
(TeX-process-asynchronous nil)
(master-file (expand-file-name (TeX-master-file t)))); append `.tex`
(TeX-save-document "")
(TeX-run-TeX "texi2dvi"
(TeX-command-expand "PDFLATEX='pdflatex -synctex=1' texi2dvi -p %s" 'TeX-master-file)
master-file)
(if (plist-get TeX-error-report-switches (intern master-file))
(TeX-next-error t)
(progn
(demolish-tex-help)
(minibuffer-message "texi2dvi: done.")))))
No clue if there's a better way to do it, but this version should work. Basically, TeX-command-expand was given the function TeX-master-file as a symbol which was called internally, and there it was called without the I-want-the-extension argument. The replacing lambda forces that.
(defun run-texi2dvi ()
(interactive)
(let ((TeX-save-query nil)
(TeX-process-asynchronous nil)
(master-file (expand-file-name (TeX-master-file t)))); append `.tex`
(TeX-save-document "")
(TeX-run-TeX "texi2dvi"
(TeX-command-expand
"PDFLATEX='pdflatex -synctex=1' texi2dvi -p %s"
(lambda (ext-ignored nondir)
(TeX-master-file t nondir)))
master-file)
(if (plist-get TeX-error-report-switches (intern master-file))
(TeX-next-error t)
(progn
(demolish-tex-help)
(minibuffer-message "texi2dvi: done.")))))
See here for a more detailed description of the issue and a simple workaround: https://tex.stackexchange.com/questions/67244/how-to-set-up-texi2dvi-with-synctex-and-error-handling/67384#67384

How to pass arguments to saved SBCL core?

I have a Lisp (SBCL 1.0.40.0.debian) application (myfitnessdata), which uses the following code to process command line arguments:
(:use :common-lisp)
(:export #:main))
(in-package :myfitnessdata)
(require :sb-posix)
;; snip
(defun main ()
(if (= (length sb-ext:*posix-argv*) 3)
(let ((username (nth 0 sb-ext:*posix-argv*))
(password (nth 1 sb-ext:*posix-argv*))
(path (nth 2 sb-ext:*posix-argv*)))
(scrape (username password path)))
(show-usage)))
I am compiling this application using the following Lisp code:
(load "myfitnessdata.lisp")
(save-lisp-and-die "myfitnessdata.bin" :executable t :toplevel 'myfitnessdata:main)
This produces an executable that I can run. However, the sb-ext:*posix-argv* list is always empty. If I run the following:
./myfitnessdata.bin myusername mypassword /home/me/data
... then all I get is the usage instructions produced by (show-usage).
I think I must be missing something simple again - could someone please let me know how to (save-lisp-and-die) such that the resultant executable takes command line arguments?
The solution, as suggested by the good folks on sbcl-help, is to use a tool like buildapp to compile the app. You can specify an entry point, which is assumed to be a function with one argument. At run-time, that function is called with a list of command-line parameters.
Using buildapp, my main function is now:
(defun main (args)
(if (= (length args) 4)
(let ((username (nth 1 args))
(password (nth 2 args))
(path (nth 3 args)))
(scrape username password path))
(show-usage)))

Racket URL dispatch

I'm trying to hook up URL dispatch with Racket (formerly PLT Scheme). I've taken a look at the tutorial and the server documentation. I can't figure out how to route requests to the same servlets.
Specific example:
#lang scheme
(require web-server/servlet)
(require web-server/dispatch)
(provide/contract (start (request? . -> . response/c)))
(define (start request)
(blog-dispatch request))
(define-values (blog-dispatch blog-url)
(dispatch-rules
(("") list-posts)
(("posts" (string-arg)) review-post)
(("archive" (integer-arg) (integer-arg)) review-archive)
(else list-posts)))
(define (list-posts req) `(list-posts))
(define (review-post req p) `(review-post ,p))
(define (review-archive req y m) `(review-archive ,y ,m))
(require web-server/servlet-env)
(serve/servlet start
#:launch-browser? #t
#:quit? #f
#:listen-ip #f
#:port 8080
#:extra-files-paths (list (build-path "js")
(build-path "css"))
#:servlet-path "")
Assuming the above code, localhost:8080/ goes to a page that says "list-posts". Going to localhost:8080/posts/test goes to a Racket "file not found" page (I'd expect it to go to a page that says "review-post test").
It feels like I'm missing something small and obvious. Can anyone give me a hint?
What you've written is not a whole program, so I cannot debug it.
Here is a program with annotations that does what you want, probably:
#lang scheme ; specify the right language
; include the correct libraries
(require web-server/servlet
; this one gets "serve/servlet"
web-server/servlet-env)
(define (start request)
(blog-dispatch request))
(define-values (blog-dispatch blog-url)
(dispatch-rules
(("") list-posts)
(("posts" (string-arg)) review-post)
(("archive" (integer-arg) (integer-arg)) review-archive)
(else list-posts)))
(define (list-posts req) `(list-posts))
(define (review-post req p) `(review-post ,p))
(define (review-archive req y m) `(review-archive ,y ,m))
; starts a web server where...
(serve/servlet start ; answers requests
#:servlet-path "" ; is the default URL
#:port 8080 ; is the port
#:servlet-regexp #rx"") ; is a regexp decide
; if 'start' should
; handle the request
Because the functions list-posts, review-post, and review-archive don't return sensible xexpr encodings of HTML, you'll have to view source to see them right.
Please feel free to email me directly or email the PLT Scheme mailing list. (Note: We are renaming PLT Scheme to "Racket" so you may see that when you post.)
Jay McCarthy

Resources