Fork me on GitHub
#clojure
<
2019-05-06
>
vlaaad05:05:40

What is the use case of type function when there is class? When it's useful to put :type on something's metadata?

mpenet08:05:20

since you can "type" anything supporting metadata I guess one answer could be that it's useful with multimethods dispatching via (type ... )

๐Ÿ‘ 4
vlaaad08:05:54

oh, makes sense

Ivan Koz18:05:09

is there any book or written series about clojure compiler?

Alex Miller (Clojure team)18:05:57

wish I had the time to write such a thing :) in a broad sense, the clojure compiler is just translating a relatively small set of possible expressions to java bytecode, and as such is pretty simple as far as compilers go

the2bears18:05:28

I would buy this day one ๐Ÿ™‚

Alex Miller (Clojure team)18:05:58

well, don't hold your breath

๐Ÿ‘ 4
Alex Miller (Clojure team)18:05:53

there's essentially no optimization - really Clojure leans on the JIT rather than doing much itself

Alex Miller (Clojure team)18:05:30

fortunately, the jvm is pretty great at it

lilactown18:05:44

the defn podcast with the guy working on ClojureCLR was super interesting. he went into differences between JVM and CLR and how one could optimize things for one over the other

๐Ÿ‘‚ 4
valtteri18:05:50

This was really good

Ivan Koz18:05:01

yeah i've seen this one few days ago

ghadi18:05:16

The nice thing about the clojure compiler is that it's a one pass translator to bytecode

oz18:05:13

Anyone else have this issue? I'm using the Clojure CLI and have dependency that is a git repo. If I try to update the sha I get this error.

Destination path "my-repo" already exists and is not an empty directory
org.eclipse.jgit.api.errors.JGitInternalException: Destination path "my-repo" already exists and is not an empty directory
.

oz18:05:34

I'm also having a hard time finding exactly where the code gets checked out.

ghadi18:05:00

I've had that error before and I haven't been able to pinpoint it, but I remember something about auth

ghadi18:05:16

All the files go in .gitlibs @ozanzal

CyberSapiens9718:05:46

Hello guys, i'm writing tests for an async function that uses future But in order to test it, i need to know when the background process have finished, but because it's async i have a return value right when i call it. How can i handle this situation?

Ivan Koz18:05:08

@cybersapiens97 check future-done? function

noisesmith18:05:40

there's also realized?

Ivan Koz18:05:01

whats the difference?

noisesmith18:05:07

