Fork me on GitHub
#clojure
<
2020-04-02
>
Akiz06:04:10

Hi everybody, can you help me here? How to have different main for every lein profile? I have got one -main function for DEV and one for TEST.

... 
 :profiles {:dev [:project/dev :profiles/dev]
             :test [:project/test :profiles/test]
             :profiles/dev {}
             :profiles/test {}
             :project/dev {:main xbimonitor2.dev
                           :source-paths ["src/clj"]}
             :project/test {:main xbimonitor2.core
                            :source-paths ["src/clj"]}
             :user {:plugins [[lein-classpath-jar "0.1.0"]]}}
  :source-paths ["src/clj"]
  :resource-paths ["resources"]
  :repl-options {:init-ns xbimonitor2.core}
  :plugins [[lein-environ "1.1.0"]
            [lein-cljsbuild "1.1.7"]]
  :cljsbuild {:builds
              [{:id "default"
                :source-paths ["src/cljs"]
                :compiler {:output-to "resources/public/js/main.js"
                           :optimizations :whitespace
                           :pretty-print true}}]}
  :main xbimonitor2.core)
When I run
lein with-profile dev run 
It will run xbimonitor2.core and not xbimonitor2.dev. What am I doing wrong? Thanks!

otwieracz08:04:45

Is my understanding correct, that adding (require '[clojure.tools.trace :refer [trace-vars untrace-vars]]) to :injections in Lein should make those two functions available in every namespace in every project?

vlaaad08:04:51

no, it affects only namespace that is current when injections are executed

vlaaad08:04:22

I don’t know lein’s semantics for injections, my guess is that’s a user namespace

kaffein09:04:29

hey guys, I have a quick question related to java interop please : I am playing with a Google text to speech now and I have the following code ;

(let [...
      recognize-response (recognize speech-client config audio)
      _ (log/info (class recognize-response))
      speech-recognition-results (.getResultsList recognize-response)
      _ (log/info (class speech-recognition-results))]
  speech-recognition-results)
the related output for this is :
20-04-01 16:25:05 bigbeast INFO [backend.google:9] - class com.google.cloud.speech.v1.RecognizeResponse
20-04-01 16:25:05 bigbeast INFO [backend.google:11] - class java.util.Collections$UnmodifiableRandomAccessList
=>
[#object[com.google.cloud.speech.v1.SpeechRecognitionResult
         0x5ceda460
         "alternatives {\n  transcript: \"skildre\"\n  confidence: 0.7400255\n}\n"]]
My issue is : :thinking_face: the first log line is displaying the correct class com.google.cloud.speech.v1.RecognizeResponse I am retrieving from the call to recognize fn :
20-04-01 16:25:05 bigbeast INFO [backend.google:9] - class com.google.cloud.speech.v1.RecognizeResponse
but then, when calling (.getResultsList recognize-response), I am supposed to get back a List<SpeechRecognitionResult>, instead what I have is a log line displaying :
20-04-01 16:25:05 bigbeast INFO [backend.google:11] - class java.util.Collections$UnmodifiableRandomAccessList
which is exactly the problem since I have to extract some infos from this List<SpeechRecognitionResult>. Is there something I am missing ? Do I have to type-hint/coerce something somewhere ?

hindol09:04:49

You are still getting back a list, which is a good thing. Did you try logging the contents of the list?

kaffein09:04:48

I have found a solution 😉 from an old post on clojurians https://clojurians-log.clojureverse.org/clojure-uk/2016-07-15

kaffein09:04:12

I had to coerce the UnmodifiableRandomAccessList with seq

kaffein09:04:28

thanks a lot anyway @UJRDALZA5

hindol10:04:49

Usually seq need not be called explicitly. A lot of the core functions internally call seq when needed. For debugging purposes, you can call pr-str on it, this is similar to calling .toString() in Java.

👍 4
hindol10:04:58

There is also str.

emccue17:04:04

Well, strictly speaking List<SpeechRecognitionResult> is just what the java api guarantees. java.util.Collections$UnmodifiableRandomAccessList implements List and at runtime generics are erased. So that is correct

emccue18:04:05

So you should be all set to go without any conversions. Most builtin functions will work, and failing that you can use the ones on List that are supported

