ClojureScript REPL in emacs printing out extra ^Ms and nils - emacs

I'm a ClojureScript newbie using emacs, cider, cljsbuild, and austin with slimerjs on a Windows machine. I've noted that sometimes when I type into the clojurescript repl, an extra ^M character and nil are appended to the output (but the return value is not nil, as indicated by the output of the repl enclosed below). The output before the ^M is colored red, while the nil output is black. What could be causing this, and how can I fix this? (Should I be reporting this as an issue to one of the project's trackers?)
cljs.user> 1
1
cljs.user> true
true
cljs.user> (reduce + [1 2 3])
6
cljs.user> (list [1 2 3])
([1 2 3])
cljs.user> reduce
#<function (a,e,f){switch(arguments.length){case 2:return b.call(this,
a,e);case 3:return c.call(this,a,e,f)}throw Error("Invalid arity: "+arguments.length);}>^M
nil
cljs.user> js/document
#<[object HTMLDocument]>^M
nil
cljs.user> (def d js/document)
#<[object HTMLDocument]>^M
nil
cljs.user> (nil? d)
false

^M is windows line ending. Answer how ho hide it in Emacs can be found here.
Printing of nil in general is normal behaviour and it's not specific to Clojurescript or Emacs. All forms return a value (which may be nil) and also may produce side-effects:
cljs.user> (println 1)
1 ; Side effect - printed value
nil ; Result of evaluation
However returning nil for js/document, (def d js/document) and similar "not-nil" forms is Austin specific behaviour and probably can be treated as minor bug.

Related

Navigating to the definitions of `defun` and `defmacro` with slime/swank