I think realized? is more general though (but I've heard multiple warnings about using it on lazy things)

noisesmith18:05:19

realized? works on promises, delays, futures, and lazy-seqs

noisesmith18:05:31

and from what I hear, using it on lazy-seqs is a bad code smell

Ivan Koz18:05:36

i mean if we have realized why do we have more specific future-done?

noisesmith18:05:13

principle of least power I guess - also it uses the java Future api, and not the IPending api so it works on java futures, not just clojure's specific implementation of futures

noisesmith18:05:02

every clojure future isa java.util.concurrent.Future, but not every j.u.c.Future is a clojure future

CyberSapiens9718:05:17

well, i can use future-done? but still i have to supply a Thread/Sleep ? or i can use something like this await-for ?

noisesmith18:05:57

@cybersapiens97 what do you want to do if the future takes to long?

Ivan Koz18:05:59

realized is bound to be used for IPending implementors

noisesmith18:05:12

if you always want to wait for it, just use deref / @

noisesmith18:05:21

if you want to timeout, that's an optional arg to deref

CyberSapiens9718:05:30

@noisesmith nothing, the test will fail i guess

noisesmith18:05:33

in neither case do you actually need to explicitly check if it is realized

noisesmith18:05:16

@cybersapiens97 then I'd use deref, with the timeout arg (how long is too long? probably more than 0 ms...) then use the timed-out value as your failure condition in the check

noisesmith18:05:44

@cybersapiens97

(ins)user=> (let [f (future (Thread/sleep 1000) ::OK)] (deref f 500 ::failure))
:user/failure
(ins)user=> (let [f (future (Thread/sleep 1000) ::OK)] (deref f 5000 ::failure))
:user/OK

Ivan Koz18:05:55

was about to write that snippet ๐Ÿ˜„

CyberSapiens9719:05:54

so, deref waits for the future to be done?

Ivan Koz19:05:06

yes it blocks

noisesmith19:05:11

yes, by default it blocks, but with the extra arg it has a timeout

noisesmith19:05:35

there's also future-cancel, if you know your code calls some cancellable method

CyberSapiens9719:05:45

nice to know, async is something i didn't really used before on clojure or other langs

Ivan Koz19:05:25

try core.async also, it provides a nice way to build concurrent applications

CyberSapiens9719:05:08

don't think i need that much, it was just a function that needed to be async because it's just a HTTP response 201, Accepted and being processed

CyberSapiens9719:05:51

(deftest download-musics--return-file-string
  (let [result (deref (core/download-musics test-links) 180000 ::failure)
        _      (shell/sh "unzip" result :dir core/resources-folder)]
    (is (string? result))
    (is (.exists (io/as-file (str core/resources-folder result))))
    (is (= (+ 1 (count test-links)) ;; This is because file-seq add's the own arg folder at the beginning of the seq
           (count (file-seq (io/file (str core/resources-folder (subs result 0 (- (count result) 4))))))))))


Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.util.concurrent.Future (java.lang.String and java.util.concurrent.Future are in module java.base of loader 'bootstrap')
@noisesmith what i'm doing wrong here?

Jimmy Miller20:05:08

Can you post the source of core/download-musics?

Joe Lane19:05:15

Does core/download-musics return a ref or a string?

Joe Lane19:05:10

The error message youโ€™re getting is because youโ€™re trying to treat a string (the result) as a ref (like an atom)

CyberSapiens9719:05:49

but i can't really change the behavior of this function and it's output, guessing if i could make a wrapper that returns some kind of ref?

lilactown19:05:31

you can change download-musics but not the deftest?

CyberSapiens9719:05:34

i can change deftest but not download-musics

CyberSapiens9719:05:35

it's output goes directly to a handler that returns an HTTP response based on it, and using a ref as return value would break the response pattern that i'm using for all my functions

lilactown19:05:08

why does the deftest try and deref it?

CyberSapiens9719:05:41

because download-musics is async and i need to wait the background process to finish

CyberSapiens9719:05:19

deref blocks the main thread until it's done, but i didn't know that it expects a ref, or, i knew it but i forgot ๐Ÿ˜ž

lilactown19:05:24

according to the error, you don't

lilactown19:05:41

it's returning a string. not a future

CyberSapiens9719:05:14

yes, because i need an immediate response from this function, in this case, a string

CyberSapiens9719:05:28

i'm struggling to write a test for it

lilactown19:05:04

it sounds like you should remove the deref

lilactown19:05:22

I dont' really understand what's going on. are you redefing the download-musics to just return a string or something?

CyberSapiens9720:05:20

download-musics is an async function, which returns a string. Inside it's body, there is a future, to do the background work (download the musics), but i need an immediate response of where this musics are going to be stored, so it returns the string (the name of the zip file that will be created). all i need is to write a test that waits the completition of the future inside it's body, so i can test it propperly

CyberSapiens9720:05:42

guess i'll need to write a simple Thread/Sleep for now, just to write the test and refactor it later

lilactown20:05:07

no idea. either download-musics returns a string synchronously, or it returns a future that resolves with a string. I donโ€™t understand your test

noisesmith20:05:19

@cybersapiens97 one pattern for what you are doing is to return a hash-map, eg. {:f the-future :s the-string} so a client can use the parts of the result that matter

๐Ÿ‘ 4
noisesmith20:05:46

if the consumer needs a string, you can make a thin wrapper that just pulls the string out, but you can use the real return value in your test

noisesmith20:05:04

you don't really need a unit test for a function that does nothing but a single key lookup

ivana21:05:59

Sorry for silly question, but can you suggest me, what project I can create and share on github, to make any interest to my person as a remote employee (keeping in mind, that I live in Russia). If it is possible, of course ๐Ÿ™‚