Fork me on GitHub
#clojure
<
2018-07-30
>
Vikash Mansinghka00:07:20

My lab is developing a new probabilistic programming language, embedded in Clojure. (More on this soon.) As part of the process of developing tutorial material for this language, I'm trying to get lein-jupyter and clojuypter working with this project. I'm a Clojure novice, and a clojuypter novice, so I may be missing something basic. Right now I can't seem to access functions defined in clojure.core from clojuypter. Here is an input/output example from within lein repl:

user=> (boolean? true)
true
But the same expression doesn't work when evaluated from lein juypter notebook:
In [1]: (boolean? true)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: boolean? in this context, compiling:(null:1:1) 

punit-naik00:07:06

Hi All. Had a small clojure question: Why doesn't this line work: (let [x 1] (eval (read-string "(str x)")))? It throws the following error: CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(null:1:1)

lilactown01:07:13

@vkm I just installed lein-jupyter and I’m able to run (boolean? true). whats your project.clj look like?

noisesmith01:07:34

given that the boolean? function was added in clojure 1.0, the likely issue here is some error in creating the initial namespace the notebook started with

noisesmith01:07:25

if you ask lein to switch to a namespace at init that wasn't created properly you can end up with a situation where clojure.core isn't available

noisesmith01:07:50

there should be some error message about loading the initial namespace (or something it loaded...) and that's the real issue

noisesmith01:07:54