👍 4
🙏 4
Fredrik Meyer10:04:58

Maybe a beginner question: I'm trying to use clojure.tools/logging for logging. I found this blog post explaining what to do, except that I'm using version 2.13.1 of Log4j. Here's my project.clj:

(defproject chat-app "0.1.0-SNAPSHOT"
   .....
  :dependencies [[org.clojure/clojure "1.10.0"]
                 ;; Logging ()
                 [org.clojure/tools.logging "1.0.0"]
                 [org.apache.logging.log4j/log4j-core "2.13.1" :exclusions [javax.mail/mail
                                                    javax.jms/jms
                                                    com.sun.jmdk/jmxtools
                                                    com.sun.jmx/jmxri]]
             .....
                 ]
  :main ^:skip-aot chat-app.core
  :target-path "target/%s"
  :jvm-opts ["-Dclojure.tools.logging.factory=clojure.tools.logging.impl/log4j2-factory"]
  :profiles {:prod {:resource-paths ["config/prod"]}
             :dev {:resource-paths ["config/dev"]}
             :uberjar {:aot :all}
             }
  )
I have a log4j.properties file identical to the one in the blog post. However, when I try to log anything, only nil is returned. No log file is created either.

ataggart16:04:54

The linked page isn't opening for me, but this is what I use:

Spaceman12:04:30

Hi, suppose I have an array list created like so (def some-array-list (ArrayList.)), and it itself contains array-lists. I want to sort this some-array-list based on the first elements of the constituent array lists. How can I do that?

hindol12:04:29

In Clojure at least, sorting a list of lists happens in that order. Compare first elements, if there is a tie, compare second elements and so on.

hindol12:04:50

I mean with Clojure lists.

Spaceman12:04:45

This is what I'm doing but it's really slow:

(defn largest-area-contour [contours hierarchy]
  (loop [contour-index 0 largest-area-contour [0 0 0]]
    (if-not (< contour-index (.width hierarchy))
      largest-area-contour
      (recur
       (inc contour-index)
       (let [contour (nth (vec contours) contour-index)
             contour-area (->
                           contour
                           (cv/contour-area))]
         (if (< (nth largest-area-contour 1) contour-area) ;; sort based on the second element 
           [contour contour-area contour-index]
           largest-area-contour))))))

hindol12:04:18

Did you try Collections/sort?

Spaceman12:04:45

it would use a comparator, but I don't know how to create an instance of a comparator in clojure

hindol12:04:19

You are doing so much Java interop, you run the risk of unintentionally converting data structures back and forth. Making the program very slow.

Spaceman12:04:34

I don't know what else to do. I

hindol12:04:39

Is this production code or a hobby project?

Spaceman12:04:40

I'm using opencv

Spaceman12:04:58

production. I can share the whole file with you:

hindol12:04:14

Did you look at projects like these? https://github.com/hellonico/origami

Spaceman12:04:44

Yes I'm using origami but it seems to lack basic matrix operations.

Spaceman12:04:10

like I couldn't find a way to multiply a Mat. with a scalar.

Spaceman12:04:30

so I created my own function

(defn ->mat [vector type]
  (let [mat (Mat. (Size. (count (nth vector 0)) (count vector)) type)]
    (doseq [x (range (.width mat))
            y  (range (.height mat))
            :let [data1 (nth (nth vector y) x)]]
      (.put mat
            (int y) (int x)
            (double-array data1)))
    mat))
To convert the Mat into a clojure vector and a similar ->vec function for the opposite.

hindol12:04:50

I don't know enough about image processing etc. to comment on what is the best approach.

hindol12:04:13

But I can help with the comparator.

Spaceman12:04:13

okay. So an array list of array lists and need to sort by the i'th elements of the constituent array lists.

Spaceman12:04:31

what does the (defn sort [array-list] ...) look like?

hindol12:04:14

I recommend going the Collections/sort route and creating a comparator with reify.

Spaceman12:04:49

How to create a comparator with reify?

hindol12:04:53

I am trying it out in my REPL.

hindol12:04:01

So this works, but only compares the first element,

(sort (comparator (fn [x y] (< (.get x 0) (.get y 0))))
      [(java.util.ArrayList. [3 1 2]) (java.util.ArrayList. [1 2 3])])
