How do you halt in DrScheme's implementation of R5RS? - scheme

When using DrScheme with R5RS, there is no error function. I plan to write my own, but can't figure out how to halt the program execution. I tried commands such as:
(halt)
(exit)
(error)
and none worked. How do you halt program execution?

SLIB (the portable Scheme library) has an implementation of ERROR. You might want to either look at that, or use SLIB in your programs.
Other than that, one way to halt the program is simply to raise a different error! Try something like this (thanks to Stephen Houben):
(define (error reason . args)
(display "Error: ")
(display reason)
(for-each (lambda (arg)
(display " ")
(write arg))
args)
(newline)
(scheme-report-environment -1)) ;; we hope that this will signal an error
While this does raise a second (unrelated) error, it will surely halt program execution.

Is there a reason you need to use R5RS? Other language definitions in DrScheme define error and exit. For example, the (module ...) PLT language defines error and exit. Invoking mzscheme from the command line also gives you these definitions.
Note: I have DrScheme 372, which is pretty old. Things shouldn't have changed too much, though.

an ugly solution is to define abort to become a runtime error.
for example any of these should do the trick
(define abort "the program was aborted")
(define abort 123)
(define abort #f)
any call to abort
(abort)
should generate a runtime error, if your lucky even show the string , error code or whatever you care.

Related

Emacs: How to enable highlighting breakpoints in a text terminal (emacs -nw)

Emacs doesn't show breakpoints in text mode.
I tried integrating the suggestions here and here, but failed (I am not a lisp programmer).
I tried:
(require 'gdb-mi)
(setq default-text-properties '(foo 1111))
(defun set_breakpt_cmds ()
"set breakpoint and indicate on editor"
(interactive)
(gud-break)
(gdb-put-breakpoint-icon "false" (get-text-property 1 'foo)))
(global-set-key (kbd "<f12>") 'set_breakpt_cmds)
The resulting error is
Wrong number of arguments: (lambda (arg) "Set breakpoint at current line." (interactive "p") (if (not gud-running) (gud-call "dbstop \
at %l in %f" arg))), 0
Note: A similar issue is this (following this). However the solution there doesn't fit me because I would like to be able to call the fix from .emacs file. This way it is easier to duplicate my emacs configuration when I setup a new linux box.
Thanks
The error you get comes from the fact that gud-break expects an argument (which isn't used), so just use (gud-break 1).
The message reads as follow:
the error is of kind wrong number of arguments
when calling (lambda (arg) ...) (where we see that exactly one argument is expected)
and it was called with 0 arguments.

elisp parse output of asynchronous shell command

I have a simple elisp interactive function that I use to launch a Clojure repl.
(defun boot-repl ()
(interactive)
(shell-command "boot repl wait &"))
It opens an *Async Shell Command* buffer, and after a while the following text appears :
nREPL server started on port 59795 on host 127.0.0.1 - nrepl://127.0.0.1:59795
Implicit target dir is deprecated, please use
the target task instead. Set BOOT_EMIT_TARGET=no to disable implicit
target dir.
I would like to monitor the output of this command to be able to parse the port ("59795" in this example).
Even just the first line (in the case without warnings) would be alright.
This way I could be able to use another command to connect to the Clojure REPL waiting for me.
I cannot use shell-command-to-string as the command does not return and it blocks emacs forever (boot repl wait is supposed to last for my whole programming session, possibly more).
There may be something easy to do with cider also, but I haven't found it.
So, how do I parse the result of an asynchronous bash command in Elisp ?
Alternatively, how can I set-up Cider to launch this REPL for my and connect to it ?
To answer the question directly, you can definitely parse the output of an asyncronous shell command, using start-process and set-process-filter:
(let ((proc (start-process "find" "find" "find"
(expand-file-name "~") "-name" "*el")))
(set-process-filter proc (lambda (proc line)
(message "process output: %s" line))))
(Docs for filter function)
However, note that line above is not necessarily a line, and may include multiple lines or broken lines. Your filter is called whenever the process or emacs decides to flush some ouput:
...
/home/user/gopath/src/github.com/gongo/json-reformat/test/json-reformat-test.el
/home/user/gopath/src/github.com/gongo/json-reformat/test/test-
process output: helper.el
In your case, this could mean that your port number might be broken into two separate process-filter calls.
To fix this, we can introduce a line-buffering and line-splitting wrapper, which calls your filter for each process output line:
(defun process-filter-line-buffer (real-filter)
(let ((cum-string-sym (gensym "proc-filter-buff"))
(newline (string-to-char "\n"))
(string-indexof (lambda (string char start)
(loop for i from start below (length string)
thereis (and (eq char (aref string i))
i)))))
(set cum-string-sym "")
`(lambda (proc string)
(setf string (concat ,cum-string-sym string))
(let ((start 0) new-start)
(while (setf new-start
(funcall ,string-indexof string ,newline start))
;;does not include newline
(funcall ,real-filter proc (substring string start new-start))
(setf start (1+ new-start)));;past newline
(setf ,cum-string-sym (substring string start))))))
Then, you can safely expect your lines to be whole:
(let* ((test-output "\nREPL server started on port 59795 on host 127.0.0.1 - \nrepl://127.0.0.1:59795 Implicit target dir is deprecated, please use the target task instead. Set BOOT_EMIT_TARGET=no to disable implicit target dir.")
(proc (start-process "echo-test" "echo-test" "echo" test-output)))
(set-process-filter proc (process-filter-line-buffer
(lambda (proc line)
(when (string-match
"REPL server started on port \\([0-9]+\\)"
line)
(let ((port (match-string 1 line)))
;;take whatever action here with PORT
(message "port found: %s" port)))))))
Finally, I'm not familiar with cider but this kind of low-level work probably belongs in an inferior-type mode and has probably already been solved.
shell-command
allows to name optional output- and error-buffers. Than the error should appear inside the latter and not clutter the output any more.
A better answer to the other one I provided is to simply use cider as you suggested:
(progn
(package-refresh-contents)
(package-install 'cider)
(cider-jack-in))

Why this scheme code can't resolve the first one of spoj?

The problem is here: http://www.spoj.com/problems/TEST/
And my scheme solution is:
(define (main)
(let ((line (read-line)))
(if (or
(eof-object? line)
(string=? line "42"))
(void)
(begin
(display line)
(newline)
(main)))))
(main)
It reports
runtime error (NZEC)
But I don't know why it's wrong.
You should install guile and try your code before you submit. Guile doesn't have read-line available by default. You need to add this as first line:
(use-modules (ice-9 rdelim))
So what happens is that guile post an error and return a non zero value back to the parent process, which in turns indicated the program did not terminate normally. SPOJ will then report is as NZEC.
The guile error looks like this:
sylwester#sylhp ~> guile test.scm
ERROR: Unbound variable: read-line
Whenever you get NZEC you should try to run it locally to find errors.

Scheme: Proper application of the eval function?

at work I encountered a basic problem when trying to implement a configuration script with Scheme. To avoid the need of inventing an artificial and restricted language the script should contain actual code. This code shall be evaluated later on. To make the configuration work as desired it has to have access to certain variables. These variables are only known in the context of the evaluation. Therefore the configuration script has to be evaluated in the current environment. Here is a primitive example of what I am talking about:
(let ((a #t))
(wr "a is ..."
(eval '(if a "true" "false"))))
When running this code I'd always get an error message telling me that the variable 'a' is unknown. So the question is: Do you know how to evaluate frozen code inside the current environment?
P.S.: I use the bigloo compiler.
/////////////////////////////////////////////
EDIT: //////////////////////////////////////////////////////
When using the approach suggested by Chris I came to another interesting problem, the usage of the case keyword. The following two examples both use the same case construction which should trigger the output of a "yes!" line. Unfortunately they behave differently.
Usual -> output is "yes!" as expected:
(define testit "test")
(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
With eval -> output is surprisingly "no":
(define env (null-environment 5))
(eval '(define testit "test") env)
(eval '(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
Does that make any sense?
eval cannot access lexical variables, such as those defined using let.
Instead, you have to create an environment, and populate it with the variables you want to make available. For example:
(define env (null-environment 5))
(eval '(define a #t) env)
(wr "a is ..."
(eval '(if a "true" "false") env))
To answer your edit, you aren't passing env as an argument to the last eval. testit doesn't exist in the environment that eval creates if that argument isn't given.
That may be a typo, but if not, that's your problem.

When does format actually print in Common Lisp?

I have the following Common Lisp code:
(defun micro-read-eval-print ()
(format t "Micro > ")
(let ((form (read-line)))))
When I run it, I get the following:
CL-USER> (micro-read-eval-print)
(m-quote a)
Micro > NIL
Note that I typed in "(m-quote a)", while the Lisp interpreter output "Micro > NIL".
Now, I would have expected these events to happen in the reverse order. I would have expected "Micro > " to have been printed first since the format statement comes first. Why isn't it printed first? And what do I have to do to make sure it is printed first?
Try adding
(defun micro-read-eval-print ()
(format t "Micro > ")
(finish-output)
(let ((form (read-line)))))
I believe you are encountering the buffering of standard io (stdio) which, in C, is commonly bypassed via fflush() in that language.
finish-output appears to be the Common Lisp equivalent of C standard library's fflush.

Resources