java.lang.IllegalArgumentException error depending on symbol names used - Clojure - linux

I am a beginner at Clojure. I am performing one operation twice, but with changed symbols lang against language
One case it is working well, another is throwing an error:
java.lang.IllegalArgumentException: No method in multimethod 'my-method' for dispatch value: null
I am not sure if it is caused by an Clojure syntax or there is something wrong in my linux configuration. I have Debian Stretch and boot.clj.
The error happens in the terminal. Here you are the both peaces of code an the error:
s#lokal:~$ boot repl
nREPL server started on port 36091 on host 127.0.0.1 - nrepl://127.0.0.1:36091
java.lang.Exception: No namespace: reply.eval-modes.nrepl found
REPL-y 0.4.1, nREPL 0.4.4
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.8.0_181-8u181-b13-2~deb9u1-b13
Exit: Control+D or (exit) or (quit)
Commands: (user/help)
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Find by Name: (find-name "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Examples from clojuredocs.org: [clojuredocs or cdoc]
(user/clojuredocs name-here)
(user/clojuredocs "ns-here" "name-here")
boot.user=> (do
#_=> (defmulti my-method (fn[x] (x "lang")))
#_=> (defmethod my-method "English" [params] "Hello!")
#_=> (def english-map {"id" "1", "lang" "English"})
#_=> (my-method english-map)
#_=> )
"Hello!"
boot.user=>
boot.user=> (do
#_=> (defmulti my-method (fn[x] (x "language")))
#_=> (defmethod my-method "English" [params] "Hello!")
#_=> (def english-map {"id" "1", "language" "English"})
#_=> (my-method english-map)
#_=> )
java.lang.IllegalArgumentException: No method in multimethod 'my-method' for dispatch value: null
boot.user=>
I must add that before it worked with language but not with lang. It also turned to work or did not when I was changing a my-method symbol name with mymetho-d or greeting.

defmulti defines a var, and subsequent calls to defmulti with the same name do nothing, so your second defmulti call is ineffective and the original dispatch function remains. There's remove-method and remove-all-methods for removing defmethod definitions, but to remove a defmulti definition (without restarting REPL) you can use alter-var-root to set the var to nil:
(defmulti my-method (fn [x] (x "lang")))
(defmethod my-method "English" [params] "Hello!")
(def english-map {"id" "1", "lang" "English"})
(my-method english-map)
=> "Hello!"
(alter-var-root #'my-method (constantly nil)) ;; set my-method var to nil
(def english-map {"id" "1", "language" "English"})
(defmulti my-method (fn [x] (x "language")))
(defmethod my-method "English" [params] "Hello!")
(my-method english-map)
=> "Hello!"
You can use ns-unmap to similar effect:
(ns-unmap *ns* 'my-method)

Related

datalevin, concurrency, transactions

I am using latest Datalevin version 0.7.8 and wrote the following small program:
(ns datalevintest.core
(:require [datalevin.core :as dc]))
(def store (System/getenv "DBSTORE"))
(def conn (datalevin.core/get-conn store {} {:auto-entity-time? true :validate-data? true}))
(defn -main [& _]
(dotimes [i 5]
(future
(locking ::println (println "Starting thread"))
(try
(dotimes [j 100]
(dc/transact! conn [{:i+j (+ i j)}])
(dc/with-transaction [tx-conn conn]
(dc/transact! tx-conn [{:i*j (* i j)}]))
(dc/q '[:find (pull ?e [*]) :in $ ?id :where [?e :db/id ?id]]
(dc/db conn) 2345))
(catch Throwable t (.printStackTrace t))
(finally (println "Thread" i "done")))))
(println "END"))
Nondeterministically, sometimes I get the following:
clojure.lang.ExceptionInfo: Fail to transact to LMDB: "Transaction is not in ready state" {}
at datalevin.binding.java.LMDB.transact_kv(java.clj:484)
at datalevin.storage.Store.load_datoms(storage.cljc:376)
at datalevin.db$local_transact_tx_data.invokeStatic(db.cljc:1236)
at datalevin.db$local_transact_tx_data.invoke(db.cljc:963)
at datalevin.db$transact_tx_data.invokeStatic(db.cljc:1274)
at datalevin.db$transact_tx_data.invoke(db.cljc:1250)
at datalevin.core$with.invokeStatic(core.cljc:291)
at datalevin.core$with.invoke(core.cljc:285)
at datalevin.core$with.invokeStatic(core.cljc:288)
at datalevin.core$with.invoke(core.cljc:285)
at datalevin.core$_transact_BANG_$fn__13128$fn__13129.invoke(core.cljc:550)
at clojure.lang.Atom.swap(Atom.java:37)
at clojure.core$swap_BANG_.invokeStatic(core.clj:2356)
at clojure.core$swap_BANG_.invoke(core.clj:2349)
at datalevin.core$_transact_BANG_$fn__13128.invoke(core.cljc:549)
at datalevin.core$_transact_BANG_.invokeStatic(core.cljc:548)
at datalevin.core$_transact_BANG_.invoke(core.cljc:545)
at datalevin.core$transact_BANG_.invokeStatic(core.cljc:643)
at datalevin.core$transact_BANG_.invoke(core.cljc:555)
at datalevin.core$transact_BANG_.invokeStatic(core.cljc:640)
at datalevin.core$transact_BANG_.invoke(core.cljc:555)
at datalevintest.core$save_BANG_.invokeStatic(core.clj:10)
at datalevintest.core$save_BANG_.doInvoke(core.clj:9)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at datalevintest.core$_main$fn__13261$fn__13265.invoke(core.clj:32)
at datalevintest.core$_main$fn__13261.invoke(core.clj:27)
at clojure.core$binding_conveyor_fn$fn__5772.invoke(core.clj:2034)
at clojure.lang.AFn.call(AFn.java:18)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
(You may need to run the program multiple times to get the error.)
Less often I get the following:
clojure.lang.ExceptionInfo: Fail to get-first: nil {:dbi "datalevin/eav", :k-range [:all-back], :k-type :eav, :v-type :id}
at datalevin.scan$get_first.invokeStatic(scan.cljc:233)
at datalevin.scan$get_first.invoke(scan.cljc:229)
at datalevin.binding.java.LMDB.get_first(java.clj:502)
at datalevin.binding.java.LMDB.get_first(java.clj:500)
at datalevin.storage.Store.init_max_eid(storage.cljc:300)
at datalevin.db$new_db.invokeStatic(db.cljc:387)
at datalevin.db$new_db.invoke(db.cljc:379)
at datalevintest.core$_main$fn__13261$fn__13265$fn__13276.invoke(core.clj:30)
at datalevintest.core$_main$fn__13261$fn__13265.invoke(core.clj:30)
at datalevintest.core$_main$fn__13261.invoke(core.clj:27)
at clojure.core$binding_conveyor_fn$fn__5772.invoke(core.clj:2034)
at clojure.lang.AFn.call(AFn.java:18)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
If I move the creation of connection into the future wiht create-conn, I get another exception:
java.lang.NullPointerException: Cannot read field "e"
at datalevin.storage.Store.init_max_eid(storage.cljc:302)
at datalevin.db$new_db.invokeStatic(db.cljc:387)
at datalevin.db$new_db.invoke(db.cljc:379)
at datalevin.db$empty_db.invokeStatic(db.cljc:399)
at datalevin.db$empty_db.invoke(db.cljc:392)
at datalevin.core$create_conn.invokeStatic(core.cljc:529)
at datalevin.core$create_conn.invoke(core.cljc:488)
at datalevintest.core$_main$fn__13252.invoke(core.clj:14)
at clojure.core$binding_conveyor_fn$fn__5772.invoke(core.clj:2034)
at clojure.lang.AFn.call(AFn.java:18)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
(This one also breaks the database file so the application will not start up the next time.)
The issue comes up in a multithreaded environment and sounds like a concurrency problem. My first idea was that the same connection should'nt be used across different threads, however, the code of get-conn says the same connection will be reused when it alrady exists for a directory. The documentation does not mention multithreading.
What is the error in my code causing the problem and how can I make it safer?
This bug was fixed by version 0.7.9 released half an hour after the question was posted.

unbound variable when creating a Guix rust package with dependencies

I'm trying to create a guix package for the xsv crate. I use output of guix import crate xsv and add the necessary use-modules lines, which gives the following rust_xsv.scm file :
(use-modules (guix packages)
(guix download)
(guix build-system cargo)
((guix licenses) #:prefix license:))
;; (define-public rust-xsv-0.13
(package
(name "rust-xsv")
(version "0.13.0")
(source (origin
(method url-fetch)
(uri (crate-uri "xsv" version))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"0pvzr7x5phlya6m5yikvy13vgbazshw0plysckz9zmf2ly5x4jl8"))))
(build-system cargo-build-system)
(arguments
`(#:cargo-inputs (("rust-byteorder" ,rust-byteorder-1)
("rust-chan" ,rust-chan-0.1)
("rust-csv" ,rust-csv-1)
("rust-csv-index" ,rust-csv-index-0.1)
("rust-docopt" ,rust-docopt-1)
("rust-filetime" ,rust-filetime-0.1)
("rust-num-cpus" ,rust-num-cpus-1)
("rust-rand" ,rust-rand-0.4)
("rust-regex" ,rust-regex-1)
("rust-serde" ,rust-serde-1)
("rust-serde-derive" ,rust-serde-derive-1)
("rust-streaming-stats" ,rust-streaming-stats-0.2)
("rust-tabwriter" ,rust-tabwriter-1)
("rust-threadpool" ,rust-threadpool-1))
#:cargo-development-inputs (("rust-log" ,rust-log-0.4)
("rust-quickcheck" ,rust-quickcheck-0.6))))
(home-page "https://github.com/BurntSushi/xsv")
(synopsis "A high performance CSV command line toolkit.")
(description
"This package provides a high performance CSV command line toolkit.")
(license (list license:unlicense license:expat)))
;; )
When I try to build this package with guix package --install-from-file=./rust-xsv.scm I get the error error: rust-byteorder-1: unbound variable, in other words it doesn´t find the cargo-input dependencies. What am I missing ?
Here is the complete trace :
The following package will be installed:
rust-xsv 0.13.0
Backtrace:
In guix/ui.scm:
2263:7 19 (run-guix . _)
2226:10 18 (run-guix-command _ . _)
In ice-9/boot-9.scm:
1752:10 17 (with-exception-handler _ _ #:unwind? _ # _)
In guix/status.scm:
835:3 16 (_)
815:4 15 (call-with-status-report _ _)
In guix/store.scm:
1298:8 14 (call-with-build-handler #<procedure 7f93512c2b70 at g…> …)
In guix/build/syscalls.scm:
1428:3 13 (_)
1395:4 12 (call-with-file-lock/no-wait _ #<procedure 7f934238684…> …)
In guix/scripts/package.scm:
153:19 11 (build-and-use-profile #<store-connection 256.99 7f935…> …)
In guix/store.scm:
2168:25 10 (run-with-store #<store-connection 256.99 7f93511bf640> …)
In guix/profiles.scm:
666:3 9 (_ _)
In srfi/srfi-1.scm:
586:17 8 (map1 (#<<manifest-entry> name: "rust-xsv" version: …> …))
In guix/profiles.scm:
1929:19 7 (_ _)
In guix/packages.scm:
1279:17 6 (supported-package? #<package rust-xsv#0.13.0 /home/he…> …)
In guix/memoization.scm:
101:0 5 (_ #<hash-table 7f93429e7f00 0/31> #<package rust-xsv#…> …)
In guix/packages.scm:
1257:37 4 (_)
1517:16 3 (package->bag _ _ _ #:graft? _)
1622:43 2 (thunk)
In /home/henri/travaux/www/orchestraGuix/rust-xsv.scm:
19:42 1 (arguments #<package rust-xsv#0.13.0 /home/henri/travau…>)
In ice-9/boot-9.scm:
1685:16 0 (raise-exception _ #:continuable? _)
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
error: rust-byteorder-1: unbound variable
I was missing two things :
an import of the (gnu packages crate-io) in order to have access to the crates already packaged in the guix repository (like rust-byteorder)
the -r option in the initial command guix import crate -r xsv in order to get the definitions of the crates not already packaged by guix repo.
Here is the fixed file :
(use-modules (guix packages)
(guix download)
(guix build-system cargo)
(gnu packages crates-io)
((guix licenses) #:prefix license:))
(define-public rust-filetime-0.1
(package
(name "rust-filetime")
(version "0.1.15")
(source (origin
(method url-fetch)
(uri (crate-uri "filetime" version))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"03xishfxzpr4nfz4g3r218d6b6g94rxsqw9pw96m6wa8wgrm6iki"))))
(build-system cargo-build-system)
(arguments
`(#:skip-build? #t
#:cargo-inputs (("rust-cfg-if" ,rust-cfg-if-0.1)
("rust-libc" ,rust-libc-0.2)
("rust-redox-syscall" ,rust-redox-syscall-0.1))))
(home-page "https://github.com/alexcrichton/filetime")
(synopsis "Platform-agnostic accessors of timestamps in File metadata
")
(description "Platform-agnostic accessors of timestamps in File metadata")
(license (list license:expat license:asl2.0))))
(define-public rust-csv-index-0.1
(package
(name "rust-csv-index")
(version "0.1.6")
(source (origin
(method url-fetch)
(uri (crate-uri "csv-index" version))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"01048y84y0bakqm0x4y1svjv6lzc753b9q598xp7xgcqrdgi6x7j"))))
(build-system cargo-build-system)
(arguments
`(#:skip-build? #t
#:cargo-inputs (("rust-byteorder" ,rust-byteorder-1)
("rust-csv" ,rust-csv-1))))
(home-page "https://github.com/BurntSushi/rust-csv")
(synopsis "On disk CSV indexing data structures.")
(description "On disk CSV indexing data structures.")
(license (list license:unlicense license:expat))))
(define-public rust-chan-0.1
(package
(name "rust-chan")
(version "0.1.23")
(source (origin
(method url-fetch)
(uri (crate-uri "chan" version))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"1n0y992mqfk5zpxzvrv14g9qivacmd4fiv4j1nmgyrg0vaimcjfi"))))
(build-system cargo-build-system)
(arguments
`(#:skip-build? #t
#:cargo-inputs (("rust-rand" ,rust-rand-0.3))))
(home-page "https://github.com/BurntSushi/chan")
(synopsis "DEPRECATED. Use crossbeam-channel instead.")
(description "DEPRECATED. Use crossbeam-channel instead.")
(license (list license:unlicense license:expat))))
;; (define-public rust-xsv-0.13
(package
(name "rust-xsv")
(version "0.13.0")
(source (origin
(method url-fetch)
(uri (crate-uri "xsv" version))
(file-name (string-append name "-" version ".tar.gz"))
(sha256
(base32
"0pvzr7x5phlya6m5yikvy13vgbazshw0plysckz9zmf2ly5x4jl8"))))
(build-system cargo-build-system)
(arguments
`(#:cargo-inputs (("rust-byteorder" ,rust-byteorder-1)
("rust-chan" ,rust-chan-0.1)
("rust-csv" ,rust-csv-1)
("rust-csv-index" ,rust-csv-index-0.1)
("rust-docopt" ,rust-docopt-1)
("rust-filetime" ,rust-filetime-0.1)
("rust-num-cpus" ,rust-num-cpus-1)
("rust-rand" ,rust-rand-0.4)
("rust-regex" ,rust-regex-1)
("rust-serde" ,rust-serde-1)
("rust-serde-derive" ,rust-serde-derive-1)
("rust-streaming-stats" ,rust-streaming-stats-0.2)
("rust-tabwriter" ,rust-tabwriter-1)
("rust-threadpool" ,rust-threadpool-1))
#:cargo-development-inputs (("rust-log" ,rust-log-0.4)
("rust-quickcheck" ,rust-quickcheck-0.6))))
(home-page "https://github.com/BurntSushi/xsv")
(synopsis "A high performance CSV command line toolkit.")
(description
"This package provides a high performance CSV command line toolkit.")
(license (list license:unlicense license:expat)))
;; )

How to define target env in compile time while building .cljs?

I want to compile my .cljs file for both browser and node.js environments, to get server side rendering. As I understand, there's no way to define cljs env in compile time with reader macro conditions like:
#?(:clj ...)
#?(:cljs ...)
so, I can't easily tell compiler to process something like #?(:cljs-node ...) in node.js env.
Second option I see here is to develop a macro file which will define env at compile time. But how to define that current build is targeting node.js? May be, I could pass some params somehow to compiler or get :target compiler param?
Here are my boot files:
application.cljs.edn:
{:require [filemporium.client.core]
:init-fns [filemporium.client.core/init]}
application.node.cljs.edn:
{:require [filemporium.ssr.core]
:init-fns [filemporium.ssr.core/-main]
:compiler-options
{:preamble ["include.js"]
:target :nodejs
:optimizations :simple}}
I am not aware of a public API to achive this. However, you might use cljs.env/*compiler* dynamic var in your macro to check the target platform (i.e. NodeJS vs browser) configured with :target in your :compiler-options and either emit or suppress the code wrapped in the macro:
(defn- nodejs-target?
[]
(= :nodejs (get-in #cljs.env/*compiler* [:options :target])))
(defmacro code-for-nodejs
[& body]
(when (nodejs-target?)
`(do ~#body)))
(defmacro code-for-browser
[& body]
(when-not (nodejs-target?)
`(do ~#body)))
(code-for-nodejs
(def my-variable "Compiled for nodejs")
(println "Hello from nodejs"))
(code-for-browser
(def my-variable "Compiled for browser")
(println "Hello from browser"))
Here is up to date code working on org.clojure/clojurescript {:mvn/version "1.11.60"}
(ns contrib.cljs-target
#?(:cljs (:require-macros [contrib.cljs-target]))
#?(:cljs (:require [goog.object :as object])))
; preferred runtime check for target through public API https://cljs.github.io/api/cljs.core/STARtargetSTAR
#?(:cljs (defn nodejs? [] (= cljs.core/*target* "nodejs")))
#?(:cljs (defn browser? [] (= cljs.core/*target* "default")))
; undocumented hack, only works in macros. https://stackoverflow.com/a/47499855
#?(:clj (defn- cljs-target [] (get-in #cljs.env/*compiler* [:options :closure-defines 'cljs.core/*target*])))
(defmacro do-nodejs [& body] (if (= "nodejs" (cljs-target)) `(do ~#body)))
(defmacro do-browser [& body] (if-not (= "nodejs" (cljs-target)) `(do ~#body)))

How to setup classpath for slimv and ritz

I would like to resolve my problem for classpath.Could you tell me how to do?
I can do the following.
I can eval (+ 1 1) in vim(slimv) by pushing ,e.
Then slimv display the followings.
user>
(+ 1 1)
2
However,I can not do the followings.
1.When I eval the the following code in vim(slimv) by pushing ,e,
(use '[clojure.contrib.str-utils :only (re-split)])
2.Slimv displays the following error.
; Evaluation aborted on java.io.FileNotFoundException: Could not locate clojure/contrib/str_utils__init.class or clojure/contrib/str_utils.clj on classpath:
My enviroment is the followings.
macvim 7.3.754
lein 2.0.0
slimv 0.9.9
ritz 0.7.0
project.clj
(defproject helloworld "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.4.0"]]
:plugins [[lein-ritz "0.7.0"]]
)
~/.lein/profiles.clj
{:user {:plugins [
[lein-ritz "0.7.0"]
]}}
ref
lein ritz setup error
Have you tried clojure.string?
(use '[clojure.string :only (split)])
(split "clojure8*)-6contrib&(*does^&$not*_^%exist^*#anymore" #"[^a-zA-Z]+")
=> ["clojure" "contrib" "does" "not" "exist" "anymore"]
BTW all clojure.contrib have been migrated to separated libraries http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

How do I write to a zip file in Common Lisp?

I'm able to open a zip entry and tweak the contents, but I can't figure out how to save them.
The API for CL ZIP is wanting.
Specs:
ZIP
Quicklisp
MacPorts CLISP 2.49
Aquamacs 2.1 (Emacs 23.2)
Mac OS X 10.6.4
MacBook Pro 5,1
; Removes newlines at the beginning of PRE tags in Sigil-edited ePub files.
;
; See http://code.google.com/p/sigil/issues/detail?id=655
;
; Andrew Pennebaker
; 16 Nov 2010
; Requires Quicklisp.
; http://www.quicklisp.org/
(ql:quickload "zip")
(ql:quickload "cl-ppcre")
(defvar *epub* nil)
(defvar *epub-contents* nil)
(defvar *epub-out* nil)
(defun load-epub (filename)
(setq *epub* (zip:open-zipfile filename)))
(defun close-epub ()
(zip:close-zipfile *epub*)
(setq *epub* nil)
(setq *epub-contents* nil))
(defun gather-epub-contents ()
(zip:do-zipfile-entries (name entry *epub*)
(push name *epub-contents*)))
(defun is-html-file (name)
(if (cl-ppcre:scan ".+\\.htm[l]?$" name) t nil))
(defun entry-name-to-html (name)
(flexi-streams:octets-to-string
(zip:zipfile-entry-contents
(zip:get-zipfile-entry name *epub*))))
(defun clean (html)
(values
(cl-ppcre:regex-replace-all
"<pre[^>]*>(\\s)*"
(cl-ppcre:regex-replace-all "\\s+</pre>" html "</pre>")
"<pre>")))
As per the documentation of the Common Lisp ZIP library, you have to obtain a separate handle to write to the zip file. Probably you can extract the contents to a folder, tweak the contents and compress the whole folder with a single call to (zip path-name source-folder).
Using a temp file, you're able to unzip, modify, and rezip.
See sigil-clean.cl

Resources