Clojurescript repl trying to invoke Clojure function from the Transit library - clojure

I have both the cognitect.transit-clj and cognitect.transit-cljs dependencies because my project is Clojure on the backend and CLJS on the frontend. I'm connecting to a shadow-cljs repl in cider with cider-connect.
In the repl, I do:
(require '[cognitect.transit :as xit])
(def my-writer (xit/writer :json))
I get this error:
Execution error (ArityException) at nrepl.middleware.interruptible-eval/evaluate$fn (interruptible_eval.clj:91).
Wrong number of args (1) passed to: cognitect.transit/writer
It appears that it's trying to invoke the java version of transmit/writer. Is something wrong with my dependencies or setup?
Here's the full stack trace:
clojure.lang.Compiler$CompilerException: Syntax error macroexpanding at (NO_SOURCE_FILE:45:29).
#:clojure.error{:phase :execution, :line 45, :column 29, :source "NO_SOURCE_FILE"}
at clojure.lang.Compiler$InvokeExpr.eval (Compiler.java:3707)
clojure.lang.Compiler$DefExpr.eval (Compiler.java:457)
clojure.lang.Compiler.eval (Compiler.java:7182)
clojure.lang.Compiler.eval (Compiler.java:7132)
clojure.core$eval.invokeStatic (core.clj:3214)
clojure.core$eval.invoke (core.clj:3210)
nrepl.middleware.interruptible_eval$evaluate$fn__42793.invoke (interruptible_eval.clj:91)
clojure.main$repl$read_eval_print__9086$fn__9089.invoke (main.clj:437)
clojure.main$repl$read_eval_print__9086.invoke (main.clj:437)
clojure.main$repl$fn__9095.invoke (main.clj:458)
clojure.main$repl.invokeStatic (main.clj:458)
clojure.main$repl.doInvoke (main.clj:368)
clojure.lang.RestFn.invoke (RestFn.java:1523)
nrepl.middleware.interruptible_eval$evaluate.invokeStatic (interruptible_eval.clj:84)
nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)
nrepl.middleware.interruptible_eval$interruptible_eval$fn__42819$fn__42823.invoke (interruptible_eval.clj:155)
clojure.lang.AFn.run (AFn.java:22)
nrepl.middleware.session$session_exec$main_loop__43068$fn__43072.invoke (session.clj:190)
nrepl.middleware.session$session_exec$main_loop__43068.invoke (session.clj:189)
clojure.lang.AFn.run (AFn.java:22)
java.lang.Thread.run (Thread.java:748)
Caused by: clojure.lang.ArityException: Wrong number of args (1) passed to: cognitect.transit/writer
at clojure.lang.AFn.throwArity (AFn.java:429)
clojure.lang.AFn.invoke (AFn.java:32)
clojure.lang.AFn.applyToHelper (AFn.java:154)
clojure.lang.AFn.applyTo (AFn.java:144)
clojure.lang.Compiler$InvokeExpr.eval (Compiler.java:3702)
clojure.lang.Compiler$DefExpr.eval (Compiler.java:457)
clojure.lang.Compiler.eval (Compiler.java:7182)
clojure.lang.Compiler.eval (Compiler.java:7132)
clojure.core$eval.invokeStatic (core.clj:3214)
clojure.core$eval.invoke (core.clj:3210)
nrepl.middleware.interruptible_eval$evaluate$fn__42793.invoke (interruptible_eval.clj:91)
clojure.main$repl$read_eval_print__9086$fn__9089.invoke (main.clj:437)
clojure.main$repl$read_eval_print__9086.invoke (main.clj:437)
clojure.main$repl$fn__9095.invoke (main.clj:458)
clojure.main$repl.invokeStatic (main.clj:458)
clojure.main$repl.doInvoke (main.clj:368)
clojure.lang.RestFn.invoke (RestFn.java:1523)
nrepl.middleware.interruptible_eval$evaluate.invokeStatic (interruptible_eval.clj:84)
nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)
nrepl.middleware.interruptible_eval$interruptible_eval$fn__42819$fn__42823.invoke (interruptible_eval.clj:155)
clojure.lang.AFn.run (AFn.java:22)
nrepl.middleware.session$session_exec$main_loop__43068$fn__43072.invoke (session.clj:190)
nrepl.middleware.session$session_exec$main_loop__43068.invoke (session.clj:189)
clojure.lang.AFn.run (AFn.java:22)
java.lang.Thread.run (Thread.java:748)