;; => ([1 2 3] [3 1 2])

hindol12:04:48

Here x and y are your ArrayLists.

Spaceman12:04:50

So for second, it would be

(sort (comparator (fn [x y] (< (.get x 1) (.get y 1))))
      [(java.util.ArrayList. [3 1 2]) (java.util.ArrayList. [1 2 3])])
right?

emccue17:04:11

(`sort-by first [(java.util.ArrayList. [3 1 2]) (java.util.ArrayList. [1 2 3])])`

emccue17:04:45

comparators are neat but when possible, a key function is alot clearer

hindol18:04:10

True, but what I was aiming for is a Clojuresque sort, where the tie is broken by comparing the next element and without converting the whole list to a Clojure PersistentList.

hindol18:04:15

Though I did not complete it.

emccue18:04:46

(sort-by vec ...) obviously is the quickest way

emccue18:04:06

but does quite a bit of copying

emccue18:04:15

public int compareTo(Object o){
	IPersistentVector v = (IPersistentVector) o;
	if(count() < v.count())
		return -1;
	else if(count() > v.count())
		return 1;
	for(int i = 0; i < count(); i++)
		{
		int c = Util.compare(nth(i),v.nth(i));
		if(c != 0)
			return c;
		}
	return 0;
}

emccue18:04:43

this is what is in the definition for APersistentVector

emccue18:04:25

give me a moment

emccue18:04:42

(defn vector-ish-comparator 
  ([]
   (vector-ish-comparator (Comparator/nullsFirst
                            (Comparator/naturalOrder))))
  ([item-comparator]
   (reify Comparator
     (compare [_ a b]
       (cond 
         (< (count a) (count b))
         -1
         
         (> (count a) (count b))
         1
         
         :else
         (loop [i 0]
           (if (>= i (count a))
             (let [comparison-result (.compare item-comparator
                                               (nth a i)
                                               (nth b i))]
               (if (= comparison-result 0)
                 (recur (inc i))
                 comparison-result))
             0)))))))

emccue18:04:50

untested but that feels right

deas15:04:40

Why does running clj doall.cljon (doall (pmap print (range 10)))take so long until the process terminates?

deas15:04:21

That did the trick! thanks!

4
andy.fingerhut15:04:54

The http://ClojureDocs.org page for pmap briefly mentions this, and refers to the page on future where there is a much longer explanation of why, and what to do about it.

4
restenb15:04:52

my brain is stuck. would this be correct for an "inner" multi-arity function?

lukasz15:04:01

(defn foo
 ([a] #_more )
([a b] #_more_here ))

lukasz15:04:07

@rslkvk oh, sorry - I see what you're asking about now

restenb15:04:28

i read my only code and just feel something is missing 😛

lukasz15:04:41

how do you know which function to return?

lukasz15:04:49

for me it's missing an if ;-)

restenb15:04:16

i know there's a way to write this I just can't remember

restenb15:04:25

that function will either be called with 1 or 3 params

restenb15:04:39

the returned function that is

restenb15:04:25

i'm stupid. the correct code is of course

lukasz15:04:33

(defn wrap-something
  ([handler]
   (fn [req]
     (handler req)))
  ([handler res next]
   (fn [req res next]
     (handler req res next))))

lukasz15:04:36

something like this?

deas15:04:34

One more: Doing just (println "Executed job " i)from various threads concurrently. How come I see multiple Executed jobs on a single line? What's the suggested way to get around.

andy.fingerhut15:04:36

I don't have a workaround handy. I believe the reason is simply that println is not atomic.

andy.fingerhut15:04:59

Logging libraries tend to provide atomicity for "separate log messages"

deas15:04:37

Building the string, and doing (print str)(flush) worked iirc. But looked ugly. 😉

victorb17:04:47

I'm pretty sure I've worked around this in the past by using an atom + clojure.lang.PersistentQueue + add-watch

👍 4
restenb15:04:36

nah res & next are not known, they are passed by the outside callers

restenb15:04:47

to the returned inner function

lukasz15:04:34

yep, that should work then either (wrap-something my-handler) or (wrap-something my-handler res next)

Ben Grabow15:04:16

(defn wrap-something [handler]
	(fn ([req]
		 (handler req))
	    ([req res next]
		 (handler req res next))))

Ben Grabow15:04:40

Your parens were almost in the right place

restenb15:04:18

yeah, I could sense something was missing but my brain was stuck 😛

Spaceman21:04:25

I have a simple python file hello.py with contents: `print("Hello World")`, and when I try to run this from the REPL using `(sh "python3 hello.py")`, I get 

Execution error (IOException) at java.lang.UNIXProcess/forkAndExec (UNIXProcess.java:-2).
error=2, No such file or directory
Obviously the program runs when I run python3 hello.py in the shell. How do I run a python file from the repl?

seancorfield21:04:30

(sh "python3" "hello.py") perhaps?

Spaceman21:04:04

Yes, that worked. Also, would this work on heroku?

Spaceman21:04:33

like I want to run some python code and get some data from it on the server. Can I do that on heroku?

seancorfield21:04:57

If python3 is on your path in the Heroku environment, probably...

Spaceman21:04:25

I don't know if it is and I don't know how to find out.

seancorfield21:04:32

Try it and see...

phronmophobic21:04:12

are you using pure python libraries? you may find it easier to “embed” python using jython than running it via shell

seancorfield21:04:19

Or perhaps look at the libpython-clj thing?

👍 12
☝️ 12
emccue22:04:23

clojure is the only language i can think of where it is feasible to have a perfectly idiomatic file using -kebab-case, snake_case, camelCase and PascalCase all at once

emccue22:04:14

libpythonclj makes that happen for better or for worse

emccue22:04:29

(i'd say for no consequence)

Spaceman23:04:55

Hi, I'm trying to display an image in the client, so I'm sending it like so as an input stream: (res/response (io/input-stream "img.jpg")), but it doesn't work in the client. I get "no reader function for tag object"

noisesmith23:04:40

is this ring?

noisesmith23:04:21

I thought that ring could handle input-stream - you might need to change that to {:body (io/input-stream "img.jpg") :headers {} :status 200}

noisesmith23:04:33

you might also end up wanting to set content type in the headers etc.

rutledgepaulv23:04:40

Sounds like a client side issue of trying to read an object tagged literal because something is serializing a Java object like an input stream into edn

rutledgepaulv23:04:53

Would have to decide if you want edn with base 64 or a byte stream

noisesmith23:04:01

if you give ring a file or an input stream in the way it likes, it handles all this for you

hiredman23:04:45

Assuming you don't have a middleware pr-str'ing the body for some reason

Spaceman23:04:55

it works now. In fact I wasn't wrapping in res/response but something else.

Spaceman23:04:20

What's the simplest way to show that input-stream as the src of an image tag, convert to base64 or a blob?

rutledgepaulv00:04:58

Simplest way is to just serve the image byte stream from an endpoint and have the browser use that endpoint as the src. If you need to download the bytes to the client yourself and then load them into an image element you can send it over the wire as base64 and then load it as a data url or blob

Spaceman00:04:40

how to serve the image as a byte stream?

Spaceman00:04:56

there's is an io/input-stream but no io/byte-stream

rutledgepaulv00:04:03

An input stream is a steam of bytes. If you return an input stream to ring it will send those bytes as the body. You should specify a content type header to help the browser interpret it as an image.

Spaceman00:04:49

but I don't see the image when I put the (:body response) as its src

Spaceman00:04:24

yes I have the header as image/jpeg

rutledgepaulv00:04:35

In the scenario of returning the image from the server you would just set the image src tag to the path the server is serving the image at. Like src="/myimage"

rutledgepaulv00:04:10

And let the browser make the request and consume the response instead of using an http client lib

Spaceman23:04:54

What's the simplest way to do that. Like (convert-to-blob-or-base64 my-input-stream)

Spaceman23:04:03

What's the convert-to-blob-or-base64 function?

noisesmith23:04:08

if you use the file-response function and hand it a File object ring should do the rest for you

noisesmith23:04:17

based on the file extension iirc

Spaceman23:04:02

what if I must send an input stream?

rutledgepaulv23:04:07

@pshar10 these questions might be better suited for #beginners

4