Using trace in Typed Racket - scheme

I'm having difficulty getting the trace module set up when using Typed Racket - my attempt is the following in a REPL:
#lang typed/racket
(require/typed racket/trace
[trace (Symbol * -> Void)])
(define (add-four [num : Number])
(+ 4 num))
(trace add-four)
(add-four 3)
This is from following along the trace and type annotation docs, but I'm getting the error trace: bad syntax in: trace in the trace type annotation when importing - not sure where I've gone wrong!

Related

How to show error message from eval in 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

"Module not found" in Guile

I'm writing an extension script on Guile for "Gnubik" program and get "module not found" error when try to use a function "get-string-all" from "textual-ports" module: when I start Gnubik from the command line, the error text is printed and the program doesn't start. When this function is used in a Guile shell script - this problem doesn't happen. I have two Guile packages installed: 2.0 and 2.2.
The error text is following:
Backtrace:
In ice-9/boot-9.scm:
160: 10 [catch #t #<catch-closure c86380> ...]
In unknown file:
?: 9 [apply-smob/1 #<catch-closure c86380>]
In ice-9/eval.scm:
505: 8 [#<procedure b5e540 at ice-9/eval.scm:499:4 (exp)> (use-modules #)]
In ice-9/psyntax.scm:
1107: 7 [expand-top-sequence ((use-modules (ice-9 textual-ports))) () ...]
990: 6 [scan ((use-modules (ice-9 textual-ports))) () ...]
279: 5 [scan ((# #) #(syntax-object *unspecified* # #)) () (()) ...]
In ice-9/boot-9.scm:
3622: 4 [process-use-modules (((ice-9 textual-ports)))]
712: 3 [map #<procedure c1ab40 at ice-9/boot-9.scm:3622:25 (mif-args)> ((#))]
3623: 2 [#<procedure c1ab40 at ice-9/boot-9.scm:3622:25 (mif-args)> (#)]
2903: 1 [resolve-interface (ice-9 textual-ports) #:select ...]
In unknown file:
?: 0 [scm-error misc-error #f ...]
ERROR: In procedure scm-error:
ERROR: no code for module (ice-9 textual-ports)
The Guile code:
(use-modules (ice-9 textual-ports))
(call-with-input-file "/tmp/tst.txt"
(lambda (port)
(define s (get-string-all port))))
How this problem can be corrected?
According to the documentation '(use-modules (rnrs io ports))'.
Works for me.
Edit: On looking at guile-2.0, I see that get-string-all is provided by the '(rnrs io ports)' module, but in guile-2.2 it is provided by both the '(rnrs io ports)' and '(ice-9 textual-ports)' modules.
So there were two problems. First you were trying to load '(ice-9 textual-ports)' module in guile-2.0, which won't work because it is only provided by guile-2.2. Secondly, there was no expression in your lambda form, which just needed to return the value of the application of get-string-all.

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)))

js/console.log in ClojureScript

I want to implement a function with ClojureScript to simplify js/console.log like this:
(defn log [& args]
(apply js/console.log args))
Calling it : (log "foo" "bar")
throws: TypeError: Illegal invocation
but this works : (js/console.log "foo" "bar")
What is the problem ?
js/something is for accessing a js object, but you shouldnt nest dots after that, since it is not clojure compatible syntax and it was going to be removed. In older versions of the compiler (2138) your code works, but it is possible that it has been deprecated in newer versions of the compiler. Which version are you using?
The correct way would be using straightforward js interop like this: [Caveat: see comment below from David Nolen, ClojureScript lead developer]
(defn log [& args] (apply (.-log js/console) args))
And even shorter, since console.log is already variadic (just make an alias):
(def log (.-log js/console))
You can also just use println if you first put this at top of your file: (enable-console-print!).
And pprint has been ported:
:require [cljs.pprint :refer [pprint]]
I found the actual answer
(.apply (.-log js/console) js/console (clj->js args))
Here is a working code for your function (tested with [org.clojure/clojurescript "1.7.228"]):
; working
(defn log [& args]
(.apply js/console.log js/console (to-array args)))
; not working
; (defn log [& args] (apply (.-log js/console) args))
; (defn log [& args] (apply js/console.log args))
; (def log js/console.log)
Here is an article that describes why (apply...) is not playing well with JS functions.
http://clojurescriptmadeeasy.com/blog/how-to-apply-with-the-console-api.html
With console.log makes sense to use a macro instead of a function. If you implement log as a function all the messages will be logged with the line number of where your log function is defined.
A macro solves this problem by generating inline code during compilation, it's important to understand that macros run at compile time.
Define this macro in macros.cljc:
(ns test.macros)
(defmacro log
[& msgs]
`(.log js/console ~#msgs))
`: is like ' or quote but:
Symbols are auto-resolved to include their namespace, preventing ambiguous symbols at the time of evaluation.
Evaluated forms can be inserted using ~ or unquote, as i did for msgs adding # to unpack multiple arguments: ~#msgs. More info about syntax quote.
Then call it from core.cljs:
(ns test.core
(:require-macros [test.macros :refer [log]]))
(log "foo" "bar")

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