I do not know enough about cider-connect but it is very likely that you are just connected to the CLJ REPL and not the actual CLJS REPL you are looking for. A connection always starts out as CLJ and your editor has to "upgrade" it to CLJS. Maybe this is still current?
For plain shadow-cljs you get to the CLJS REPL directly via shadow-cljs cljs-repl app (assuming :app is your build id). For nREPL your editor is in control. I'm sure there is a command for that.

Related

Clojure: How to restore REPL after exception?

What's the proper workflow in cases when you have an error after you restart/reload your app using mount?
An example:
user> (restart)
#error {
:cause "Unable to resolve symbol: account-database in this context"
:via
[{:type clojure.lang.Compiler$CompilerException
:message "Syntax error compiling at (app/model/session.clj:55:39)."
:data #:clojure.error{:phase :compile-syntax-check, :line 55, :column 39, :source "app/model/session.clj"}
:at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
{:type java.lang.RuntimeException
:message "Unable to resolve symbol: account-database in this context"
:at [clojure.lang.Util runtimeException "Util.java" 221]}]
:trace
[[clojure.lang.Util runtimeException "Util.java" 221]
Reloadable Clojure REPL
user> (restart)
Syntax error compiling at (*cider-repl Projects/pollcro:localhost:43993(clj)*:597:7).
Unable to resolve symbol: restart in this context
user> (start)
Syntax error compiling at (*cider-repl Projects/pollcro:localhost:43993(clj)*:600:7).
Unable to resolve symbol: start in this context
After fixing an error, I can not (restart) this reply anymore due to the following error:
Unable to resolve symbol: restart in this context
Is it always like this or am I doing something wrong with my REPL workflow?
As a workaround, I cider-quit my REPL session and start it again but that's very annoying.
It seems I can use mount/start after fixing an error:
user> (mount/start)
{:started
["#'app.server-components.config/config"
"#'app.model.database/pool"
"#'app.model.mock-database/conn"]}
But it completely loses my user namespace scope, REPL doesn't see any of its methods + I can't send user namespace to repl because of the following error:
Syntax error compiling at (app/server_components/pathom.clj:1:1).
namespace 'app.model.session' not found
("src/main" "src/dev" "src/test")#function[expound.alpha/printer]nil#'user/start#'user/stop#'user/restartnil
That's what my user namespace looks like:
(ns user
(:require
[clojure.tools.namespace.repl :as tools-ns :refer [set-refresh-dirs]]
[expound.alpha :as expound]
[clojure.spec.alpha :as s]
[mount.core :as mount]
;; this is the top-level dependent component...mount will find the rest via ns requires
[app.server-components.http-server :refer [http-server]]))
;; ==================== SERVER ====================
(set-refresh-dirs "src/main" "src/dev" "src/test")
;; Change the default output of spec to be more readable
(alter-var-root #'s/*explain-out* (constantly expound/printer))
(defn start
"Start the web server"
[] (mount/start))
(defn stop
"Stop the web server"
[] (mount/stop))
(defn restart
"Stop, reload code, and restart the server. If there is a compile error, use:
(tools-ns/refresh)
to recompile, and then use `start` once things are good."
[]
(stop)
(tools-ns/refresh :after 'user/start))
Here's the workaround that seems to work in case of an error:
the content of a fixed file need to be sent to the REPL
switch back to user namespace
send the content of your user namespace to the REPL
there is no 4 - you just got your REPL back.
At this point you can use your regular (start), (stop), (restart).

Cannot connect to compose.io hosted rethinkdb with clojure

I'm using the clojure rethinkdb library https://github.com/apa512/clj-rethinkdb - here's my connection snippet:
(ns rethink.core
(:require
[environ.core]
[cheshire.core :as json]
[org.httpkit.client :as http]
[rethinkdb.query :as r]))
(defn rethink-connect
[]
(r/connect :host (environ.core/env :rethinkdb-host)
:port (environ.core/env :rethinkdb-port)
:db (environ.core/env :rethinkdb-db)
:auth-key (environ.core/env :rethinkdb-auth)))
(defn record-event!
[event collection]
(let [r (with-open [conn (rethink-connect)]
(-> (r/table collection)
(r/insert [event])
(r/run conn)))]))
But I keep getting the error:
clojure.lang.ExceptionInfo: Error connecting to RethinkDB database
core.clj:4617 clojure.core/ex-info
core.clj:4617 clojure.core/ex-info
core.clj:88 rethinkdb.core/connect
core.clj:43 rethinkdb.core/connect
RestFn.java:619 clojure.lang.RestFn.invoke
core.clj:10 rethink.core/rethink-connect
core.clj:8 rethink.core/rethink-connect
core.clj:17 rethink.core/record-event!
core.clj:15 rethink.core/record-event!
core.clj:23 webhook.core/record-event!
core.clj:21 webhook.core/record-event!
handler.clj:11 webhook.handler/webhook-post
handler.clj:8 webhook.handler/webhook-post
handler.clj:9 app.handler/fn
handler.clj:9 app.handler/fn
core.clj:135 compojure.core/make-route[fn]
core.clj:122 compojure.core/wrap-route-middleware[fn]
core.clj:126 compojure.core/wrap-route-info[fn]
core.clj:45 compojure.core/if-route[fn]
core.clj:27 compojure.core/if-method[fn]
core.clj:151 compojure.core/routing[fn]
core.clj:2592 clojure.core/some
core.clj:2583 clojure.core/some
core.clj:151 compojure.core/routing
core.clj:148 compojure.core/routing
RestFn.java:139 clojure.lang.RestFn.applyTo
core.clj:648 clojure.core/apply
core.clj:641 clojure.core/apply
core.clj:156 compojure.core/routes[fn]
keyword_params.clj:35 ring.middleware.keyword-params/wrap-keyword-params[fn]
params.clj:64 ring.middleware.params/wrap-params[fn]
absolute_redirects.clj:38 ring.middleware.absolute-redirects/wrap-absolute-redirects[fn]
content_type.clj:30 ring.middleware.content-type/wrap-content-type[fn]
default_charset.clj:26 ring.middleware.default-charset/wrap-default-charset[fn]
not_modified.clj:52 ring.middleware.not-modified/wrap-not-modified[fn]
Var.java:379 clojure.lang.Var.invoke
reload.clj:22 ring.middleware.reload/wrap-reload[fn]
stacktrace.clj:23 ring.middleware.stacktrace/wrap-stacktrace-log[fn]
stacktrace.clj:86 ring.middleware.stacktrace/wrap-stacktrace-web[fn]
jetty.clj:20 ring.adapter.jetty/proxy-handler[fn]
(Unknown Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle
HandlerWrapper.java:116 org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:369 org.eclipse.jetty.server.Server.handle
AbstractHttpConnection.java:486 org.eclipse.jetty.server.AbstractHttpConnection.handleRequest
AbstractHttpConnection.java:944 org.eclipse.jetty.server.AbstractHttpConnection.content
AbstractHttpConnection.java:1005 org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content
HttpParser.java:865 org.eclipse.jetty.http.HttpParser.parseNext
HttpParser.java:240 org.eclipse.jetty.http.HttpParser.parseAvailable
AsyncHttpConnection.java:82 org.eclipse.jetty.server.AsyncHttpConnection.handle
SelectChannelEndPoint.java:668 org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle
SelectChannelEndPoint.java:52 org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run
QueuedThreadPool.java:608 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
QueuedThreadPool.java:543 org.eclipse.jetty.util.thread.QueuedThreadPool$3.run
Thread.java:745 java.lang.Thread.run
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character
RT.java:1177 clojure.lang.RT.intCast
tcp.clj:156 aleph.tcp/client
tcp.clj:126 aleph.tcp/client
core.clj:61 rethinkdb.core/connect
I'm getting the host "aws-us-xxx-1-portal.xxx.xxxx.com", port "15731", db "dev" and auth-key from my compose.io rethinkdb instance. The auth-key is the admin password taken from authentication credential provided by compose.io interface. Not sure what's going on.
Actually, I needed to use a :ca-cert parameter as well, with the certificate being provided from the compose.io web interface.

:use fails in lein project

When I try to use
(ns eight-puzzle.core
(:use [clojure.contrib.seq :only (positions)]))
I get this error
java.io.FileNotFoundException: Could not locate clojure/contrib/seq__init.class or clojure/contrib/seq.clj on classpath:
RT.java:443 clojure.lang.RT.load
RT.java:411 clojure.lang.RT.load
core.clj:5530 clojure.core/load[fn]
core.clj:5529 clojure.core/load
RestFn.java:408 clojure.lang.RestFn.invoke
core.clj:5336 clojure.core/load-one
core.clj:5375 clojure.core/load-lib[fn]
core.clj:5374 clojure.core/load-lib
RestFn.java:142 clojure.lang.RestFn.applyTo
core.clj:619 clojure.core/apply
core.clj:5413 clojure.core/load-libs
RestFn.java:137 clojure.lang.RestFn.applyTo
core.clj:621 clojure.core/apply
core.clj:5507 clojure.core/use
RestFn.java:408 clojure.lang.RestFn.invoke
NO_SOURCE_FILE:1 eight-puzzle.core/eval8699[fn]
NO_SOURCE_FILE:1 eight-puzzle.core/eval8699
And this problem happens when ever I try to import anything in. Did I do something wrong when setting up clojure?
External dependencies, for projects managed by Leiningen, should be specified in the project.clj file, under the :dependencies key.
(defproject project1 "0.0.1"
:description "Something"
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/clojure-contrib "1.2.0"]
[clj-time "0.6.0"]])
Note: The entries in :dependencies can originate from either maven (maven central repository) or Clojars.
It also looks like you are using clojure.contrib. This library has been deprecated and you should upgrade, if you can. If you are only using clojure.contrib.seq/positions, take a look at this StackOverflow answer. You can also reimplement it with just clojure.core functions:
(defn positions [pred coll]
(for [[idx elt]
(map-indexed vector coll)
:when (pred elt)]
idx))

How do I set local-paths for ritz.nrepl.middleware/wrap-javadoc?

In api docs for nrepl-middleware wrap-javadoc it says that it 'accepts local-paths a space separate list of paths'
How do I set this?
I've tried the following in my profiles.clj
{:user {:plugins []
:jvm-opts ["-Xmx4G"]
:injections [(require 'clojure.repl)]
:warn-on-reflection true
:dependencies [[ritz/ritz-nrepl-middleware "0.7.0"]]
:repl-options {:nrepl-middleware
[ritz.nrepl.middleware.javadoc/wrap-javadoc :local-paths "/usr/local/share/javadocs/7/docs/api"]
}}}
But that causes the following exception when I execute nrepl-jack-in
Starting nREPL server...
Mark set
error in process sentinel: nrepl-server-sentinel: Could not start nREPL server: Reflection warning, NO_SOURCE_PATH:1:483 - reference to field getLocalPort can't be resolved.
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
at clojure.core$comp$fn__4166.doInvoke(core.clj:2347)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.tools.nrepl.server$default_handler.doInvoke(server.clj:89)
at clojure.lang.RestFn.invoke(RestFn.java:436)
at user$eval1192.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6609)
at clojure.lang.Compiler.eval(Compiler.java:6582)
at clojure.core$eval.invoke(core.clj:2852)
at clojure.main$eval_opt.invoke(main.clj:308)
at clojure.main$initialize.invoke(main.clj:327)
at clojure.main$null_opt.invoke(main.clj:362)
at clojure.main$main$fn__6661.invoke(main.clj:440)
at clojure.main$main.doInvoke(main.clj:437)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Subprocess failed
If I wrap :local-paths "..." in a map I don't get any javadoc middleware
If you look at the example of the nrepl-middleware on its github page, you will find that the vector to :nrepl-middleware sbould be a vector of middleware functions where as you are passing it a string path and that's why the exception "String cannot be cast to IFn".
As far as the local-paths is concerned that's something which is send by the nrepl client in the java-doc request itself. You can set local-paths in Emacs by calling:
(setq nrepl-ritz-javadoc-local-paths (list "/usr/local/share/javadocs/7/docs/api"))

How do I eval a clojure data structure within the context of a namespace?

I'm writing a clojure app for internal use, and I want the config file to be in clojure too. I have defined a few macros to make writing the config file easier, but when I try to eval the data from the config file, it cant find my macros. This works fine from the REPL however. For example, I'm using
(load-string "/path/to/config")
I get this error:
Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: defcmd in this context, compiling:(null:1)
at clojure.lang.Compiler.analyze(Compiler.java:6235)
at clojure.lang.Compiler.analyze(Compiler.java:6177)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3452)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6411)
at clojure.lang.Compiler.analyze(Compiler.java:6216)
at clojure.lang.Compiler.analyze(Compiler.java:6177)
at clojure.lang.Compiler.eval(Compiler.java:6469)
at clojure.lang.Compiler.load(Compiler.java:6902)
at clojure.lang.Compiler.load(Compiler.java:6872)
at clojure.core$load_reader.invoke(core.clj:3625)
at clojure.core$load_string.invoke(core.clj:3635)
at serverStats.core$load_config.invoke(core.clj:67)
at serverStats.core$_main.doInvoke(core.clj:78)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.Var.invoke(Var.java:397)
at user$eval109.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6465)
at clojure.lang.Compiler.eval(Compiler.java:6455)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clojure.main$eval_opt.invoke(main.clj:296)
at clojure.main$initialize.invoke(main.clj:315)
at clojure.main$null_opt.invoke(main.clj:348)
at clojure.main$main.doInvoke(main.clj:426)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:405)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:518)
at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Unable to resolve symbol: defcmd in this context
at clojure.lang.Util.runtimeException(Util.java:156)
at clojure.lang.Compiler.resolveIn(Compiler.java:6720)
at clojure.lang.Compiler.resolve(Compiler.java:6664)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6625)
at clojure.lang.Compiler.analyze(Compiler.java:6198)
... 28 more
However, running that same command from the REPL in my namespace works fine.
You probably want some more sophisticated loading scheme. I assume you want to put the configuration into a dedicated configuration namespace. It will only contain the configuration. Helper functions are held in a separate namespace use'd in the configuration namespace.
(defn setup-config-space
[]
(binding [*ns* *ns*]
(in-ns 'config.namespace)
(refer-clojure)
(use 'config.helpers)))
(defn load-config
[path]
(binding [*ns* *ns*]
(in-ns 'config.namespace)
(load-file path)))
See the example use:
..ojure/1.4.0-alpha3% cat config/helpers.clj
(ns config.helpers)
(defmacro defcmd
[x]
`(defn ~x [] "Hello"))
..ojure/1.4.0-alpha3% cat x.clj
(defcmd foo)
..ojure/1.4.0-alpha3% java -cp .:clojure-1.4.0-alpha3.jar clojure.main -r
Clojure 1.4.0-alpha3
user=> ; Paste above functions
#'user/setup-config-space
#'user/load-config
user=> (setup-config-space)
nil
user=> (load-config "x.clj")
#'config.namespace/foo
user=> (config.namespace/foo)
"Hello"