(clojure.core/refer-clojure) followed by (require 'my.ns :reload) is likely to show you the error

mfikes01:07:16

The boolean? predicate was introduced in 1.9, right?

👍 4
noisesmith01:07:37

ugh, you are right! typo

+user=> (meta #'boolean)
{:arglists ([x]), :doc "Coerce to boolean", :inline #object[clojure.core$boolean__inliner__5416 0x6e4566f1 "clojure.core$boolean__inliner__5416@6e4566f1"], :added "1.0", :line 1597, :column 1, :file "clojure/core.clj", :name boolean, :ns #object[clojure.lang.Namespace 0x5e4bd84a "clojure.core"]}
+user=> (meta #'boolean?)
{:arglists ([x]), :doc "Return true if x is a Boolean", :added "1.9", :line 519, :column 1, :file "clojure/core.clj", :name boolean?, :ns #object[clojure.lang.Namespace 0x5e4bd84a "clojure.core"]}

noisesmith01:07:41

thanks for catching that

noisesmith01:07:25

I thought it was a 1.9 addition, then double checked, but I should have double checked my double check :D

Vikash Mansinghka02:07:10

@lilactown (defproject metaprob "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "GNU General Public License Version 3, 29 June 2007" :url "http://www.gnu.org/licenses/"} ;; Default stack size is 1MB or less, increase to 50 :jvm-opts ["-Xss50M"] :dependencies [[org.clojure/clojure "1.9.0"] [kixi/stats "0.4.0"] [criterium "0.4.4"] [org.apache.commons/commons-math3 "3.6.1"] [incanter "1.9.3"] [org.clojure/math.numeric-tower "0.0.4"]] :plugins [[lein-jupyter "0.1.16"]] ;; :aot [metaprob.basic-trace] )

noisesmith02:07:15

OK, since you are using 1.9, is clojure.core loaded properly? I'd go back to my broken ns theory in that case.

Vikash Mansinghka02:07:16

@noisesmith When I create a new project, lein chooses 1.8.0 by default. Could that be related?

noisesmith02:07:34

what matters is the project that is actually running

noisesmith02:07:47

it's simple to test that in a repl too though *clojure-version*

noisesmith02:07:13

or clojure.core/*clojure-version* since in a broken ns the first one wouldn't work

Vikash Mansinghka02:07:26

@noisesmith Did you mean (require 'my.ns :reload) literally? Or did you mean for me to replace my.ns with some namespace from my project that references boolean?

noisesmith02:07:38

I mean your init-ns - the ns that your project wants to load at startup

Vikash Mansinghka02:07:54

@noisesmith Progress! It appears that despite my project.clj depending on 1.9.0, the Clojure version I am ending up with from lein jupyter notebook is 1.8.0:

clojure.core/*clojure-version*
=> {:major 1, :minor 8, :incremental 0, :qualifier nil}

lilactown02:07:34

vikash, where are you running that command?

lilactown02:07:48

lein jupyter notebook

Vikash Mansinghka02:07:36

@lilactown @noisesmith Here is a transcript showing how the juypter notebook appears to be starting with a different clojure version than lein repl:

Vikashs-MacBook-Air:metaprob-clojure vkm$ pwd
/Users/vkm/metaprob-clojure
Vikashs-MacBook-Air:metaprob-clojure vkm$ cat project.clj
(defproject metaprob "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :license {:name "GNU General Public License Version 3, 29 June 2007"
            :url ""}
  ;; Default stack size is 1MB or less, increase to 50
  :jvm-opts ["-Xss50M"]
  :dependencies [[org.clojure/clojure "1.9.0"]
                 [kixi/stats "0.4.0"]
                 [criterium "0.4.4"]
                 [org.apache.commons/commons-math3 "3.6.1"]
		 [incanter "1.9.3"]
		 [org.clojure/math.numeric-tower "0.0.4"]]

  :plugins [[lein-jupyter "0.1.16"]]

  ;; :aot [metaprob.basic-trace]
  )
Vikashs-MacBook-Air:metaprob-clojure vkm$ jupyter-console --kernel clojure
Jupyter console 5.0.0

Clojupyters-0.1.0


In [1]: (println *clojure-version*)
{:major 1, :minor 8, :incremental 0, :qualifier nil}

In [2]:                                                                                                                                                                                          
Do you really want to exit ([y]/n)? y
Shutting down kernel
Vikashs-MacBook-Air:metaprob-clojure vkm$ lein repl
nREPL server started on port 63907 on host 127.0.0.1 - 
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.9.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_151-b12
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> (println *clojure-version*)
{:major 1, :minor 9, :incremental 0, :qualifier nil}
nil
user=> 

Vikash Mansinghka02:07:07

@lilactown @noisesmith Aha, it looks like my original bare clojupyter install (as opposed to my lein-juypter install) may have been pulling the wrong clojure version. When I start "lein juypter notebook" from that directory, and manually choose the kernel type to be "lein-clojure", I get version 1.9.

Vikash Mansinghka02:07:21

@lilactown @noisesmith Thanks for the help! I really appreciate it. I've gotten something minimal running now, and am on to debugging incanter plotting in lein-jupyter (as opposed to clojuypter, where it works out of the box).

dominicm09:07:14

I suspect there isn't due to it not being listed on https://clojure.org/guides/reader_conditionals but is there an approach for doing something like:

#?([:clj :cljs] (inc x)
   :cljr (.incInterop x))
The example is contrived, but makes sense in my larger context.

andy.fingerhut09:07:56

@dominicm I also suspect there is not, but have you tested with something like this? #?(:cljr (.incInterop x) :default (inc x)) ?

dominicm10:07:19

@andy.fingerhut yeah, in this case it works. I'm thinking about it's use in scenarios like https://shadow-cljs.github.io/docs/UsersGuide.html#_conditional_reading though. Particularly once you have quite a few js platforms where there is 3 branches, for example. Also evaluating it for use in config files.

punit-naik12:07:40

Hi All, I had a small question. How to change the context of lein run from null to any other namespace?

val_waeselynck13:07:36

@punit-naik from the doc:

...
USAGE: lein run -m NAMESPACE[/MAIN_FUNCTION] [--] [ARGS...]
Calls the main function in the specified namespace. You may have to use -- to
escape the first argument in case it begins with `-' or `:'.
HTH

👍 4
emccue14:07:57

how mature is clojupyter? this is my first time hearing about it

❤️ 4
mkvlr18:07:17

we support Clojure (through unrepl) at http://nextjournal.com (and it’s also written in Clojure). Let me know if you’d like access to our private beta.

henrik03:07:18

@U5H74UNSF Is Nextjournal written in Clojure? I was admiring it the other day.

mkvlr17:07:02

yes. Started out with Elm on the frontend and Elixir on the backend a good two years ago, now it’s all Clojure/Script.

henrik18:07:23

@U5H74UNSF That’s an interesting evolution. What provoked the switch?

mkvlr18:07:06

Elm was just very early prototyping and we found it too hard to integrate with existing JS libs. Elm also went through some big breaking changes at the time. But after a short experiment in JavaScript we knew we looked for another language that also defaults to immutability (like Elm). That’s how we ended up with ClojureScript on the frontend. As we learned about Clojure, Datomic and its workflow we decided to rewrite all our Elixir code in Clojure. Really happy with that decision. Hope to write this up in a post soon.

henrik18:07:36

@U5H74UNSF That would be an excellent read, I look forward to it. I’m also working with services in the academic space, which is how I came across Nextjournal. I’m currently on a mission to learn enough Datomic to argue for it as the basis for a new project we’re starting.

mkvlr19:07:27

@herik can’t recommend it enough, it’s been really great for us. Happy to send you an invite for Nextjournal if you’d like to try it.

👍 4
henrik19:07:15

@U5H74UNSF Sounds great! We are, amongst other things, a scientific publisher. I imagine the publishing office might find it interesting.

Garrett Hopper16:07:09

Can anyone recommend a good map based database like library? I'm using https://github.com/riverford/compound at the moment, which keeps track of multiple indexes, but there isn't any sort of joining between indexes or compounds. Ideally it would be something with a pretty good query language, but datascript doesn't really suit, because I want queries to be fast enough I can re-run all queries when the database changes. Writes don't have to be fast, so I'm imgining something that just writes to many indexes.

Garrett Hopper16:07:35

I suppose what I really want is reactive datascript materialized views... 😛

tbaldridge16:07:24

@ghopper what you want is what is known as a production rules system, or a rete network.

Garrett Hopper16:07:12

Hmm, I've heard of this before. I'll have to look into it more. Thanks!

tbaldridge16:07:39

Databases assume that your queries will change very often (or be ad-hoc), but that your data will change less often. Rules engines (most of which are based on Rete networks) assume that your rules (or queries) will remain static, but that your data changes a lot.

mario-star 16
tbaldridge16:07:09

So with a rules engine, you define a bunch of rules at the start, and then flow data into the engine, the engine will call callbacks when rules have new results

Garrett Hopper16:07:20

That's a very helpful distinction that I hadn't heard before.

12
Tiago Dall'Oca16:07:41

I'm having trouble here

Tiago Dall'Oca16:07:15

trying to compile a robocode robot from clojure

Tiago Dall'Oca16:07:33

Is this the right place to get help?

Tiago Dall'Oca16:07:18

I'm getting a stacktrace when robocode try to initialise my bot

Tiago Dall'Oca16:07:51

I'm packing the robot class with clojure itself, using lein uberjar

Tiago Dall'Oca16:07:46

robocode then initialises the class (in my case is supimpabots.RichardTheLizard class)

Tiago Dall'Oca16:07:14

Here's the stackstrace:

java.lang.ExceptionInInitializerError
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at clojure.lang.RT.classForName(RT.java:2204)
	at clojure.lang.RT.classForName(RT.java:2213)
	at clojure.lang.RT.loadClassForName(RT.java:2232)
	at clojure.lang.RT.load(RT.java:450)
	at clojure.lang.RT.load(RT.java:426)
	at clojure.lang.RT.doInit(RT.java:468)
	at clojure.lang.RT.<clinit>(RT.java:336)
	at clojure.lang.Namespace.<init>(Namespace.java:34)
	at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
	at clojure.lang.Var.internPrivate(Var.java:153)
	at supimpabots.RichardTheLizard.<clinit>(Unknown Source)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at net.sf.robocode.host.security.RobotClassLoader.createRobotInstance(RobotClassLoader.java:256)
	at net.sf.robocode.host.proxies.HostingRobotProxy.loadRobotRound(HostingRobotProxy.java:171)
	at net.sf.robocode.host.proxies.HostingRobotProxy.run(HostingRobotProxy.java:210)
	at net.sf.robocode.host.proxies.BasicRobotProxy.run(BasicRobotProxy.java:44)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.FileNotFoundException: JAR entry clojure/core_instant18__init.class not found in /home/tiago/robocode/robots/supimpabots.RichardTheLizard-0.0.0.1-standalone.jar
	at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:144)
	at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:152)
	at clojure.lang.RT.lastModified(RT.java:403)
	at clojure.lang.RT.load(RT.java:441)
	at clojure.lang.RT.load(RT.java:426)
	at clojure.core$load$fn__6548.invoke(core.clj:6046)
	at clojure.core$load.invokeStatic(core.clj:6045)
	at clojure.core$load.doInvoke(core.clj:6029)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$fn__8055.invokeStatic(core.clj:6709)
	at clojure.core$fn__8055.invoke(core.clj:6708)
	at clojure.core__init.load(Unknown Source)
	at clojure.core__init.<clinit>(Unknown Source)
	... 23 more

Tiago Dall'Oca16:07:56

This line might be relevant: Caused by: java.io.FileNotFoundException: JAR entry clojure/core_instant18__init.class not found in /home/tiago/robocode/robots/supimpabots.RichardTheLizard-0.0.0.1-standalone.jar

Tiago Dall'Oca16:07:37

clojure/core_instant18 is packed as clojure code

Tiago Dall'Oca16:07:57

It seems that clojure classes are not being compiled?

seancorfield17:07:44

@mrdalloca What's in your project.clj file?

seancorfield17:07:50

(I suspect it's a combination of AOT and different versions of Clojure being loaded -- Clojure 1.10 no longer has the instant18 namespace because it's guaranteed to have Java Time due to requiring Java 8)

phoenixjj17:07:21

@mrdalloca - I created new project and mine project.clj look lie this: (defproject robocop "0.1.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.9.0"] [net.sf.robocode/robocode.api "1.9.2.1"]] :main ^:skip-aot robocop.core :target-path "target/%s" :profiles {:uberjar {:aot :all}})

phoenixjj17:07:37

I am able to build uberjar without any issue

eraserhd19:07:42

I have a weird issue on 1.9.0 start happening. NoClassDefFound for com/stuartsierra/component/Lifecycle.class in my main class. My main class is AOT compiled and requires com.stuartsierra.component, and if I run clojure.main with the uberjar, I can require it manually and see Lifecycle.

eraserhd19:07:27

(only my main class is AOT compiled)

eraserhd19:07:06

I can, in fact, run clojure.main and require my main namespace without an issue.

noisesmith19:07:15

so in what context do you get that NoClassDefFound error?

eraserhd20:07:22

essentially java -jar myuberjar, which has {:main twou.centralpark, :aot [twou.centralpark]}.

eraserhd20:07:52

I've decided to run it through clojure.main -e "(do (require 'twou.centralpark) (twou.centralpark/main))"

eraserhd20:07:10

I mean, I don't know why AOT stopped working, but this seems safer anyhow.

noisesmith20:07:13

do you have Lifecycle in your import, or only the parent ns in require?

eraserhd20:07:22

Only the parent ns in require.

eraserhd20:07:18

(if anything references Lifecycle from that namespace, it would have to be a component macro.)

noisesmith20:07:53

it's normal to implement Lifecycle in components when using that library

noisesmith20:07:00

I think not using AOT when possible is generally better, but I suspect your issue is either something reloading that namespace so you get reload related problems with Lifecycle, or needing to import as well as require

eraserhd20:07:21

I think you might be right... I just added a non-ns require to make the production repl load correctly. I can imagine this doing it.

Tiago Dall'Oca19:07:25

@phoenixai2082 the problem is not with lein uberjar

Tiago Dall'Oca19:07:16

I'm able to compile the uberjar with no problems

Black19:07:57

Hi, can anyone help me how to use bitpay-java-api in clojure? https://mvnrepository.com/artifact/ccfontes/bitpay-java-api/1.0

Tiago Dall'Oca19:07:17

@seancorfield, I'm packaging clojure 1.9.0 with the jar

Black19:07:55

@jonahbenton I thought it is only wrapper. How do I include it inside project.clj?

jonahbenton19:07:22

I haven't used it, but it looks a little ugly. It looks like you will have to do 2 things

jonahbenton19:07:57

1. go through their pom: https://github.com/bitpay/java-bitpay-client/blob/master/pom.xml and for each <dependency>, and a corresponding entry to project.clj

jonahbenton19:07:41

2. follow their build instructions: https://github.com/bitpay/java-bitpay-client and use eclipse to produce a jar file, the name of which will come out of the pom.xml, then include that reference in your project.clj as well

Black19:07:05

It seems very complicated, there is no better way to use bitpay? But thanks for help I will look into it.

jonahbenton19:07:38

I haven't used it. But they should package their sdk into a standalone jar. Even for java devs, few people use Eclipse and none want to consume an official library in this manner

✔️ 4
seancorfield19:07:39

@mrdalloca Can you put your project up on GitHub so we can clone it and try to repro/debug?

Tiago Dall'Oca20:07:07

To reproduce the bug, unzip the file, start robocode with ./robocode, import the standalone jar generated with lein uberjar (`Robot > Import robot or team`), create a new battle (`Battle > New`) and select RichardTheLizard and other bot.

seancorfield21:07:01

@mrdalloca It's a combination of a bug in Clojure 1.9 and a bug in you robot code I think. First off, you haven't defined the -init function to perform the initialization. With that in place, it all works for Clojure 1.8.0 and for Clojure 1.10.0-alpha6.

👍 4
seancorfield21:07:06

Not quite sure what's going on with 1.9 but in the uberjar there are these files

clojure/core__init.class
clojure/core_deftype.clj
clojure/core_deftype__init.class
clojure/core_instant18.clj
clojure/core_print.clj
clojure/core_print__init.class
clojure/core_proxy.clj
clojure/core_proxy__init.class
Note that there's no __init.class file for core_instant18.clj like there is for all the others. Not sure why. But that might be why the Robocode setup is failing on 1.9.0.

roklenarcic21:07:12

This may be a dumb question, but if I want to return app version when called with -v, how can I make this automatically return the version from project.clj

roklenarcic21:07:14

My google-fu found some kind of solution. 🙂

seancorfield21:07:00

@roklenarcic I think the most common way I've seen this done is to have a version file in your resources folder and for both project.clj and your app code to read that in to set the version (`project.clj`) and return the version (your app).

👍 4
roklenarcic21:07:21

Ended up doing what amalloy answered on stackoverflow

roklenarcic21:07:29

reading version from META-INF