Emacs version: 26.3
Slime version: 2.26.1
I start up Emacs.
I open up a simple .lisp file.
(defun testfn (x y)
(+ x y))
(defmacro testmc (form)
form
`(list 1 2 3))
I place my cursor over the symbol defun and issue the keyboard-command M-. (slime-edit-definition).
This should bring me to the definition of defun.
But it doesn't.
It brings me here:
I place my cursor over the symbol defmacro and issue the keyboard-command M-. (slime-edit-definition).
This should bring me to the definition of defmacro.
But it doesn't.
It brings me here:
Why does it do this & how do I fix this
Notice there is a warning in the REPL when trying to find the source of DEFUN:
WARNING: inconsistent 2 form-number-translations
You can replicate it yourself in the REPL:
CL-USER> (let ((slynk::*buffer-package* (find-package :cl))
(slynk::*buffer-readtable* *readtable*))
(slynk:find-definitions-for-emacs "DEFUN"))
WARNING: inconsistent 2 form-number-translations
(("(DEFMACRO DEFUN)"
(:LOCATION (:FILE "/home/chris/data/src/sbcl/src/code/macros.lisp")
(:POSITION 4140)
(:SNIPPET "(setq doc nil)
(let* (;; stuff shared between LAMBDA and INLINE-LAMBDA and NAMED-LAMBDA
(lambda-guts `(,#decls (block ,(fun-name-block-name name) ,#forms)))
(lambda `(lambda ,lambda-list ,#lambda-guts))
(named-lambda `("))))
To find where the warning comes from, you could do as I did first and do a textual search on the repository, or you could use the following alternate method that works better, namely invoke the debugger on warnings:
(handler-bind ((warning (lambda (c) (invoke-debugger c))))
(let ((slynk::*buffer-package* (find-package :cl))
(slynk::*buffer-readtable* *readtable*))
(slynk:find-definitions-for-emacs "DEFUN")))
This comes from SLYNK-SBCL::FORM-NUMBER-POSITION, and the interesting value in the debugger is the source location obtained from SBCL:
#<SB-INTROSPECT:DEFINITION-SOURCE {10369C50F3}>
--------------------
The object is a STRUCTURE-OBJECT of type SB-INTROSPECT:DEFINITION-SOURCE.
PATHNAME: #P"SYS:SRC;CODE;MACROS.LISP"
FORM-PATH: (5)
FORM-NUMBER: 89
CHARACTER-OFFSET: 3917
FILE-WRITE-DATE: 3825178034
PLIST: NIL
DESCRIPTION: NIL
It says the source is the fifth toplevel form in the file (which corresponds to the character offset), and from here, the FORM-NUMBER is the 89th form in a depth-first search walk of the form (this comes from the structure's docstring).
But, if I recompile the function FORM-NUMBER-POSITION with DEBUG set to 3, the toplevel form read at this position, TLF is NIL:
1: (SLYNK-SBCL::FORM-NUMBER-POSITION #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL..
Locals:
DEFINITION-SOURCE = #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL :DESCRIPTION NIL)
FORM-NUMBER = 89
PATH-TABLE = #((0 0))
POS-MAP = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
POS-MAP#1 = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
STREAM = #<SB-IMPL::STRING-INPUT-STREAM {7F3E0350D953}>
TLF = NIL
TLF#1 = NIL
TLF-NUMBER = 5
In read-source-form, you can see that the form is being read inside a (ignore-errors (read ...)) form, which returns NIL in case of error. I tried calling (read ...) only but this somehow did not invoke the debugger, so I did the same thing as above and explicitly invoked it on any condition.
There is an error, namely that the package "SB-XC" does not exist, which is expected since, if I am not mistaken, this is a package that only exists during the compilation of SBCL itself.
I think you should contact the SBCL SLY developers and file a bug for this directly, they would certainly have a better idea of how to fix the behaviour (feel free to link to your question in addition to giving the usual details of the bug report).
I'm seeing pretty much what you're seeing.
Defun (line 280 of defboot.lisp) is a macro, which is defined in terms of defun-expander (line 230 of defboot.lisp) which is what you're seeing.
Whereas, defmacro takes you directly to its definition (line 15 of defmacro.lisp) which is what you're seeing.
It seems to be doing useful things.
I defined a new function 'addmore'
(defun addmore (x y z)
(testfn x (testfn y z)))
I compiled it all, and M-. on 'addmore' takes me to the definition of testfn.
So I think it's all working.

Strange output after putting a "prime" on an identifier in Racket REPL

Today, I made a typing mistake in the REPL and discovered a strange behaviour. Here's a sample of the interaction:
Welcome to Racket v6.11.
> (define x 3)
> x
3
> x'
3
> x
'x
>
So the first x I typed resulted in 3, which is expected. The x' I accidentally typed resulted in 3, which is unexpected. The last x resulted in 'x (!!).
It seems like there is something I don't understand about how the REPL reads values. Could someone explain why the REPL behaves in this way?
See Racketrivia: Using ' as an "identifier suffix" on the racket mailing list. The reply by Robby Findler and the reply by Matthias Felleisen both explain this.
The first line, x, is normal.
The second line, x', is actually an "expression and-a-half." It's interpreted as an expression x followed by an unfinished expression '. The unfinished expression is allowed to be finished on the next line. Whatever you put on the next line will be put as the second half of ' next-line.
That means the third x is actually interpreted as the second half of ' x.
You can see a better example of unfinished expressions with parentheses:
> 1 (list 2 ; 1 followed by an unfinished expression
1
> 3 4) ; finishing it
'(2 3 4)
> 3 4) ; on its own without the `(list 2` before it it's an error
3
4
; readline-input:13:3: read-syntax: unexpected `)` [,bt for context]
The quote after an expression is interpreted in a similar way:
> 1 ' ; 1 followed by an unfinished expression
1
> (indefatigable inexhaustible) ; finishes previously unfinished, put after a quote
'(indefatigable inexhaustible)
> (indefatigable inexhaustible) ; on its own without the quote before it it's an error
; indefatigable: undefined;
; cannot reference an identifier before its definition
; in module: top-level
; internal name: indefatigable

Spacemacs Cider test does not fail

When I run a test in Spacemacs with Clojure mode via <SPC> m t t it does not show a failure, even when the test clearly fails. See:
1 is not equal to 2, but still there are 0 test failures.
How can I make the test fail?
There is an issue in your test: it lacks comparison operator. The correct version is:
(deftest test-exercise-1-4
(testing "count-anywhere"
(is (= 2 1))))
is macro has following definition (edited source for brevity):
(defmacro is
"Generic assertion macro. 'form' is any predicate test.
'msg' is an optional message to attach to the assertion.
Example: (is (= 4 (+ 2 2)) \"Two plus two should be 4\")
([form] `(is ~form nil))
([form msg] `(try-expr ~msg ~form)))
As you can see with (is 2 1) you are calling the second arity where form is 2 and the message for assertion is 1. As 2 is truthy it makes the assertion to pass:
(is 2)
;; => 2
(is false)
FAIL in () (boot.user5045373352931487641.clj:1)
expected: false
actual: false
;; => false

Writing a macro to swap the values of two symbols

I can't think of any possible use case for this, but as an exercise to try to wrap my mind further around Clojure's macros, I'm trying to write a macro that will swap the values assigned to two symbols.
Here are two things that I tried:
Method 1:
(defmacro swap [x y]
`(let [tmp# ~x]
(def x ~y)
(def y ~tmp#)))
Method 2:
(defmacro swap [x y]
`(let [tmp# ~x]
(alter-var-root #'x (fn [] ~y))
(alter-var-root #'y (fn [] ~tmp#))))
Here is the code I use to test it:
(def four 4)
(def five 5)
(swap four five)
(printf "four: %d\nfive: %d" four five)
Expected output:
four: 5
five: 4
However, using either version of the macro, I get a java.lang.RuntimeException: Unable to resolve symbol: tmp# in this context. Am I using auto gensym incorrectly?
Using method 1, I was able to get it to run by changing the last line to (def y tmp#))) (taking out the ~ before tmp#), however I get the output four: 4\nfive: 5 which is not swapped.
Ignoring the fact that mutating vars like this is a bad idea, let's assume you really want to do it anyway. Your problem is two-fold:
You have an unquote on ~tmp#, where you just want tmp#
You're missing an unquote on x and y: you want to (def ~x ~y) and (def ~y tmp#)
The version you wrote always assigns to the vars named x and y, instead of modifying the vars provided by the user.

On ocaml indenting style for this kind of nested let-in

I am reading Ocaml Style guide on nested let-in of Ocaml.
http://www.seas.upenn.edu/~cis341/programming_style.html#16
It is suggested that
Indenting nested let expressions: Blocks of code that have nested let expressions should not be indented.
Bad:
let x = exp1 in
let y = exp2 in
x + y
Good:
let x = exp1 in
let y = exp2 in
x + y
However, what do you think about how to indent my following program.
let f =
let g = 3 in
g + 2
The above is indented by emacs. But apparently, this indenting of emacs violates the style guide I cited earlier. To follow the style, shouldn' t it be more like this one?
let f =
let g = 3 in
g + 2
Thank you for your ideas.
#Gilles: In my current default Tuareg mode, I get such indenting, which is diffrent from yours
let f =
let g = 3 in
let h = 4 in
g + 2
could you explain which configuration should I do to make my Tuareg mode indent as yours?
The official caml-mode (part of the standard Ocaml distribution) defaults to not intenting the body of a let expression:
let f =
let g = 3 in
let h = 4 in
g + 2
This is the style used by the authors of Ocaml (hence the Right style). In my experience the official mode matches the official style very well (unsurprising since it's from the same people). If you're getting something different, you (or the person or distribution who installed the mode on your machine) must have configured it.
Tuareg mode puts the same indentation on the snippet above on my machine (Debian squeeze). Different versions have different indentation defaults; in particular, this is the docstring for tuareg-in-indent on 2.0.1:
How many spaces to indent from a in keyword.
Upstream recommends 0, and this is what we default to since 2.0.1 instead of the historical tuareg-default-indent.
I think Tuareg does have some strange behavior indenting nested let-in. add these lines to come back to "default" ocaml indenting style, suggested by
C. TROESTLER
(add-hook 'tuareg-mode-hook
(function (lambda ()
(setq tuareg-in-indent 0)
(setq tuareg-let-always-indent t)
(setq tuareg-let-indent tuareg-default-indent)
(setq tuareg-with-indent 0)
(setq tuareg-function-indent 0)
(setq tuareg-fun-indent 0)
(setq tuareg-parser-indent 0)
(setq tuareg-match-indent 0)
(setq tuareg-begin-indent tuareg-default-indent)
(setq tuareg-parse-indent tuareg-default-indent); .mll
(setq tuareg-rule-indent tuareg-default-indent)
(setq tuareg-font-lock-symbols nil)
)))