Fork me on GitHub
#clojure
<
2018-10-30
>
chrisn13:10:41

Is there a way to use a jar that packages native shared libraries via tools.deps? The native library in a small isolated test appears to not load causing the jni layer to choke.

dominicm15:10:12

Pack is probably just a few flags short of supporting this.

chrisn13:10:41

chrisn@chrisn-dt:~/dev/tvm-clj/tvm/build$ clojure -Sdeps '{:deps {techascent/tech.opencv {:mvn/version "1.2"}}}'
Clojure 1.9.0
user=> (require '[tech.opencv :as opencv])
WARNING: cast already refers to: #'clojure.core/cast in namespace: tech.datatype.base, being replaced by: #'tech.datatype.base/cast
WARNING: cast already refers to: #'clojure.core/cast in namespace: tech.datatype, being replaced by: #'tech.datatype/cast
CompilerException java.lang.ClassNotFoundException: org.bytedeco.javacpp.opencv_core, compiling:(tech/opencv.clj:1:1)

valerauko13:10:02

i'd try excluding clojure.core from that import, not sure if applicable at all to this case though

Alex Miller (Clojure team)13:10:22

@chrisn there’s nothing different here than anything other classpath building. Using that dep should download it (and its deps) and build a classpath. If some other step needs to be done, you still need to do it.

Alex Miller (Clojure team)13:10:13

$ clojure -Sdeps '{:deps {techascent/tech.opencv {:mvn/version "1.2"}}}' -Stree
org.clojure/clojure 1.9.0
  org.clojure/core.specs.alpha 0.1.24
  org.clojure/spec.alpha 0.1.143
techascent/tech.opencv 1.2
  org.bytedeco.javacpp-presets/opencv-platform 3.4.0-1.4
    org.bytedeco.javacpp-presets/opencv 3.4.0-1.4
  techascent/tech.javacpp-datatype 1.3
    techascent/tech.resource 2.0
    techascent/tech.jna 1.2
      techascent/tech.datatype 1.1
        net.mikera/vectorz-clj 0.48.0
          net.mikera/clojure-utils 0.8.0
          net.mikera/vectorz 0.66.0
            us.bpsm/edn-java 0.4.7
            net.mikera/mathz 0.3.0
            net.mikera/randomz 0.3.0
        net.mikera/core.matrix 0.62.0
          org.clojure/tools.macro 0.1.5
      net.java.dev.jna/jna 5.0.0
    org.bytedeco/javacpp 1.4

Alex Miller (Clojure team)13:10:24

seems to be building and including those deps

Alex Miller (Clojure team)13:10:12

if you need to additionally include a native lib, then you need to additionally include it

Alex Miller (Clojure team)14:10:30

it looks like maybe there is a missing classifier on the org.bytedeco.javacpp-presets/opencv dep, or maybe that is a bug in the maven transitive deps stuff in deps.edn

chrisn14:10:07

I don't think there is missing information on opencv. It works from java and leiningen. The java jar includes native/linux/x68_64/*.so and leiningen has special code to deal with this (setting up java library path and such) I believe.

Alex Miller (Clojure team)14:10:41

clj doesn’t have anything special for native library paths

Alex Miller (Clojure team)14:10:47

I think it would be in scope to do so, but I’m not sure what needs to be done. If you wanted to do some research and write up a ticket and I’d be happy to look at it at some point

chrisn14:10:03

Sounds reasonable. Here is the start of the leiningen code for native although I do not know how maven does it: https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/classpath.clj#L35

chrisn14:10:31

I would be happy to help with this also. The full pathway for great native support I think is a bit more in-depth than a tools.deps fix.

socksy14:10:26

I think I either don't understand macros, or I don't understand spec, but I am getting some weird errors trying to make a macro that makes an fn form

socksy14:10:10

say I have an example destructured fn that looks a bit like this:

((fn [{{:keys [b] :as a} :a}]
   a)
 {:a {:b 2}})
where the important thing to note is the internal :as a

socksy14:10:52

it's a bit unwieldy to struct a and b each time, and b can change, as can the body of the fn, so I make a macro like so:

(defmacro ab-fn
  [args & body]
  `(fn [{{:keys [~@args] :as a} :a}]
     ~@body))

socksy14:10:01

(macroexpand-1 '(ab-fn [b] a))
;; => (clojure.core/fn [{{:as my-ns/a, :keys [b]} :a}] a)

moxaj14:10:05

@socksy the bare a after :as is getting namespace qualified, unlikely you want that

socksy14:10:26

sure, but say i do

socksy14:10:32

shouldn't it still work?

socksy14:10:44

because now, fn doesn't pass spec

moxaj14:10:25

you cannot have local variables bound to qualified symbols

socksy14:10:35

(macroexpand '(ab-fn [b] a))
;; =>
Call to clojure.core/fn did not conform to spec: In: [0 0] val: ({{:as
                                                                   application-connection.routes/a, :keys [b]} :a}) fails spec:
:clojure.core.specs.alpha/arg-list at: [:args :bs :arity-1 :args] predicate:
(cat :args (* :clojure.core.specs.alpha/binding-form) :varargs (? (cat :amp
                                                                       #{(quote &)} :form :clojure.core.specs.alpha/binding-form))), Extra input In:
[0 0] val: {{:as application-connection.routes/a, :keys [b]} :a} fails spec:
:clojure.core.specs.alpha/arg-list at: [:args :bs :arity-n :args] predicate:
vector?

socksy14:10:41

you're right, I can't. Why not?

socksy14:10:10

and is there an easy way to not get it to qualify the symbol?

moxaj14:10:21

~'a instead of a

socksy14:10:27

great, thanks

Drew Verlee15:10:14

How do you get the name of the function your currently in the scope of? (defn foo [x] (println "im from function: " ??)

Drew Verlee15:10:39

actually, it would be more like (

(defn greet [f] (print "hello:" f))
(defn foo [] (greet ???))
(foo)
=> "hello foo"

narendraj916:10:23

Looks like there is no such way. What is the real use case?

schmee15:10:51

no way to do that AFAIK

jwhitlark15:10:15

@drewverlee In a macro you can use &form to see the original call. Depending on what you're trying to do, you could have a modified defn macro, and include that info as a value that's available inside the function. IIRC macros that "leak" information intentionally into the function are Anaphoric macros.

👍 4
Patrick Hildreth15:10:55

is anyone able to give me a 30,000 view of clojure.lang.RT

andy.fingerhut16:10:03

It contains many Java methods needed by Clojure/Java to implement base Clojure functionality like cons, first, next, rest, hash, nth, etc. that are called directly from many functions in the clojure.core namespace.

✔️ 4
zilti19:10:08

I suspect modern Clojure versions don't run on the Android VM anymore due to bytecode reasons - is that correct? I tried to google for Android and Clojure 1.9, and there isn't a single mention online.

noisesmith19:10:42

there's a clojure-android project, but it had to fork the clojure compiler itself (for reasons I've forgotten), and nobody got around to doing the same modifications for newer clojure versions

zilti19:10:11

That reason is probably because the Android VM uses a different bytecode format than the JVM

noisesmith19:10:16

I suspect making 1.9 work wouldn't be any harder than making 1.3 work, both would involve editing clojure.core by hand though

noisesmith19:10:34

iirc clojure-android is stuck on 1.6?

dpsutton19:10:09

the asm lib would have to be downgraded then i suppose

zilti19:10:56

Is the asm lib capable of putting out ART VM bytecode though? Though it's probably easier to just wait until the Gluon VM (based on OpenJDK) is available for Android, which could be soon

noisesmith19:10:58

oh, at some point it upgraded to 1.7

zilti20:10:44

Looks like I'll have to use another language for my Android plans 😕

deliciousowl20:10:27

yeah I wanted to use clojure for android too 😞

zilti20:10:12

JavaFXPorts is quite phenomenal, that'd be great.

zilti20:10:43

Like, you can create an application with a JavaFX GUI that runs on all platforms without changing a single line of code. Now all that's needed is a Clojure that can run on the Android VM

lilactown20:10:50

I think we need to bribe the React Native team to decouple their bundler from the rest of the project

lilactown20:10:19

then we could plug in our CLJS toolchain a lot easier

rickmoynihan21:10:27

what are people using to program server side websockets in clojure these days? I’d prefer something that can work alongside ring/jetty, so preferably with a jetty backend… but open to other options e.g. pedestal, if they’re more mature

jsa-aerial21:10:12

You could take a look at https://github.com/jsa-aerial/hanasu which was done to have a very lightweight websocket protocol. I've used it in a few things now. It is much simpler than sente which I came to see as heavily complected and heavyweight.

rickmoynihan21:10:58

yeah the defs in a let bind over a channel socket are a bit crazy… obviously you don’t have to do it that way, but that seems a pretty hacky to me.

rickmoynihan21:10:55

I should probably look at the implementation before I judge it too harshly though…

jsa-aerial21:10:13

Among other many other things.

rickmoynihan21:10:14

thanks for sharing hansu, will take a look at that too

jsa-aerial21:10:23

It is very simple and straight forward. You can look at https://github.com/jsa-aerial/hanami for an example use case (where client is cljs)

rickmoynihan21:10:57

hanami looks interesting… it looks like you’ve implemented an idea we had but never did — lol 🙂

rickmoynihan21:10:41

vega/vega-lite clj(s) data driven charting… was wondering if you’d thought of using clojure spec for the datastructures?

jsa-aerial21:10:44

Hanami is very cool, thanks! For an example app built on Hanami see https://github.com/jsa-aerial/saite

jsa-aerial21:10:08

No, the templates are just typical nested datastructures, whose only 'requirement' is that upon full transformation the result is a legal VG or VGL spec

jsa-aerial21:10:33

There is a VGL (maybe also VG?) spec based validation system in Clj/Cljs but I don't recall off top my head the name just now

jsa-aerial21:10:55

Also, the examples directory in Hanasu has some very simple example toy apps.

rickmoynihan21:10:59

anyway we digress 🙂

jsa-aerial21:10:04

The idea of parameterized templates is rather more expressive than a spec based thing - at least on first thoughts about that.

dadair21:10:17

I use pedestal for ws at work

rickmoynihan21:10:43

was also wondering if anyone has done any websocket stuff with ring async handlers

enforser21:10:54

We use sente

rickmoynihan21:10:19

ahh yes sente I’ve been to this page before thanks, will take a look in more detail.

Audrius22:10:06

why (take 5 (repeat "x")) gives some lazy sequence when in (str "9" (doall(take 5 (repeat "x")))) or in (str "9" (take 5 (repeat "x"))) what is the deal with lazyness and how it works.

ClashTheBunny22:10:02

@zilti, did you try GraalVM and run it as a native app?

noisesmith22:10:55

@audrius try wrapping the take in pr-str

noisesmith22:10:19

the toString of lazy-seqs forces the collection, but prints in a weird and mostly useless way

noisesmith22:10:31

if you use pr-str instead you get a more reasonable printed form

noisesmith22:10:11

user=> (str (take 5 (range)))
"clojure.lang.LazySeq@1b554e1"
user=> (pr-str (take 5 (range)))
"(0 1 2 3 4)"

csm22:10:38

also, doall returns the same coll that was passed in, after calling dorun, so you get a lazy-seq back, but with the items forced

noisesmith22:10:01

doall doesn't change the type, it merely ensures the elements are realized

Audrius22:10:39

but how do I get \9 with 5 \x ?

csm22:10:16

clojure.string/join?

noisesmith22:10:30

user=> (str "9" (pr-str (take 5 (repeat "x"))))
"9(\"x\" \"x\" \"x\" \"x\" \"x\")"
user=> (print *1)
9("x" "x" "x" "x" "x")nil

noisesmith22:10:13

you might also find the format function useful

Audrius22:10:14

and join them into string?

noisesmith22:10:25

str joins all its args into a string

noisesmith22:10:47

what do you want the output string to actually look like?

noisesmith22:10:12

user=> (apply str "9" (take 5 (repeat "x")))
"9xxxxx"
- maybe this is what you want though

tristefigure22:10:29

Is there any reason for wanting to print lazy sequences like this ?

tristefigure22:10:14

also:

user=> (str "9" (seq (take 5 (repeat "x"))))
"9(\"x\" \"x\" \"x\" \"x\" \"x\")"

noisesmith22:10:31

there are many data types that print toString similarly

user=> (str (byte-array [0 1 2]))
"[B@6c81fb4c"

hiredman22:10:13

that specifically is not "printing" the lazy seq

hiredman22:10:28

str is not printing (pr or println)

hiredman22:10:17

there is no single .toString (which is what str calls) implementation for lazy seqs

hiredman22:10:25

there is a single pr implementation for lazy seqs

hiredman22:10:43

user=> (str (range 10))
"(0 1 2 3 4 5 6 7 8 9)"
user=> (str (map inc (range 10)))
"clojure.lang.LazySeq@c5d38b66"
user=> 

dpsutton22:10:36

range is a special beast isn't it? or does it return a standard lazy seq

hiredman22:10:50

it is a lazy seq

rickmoynihan22:10:45

It’s actually an instance of clojure.lang.Iterate, but it implements the lazy-seq interfaces

rickmoynihan22:10:46

It used to actually be a lazy-seq; but I think they changed its implementation for performance reasons… can’t recall which clojure version

hiredman22:10:11

lazy seqs are describe by an interface, so they cannot dictate the behavior of toString for every implementation

hiredman22:10:22

so it doesn't even try

hiredman22:10:22

pr is abased on a multimethod so it can have a behavior for objects are instances of a class that implement an interface

dpsutton22:10:45

what is the lazy seq interface?

tristefigure22:10:56

>that specifically is not "printing" the lazy seq >str is not printing (pr or println) Agreed. However, consider this:

user=> (.toString (seq [1 2 3]))
"(1 2 3)"
user=> (.toString (lazy-seq [1 2 3]))
"clojure.lang.LazySeq@7861"
Against this
user=> (pr (seq [1 2 3]))
(1 2 3)nil
user=> (pr (lazy-seq [1 2 3]))
(1 2 3)nil
I don't like this lack of symmetry. All the more so that:
user=> (.toString (range 1 10))
"(1 2 3 4 5 6 7 8 9)"
user=> (.toString (range))
^C (takes forevers)

hiredman22:10:37

what are you calling lack of symmetry?

dpsutton22:10:57

thanks @hiredman i was confused for a second if there was a different interface for lazy seqs or if it was just ISeq

rickmoynihan22:10:25

also I guess clojure.lang.IRealized if you care about it not just being a sequence. Though this isn’t much used.

tristefigure22:10:33

We can consider clojure.lang.LazySeq to be informally lazy, along with clojure.lang.Iterate and other constructs returned by range ; although they do not have a formal link via a parent class or interface, they follow the same semantics (at least to keep the surprise rate low on the programmer's side). What I observe is that .toString:

user=> (.toString (clojure.lang.Iterate/create inc 0))
^C (takes forevers, i.e. that lazy seq is being realized)
user=> (.toString (clojure.lang.LongRange/create 10))
"(0 1 2 3 4 5 6 7 8 9)"
user=> (.toString (clojure.lang.Range/create 10))
"(0 1 2 3 4 5 6 7 8 9)"
But (and this is where the symmetry breaks)
user=> (.toString (lazy-seq [1 2 3]))
"clojure.lang.LazySeq@7861"

👍 4
rickmoynihan22:10:22

Hmmm… actually I think I’m wrong in my pedantry 🙂 realized? isn’t actually implemented on all the appropriate “lazy seq like types”… e.g. (realized? (range)) ;; => true but (realized? (range 10)) ;; => ClassCastException clojure.lang.LongRange cannot be cast to clojure.lang.IPending clojure.core/realized? (core.clj:7453)

rickmoynihan22:10:37

is this a bug?

hiredman22:10:11

realized? is useless nonsense outside of maybe using it with promises

rickmoynihan23:10:04

yeah I’ve always struggled to see the use of it for sequences. When I first saw it I thought it might indicate whether a sequence was “fully realized”, i.e. it might’ve had some use as a debugging aide to let you know whether you’re getting cached results or new ones from a lazy-seq… but it doesn’t seem to do anything even half sensible for lazy-seqs.

gfredericks22:10:05

;; deadlock with nested alter-var-roots, just for fun
(let [f1 (future
           (alter-var-root #'a
                           (fn [a]
                             (Thread/sleep 100)
                             (alter-var-root #'b
                                             (fn [b] (+ b a))))))
      f2 (future
           (alter-var-root #'b
                           (fn [b]
                             (Thread/sleep 100)
                             (alter-var-root #'a
                                             (fn [a] (+ b a))))))]
  ;; two futures that never complete
  [f1 f2])

hiredman22:10:41

ugh, what horrible things are people doing that they are hooking things concurrently

tristefigure23:10:22

What horrible thing ? Hooking isa? & instance? to implement absolutely transparent delegates. But I might strike some luck overriding the getClass method on the delegation wrapper. Since this method is final I'll have to edit its bytecode with javassist. https://media.giphy.com/media/3oEduRygZtVxloohws/giphy.gif

gfredericks00:10:18

yep, those things are all Fine

andy.fingerhut00:10:40

Teacher! Gary's hurting my mind again!

andy.fingerhut01:10:28

And you may be interested to know that your Github page was the second link I found when doing a search for gfredericks on Google.

hiredman01:10:21

Instance? Has a compiler intrinsic, so if you are trying to hook that you are in for a surprise

hiredman01:10:41

Also, you seem to not have noticed the word "concurrently" in my message expressing

danielneal09:10:18

you clojure guys take halloween to the next level

gfredericks14:10:40

@U0CMVHBL2 what was the first thing?

andy.fingerhut14:10:47

Fredericks of Hollywood

gfredericks16:10:07

dang those people