Fork me on GitHub
#clojure
<
2018-01-17
>
cfleming00:01:03

Is there any difference between (sequence (filter query-var?) (iterate/tree form)) and just (filter query-var? (iterate/tree form)) where iterate/tree returns an IReduceInit?

noisesmith00:01:07

the second one should create a lazy-seq from (iterate/tree form) before filtering - I wouldn’t expect the return value to be different though

cfleming00:01:56

I see, so sequence creates a seq directly, and is potentially slightly more efficient then?

noisesmith00:01:26

yeah - and also - corner case - if it implemented IReduceInit and not ISeq the former would work and the second one would fail

noisesmith00:01:47

but I expect that to be rare ,most things that implement IReduceInit should also give you something you can seq…

cfleming00:01:00

Ok, seq doesn’t automatically handle IReduceInit? Interesting.

noisesmith00:01:11

ummm let me double check that

cfleming00:01:12

No, this one doesn’t, it’s my own concoction.

noisesmith00:01:25

oh it would make sense to implement ISeq too unless you know the only consumer is a transducing context

cfleming00:01:59

seq doesn’t handle IReduceInit, which makes sense.

noisesmith00:01:21

I was just double checking, thanks for confirming

cfleming00:01:55

Well, I’m looking at moving most of Cursive’s internal iteration over to transducers so I’m not worried. Implementing ISeq might be useful too, although I think I’d prefer a fail fast in case I’m accidentally using a seq where I didn’t mean to.

noisesmith00:01:24

that makes sense too, might call for a cautionary doc string or whatever but yeah

cfleming00:01:33

One interesting thing is that seq checks instanceof ASeq and not ISeq

noisesmith00:01:51

maybe ISeq implements ASeq?

cfleming00:01:14

No, ASeq is the concrete implementation of ISeq

hiredman00:01:46

ISeq extends IPCollection which extends Seqable

cfleming00:01:06

Right, it seems like Seqable would be the better interface to implement.

cfleming00:01:13

I’m still surprised that seq checks for ASeq and not ISeq, though - I’m not sure what the thinking is there.

hiredman00:01:34

in general, I don't implement ISeq or Seqable for things I want to process with reduce, which tend to be about controlling backing resource scope, like a collection representing the lines from a file

cfleming00:01:42

Yeah, my plan is to move to reduce for pretty much everything I do internally, seqs don’t actually add much value since I’m operating over an AST which is all in memory anyway.

cfleming00:01:23

Actually, sequence can’t be used as I showed above since it still expects a sequable thing as the coll, which makes sense.

cfleming00:01:52

@noisesmith So the correct answer is that they both do the same thing - fail 🙂

noisesmith00:01:15

oh wow - I would have expected sequence to work

cfleming00:01:56

Well, if you think about it, converting an IReduceInit to a seq is impossible without fully reducing - they’re different iteration models (push vs pull, if you like)

noisesmith01:01:07

oh right, you can use a reduce to get a collection from it, but only eagerly so

qqq04:01:35

(ct/is (thrown? AssertionError (assert false)))
does not work as expected. I want a test that says "this piece of code fails due to an assertion [I don't care which exception in particular]"

qqq05:01:53

According to https://clojure.github.io/clojure/clojure.test-api.html (ct/is (thrown? java.lang.ArithmeticException (/ 1 0))) is supposed to work. Instead, I get:

(comment
 ]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invokeStatic "core.clj" 657]
  [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1965]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1965]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 85]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 55]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__1186$fn__1189 invoke "interruptible_eval.clj" 222]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__1181 invoke "interruptible_eval.clj" 190]
  [clojure.lang.AFn run "AFn.java" 22]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1149]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 624]
  [java.lang.Thread run "Thread.java" 748]]})
(comment
 #error {
 :cause "Divide by zero"
 :via
 [{:type java.lang.ArithmeticException
   :message "Divide by zero"
   :at [clojure.lang.Numbers divide "Numbers.java" 163]}]
 :trace
 [[clojure.lang.Numbers divide "Numbers.java" 163]
  [clojure.lang.Numbers divide "Numbers.java" 3833]
  [aa.abcd$eval8596 invokeStatic "NO_SOURCE_FILE" 31]
  [aa.abcd$eval8596 invoke "NO_SOURCE_FILE" 31]
  [clojure.lang.Compiler eval "Compiler.java" 7062]
  [clojure.lang.Compiler eval "Compiler.java" 7025]
  [clojure.core$eval invokeStatic "core.clj" 3206]
  [clojure.core$eval invoke "core.clj" 3202]
  [clojure.main$repl$read_eval_print__8572$fn__8575 invoke "main.clj" 243]
  [clojure.main$repl$read_eval_print__8572 invoke "main.clj" 243]
  [clojure.main$repl$fn__8581 invoke "main.clj" 261]
  [clojure.main$repl invokeStatic "main.clj" 261]
  [clojure.main$repl doInvoke "main.clj" 177]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__1141 invoke "interruptible_eval.clj" 87)

gonewest81805:01:40

@qqq - works for me only inside deftest, e.g. this fails:

$ lein repl
nREPL server started on port 62317 on host 127.0.0.1 - 
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_112-b16
    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=> (require '[clojure.test])
nil
user=> (clojure.test/is (thrown? java.lang.ArithmeticException (/ 1 0)))
#error {
 :cause "Divide by zero"
 :via
 [{:type java.lang.ArithmeticException
   :message "Divide by zero"
   :at [clojure.lang.Numbers divide "Numbers.java" 158]}]
 :trace
 [[clojure.lang.Numbers divide "Numbers.java" 158]
  [clojure.lang.Numbers divide "Numbers.java" 3808]
  [user$eval7323 invokeStatic nil 1]
  [user$eval7323 invoke nil 1]
  [clojure.lang.Compiler eval "Compiler.java" 6927]
  [clojure.lang.Compiler eval "Compiler.java" 6890]
  [clojure.core$eval invokeStatic "core.clj" 3105]
  [clojure.core$eval invoke "core.clj" 3101]
  [clojure.main$repl$read_eval_print__7408$fn__7411 invoke "main.clj" 240]
  [clojure.main$repl$read_eval_print__7408 invoke "main.clj" 240]
  [clojure.main$repl$fn__7417 invoke "main.clj" 258]
  [clojure.main$repl invokeStatic "main.clj" 258]
  [clojure.main$repl doInvoke "main.clj" 174]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__5508 invoke "interruptible_eval.clj" 87]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invokeStatic "core.clj" 646]
  [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1881]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1881]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 85]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 55]
  [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__5553$fn__5556 invoke "interruptible_eval.clj" 224]
  [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__5548 invoke "interruptible_eval.clj" 192]
  [clojure.lang.AFn run "AFn.java" 22]
  [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1142]
  [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 617]
  [java.lang.Thread run "Thread.java" 745]]}

gonewest81805:01:17

but this works:

user=> (clojure.test/deftest foo (clojure.test/is (thrown? java.lang.ArithmeticException (/ 1 0))))
user=> (clojure.test/run-tests)

Testing user

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
{:test 1, :pass 1, :fail 0, :error 0, :type :summary}

gonewest81805:01:35

… which is all new to me. I’ve never tried to evaluate is outside a test definition.

qqq05:01:47

@gonewest818: TIL I have been using ct/is wrong this whole time

qqq05:01:15

putting it in a deftest makes it all work; thanks!

cmal07:01:05

Hi, how to elegantly remove leading elements that not satisfies some condition from a sorted vector in Clojure?

cmal07:01:44

Currently I use for to do this, but this will run the judging function for every leading elements that does not satisfies this condition in the vector. I think that must be some O(logN) method, like dichotomy.

Alex Miller (Clojure team)07:01:55

(drop-while #(not (satisfied? %)) sorted-vector)

cmal07:01:56

Thanks a lot! Are there a Bisection method to do this?

cmal07:01:36

The vector is very long and the function is not cheap.

Alex Miller (Clojure team)07:01:46

although that actually runs two passes, one with drop-while and one with take-while

cmal07:01:54

Thanks. Does split-with use bisection method?

Alex Miller (Clojure team)07:01:38

no, nothing does bisection in core

Alex Miller (Clojure team)07:01:26

but it’s probably just a few lines of code to write it yourself

cmal07:01:37

Thanks! 😄

cmal07:01:49

I will try to do this!

Alex Miller (Clojure team)08:01:28

something along these lines is pretty close

(defn bisect
  [v pred]
  (loop [low 0, high(count v)]
    (if (< low high)
      (let [mid (quot (+ low high) 2)]
        (if (pred (nth v mid))
          (recur low mid)
          (recur (inc mid) high)))
      (split-at low v))))

Alex Miller (Clojure team)08:01:50

depending on the sense of your predicate you may need to not the pred or flip the inner recurs

cmal02:01:26

Thank you very much!

ido07:01:59

what is the standard way/work-around in clojure to propagate exception via a promise? assuming I do not want to use a sentinel in the returned value nor a future for that?

Alex Miller (Clojure team)08:01:07

I think you’ve successfully ruled out all the options :)

ido08:01:43

@alexmiller what was the reason for not implementing this in promise ?

Alex Miller (Clojure team)08:01:07

promise conveys a value - how do you convey an exception?

Alex Miller (Clojure team)08:01:09

Clojure promises are pretty old and simple and pre-date a lot of what has happened in js and other places

Alex Miller (Clojure team)08:01:23

some people use http://funcool.github.io/promesa/latest/ - maybe that would have more stuff to your liking

schmee08:01:47

another option to take a look at is https://github.com/ztellman/manifold

Alex Miller (Clojure team)08:01:39

I looked at git blame and Clojure promise code hasn’t been touched since ’09 :)

Alex Miller (Clojure team)08:01:07

actually, that’s not true, was first implemented in ’09 but was updated as recently as ’11

ido08:01:22

java.util.concurrent.Future supports this so I was surprised that clojure did not have something alike in core.

crankyadmin13:01:39

Hi, whats the clojure equivalent of LongWritable.class?

bronsa14:01:52

LongWritable

pfeodrippe16:01:56

For those which work with Kafka or would like to, would you use avro or spec + nippy (https://github.com/ptaoussanis/nippy)?

mpenet16:01:09

Depends, avro has good cross language support, nippy is purely clj and not really specified in any way so it can be tricky if you need to later use another lang with your data. Transit could be a contender but I never used it myself.

danm16:01:59

@pfeodrippe We have used nippy

danm16:01:23

But we have specifically only done it on those topics were we need high speed, and where the data has a very short lifetime

danm16:01:55

So if we ever wanted to change language we could rebuild the existing data in some other format realtively quickly

danm16:01:02

Most of the time we just write and read as JSON

octahedrion16:01:47

can you delete data permanently in Datomic (for legal reasons) ?

octahedrion16:01:17

...i.e. European privacy law

pfeodrippe16:01:34

Going with Avro because our data is more long-term and it has better Kafka support

josh_tackett16:01:20

I am getting the following response from my frontend server:

:status 0, :success false, :body "", :headers {}, :trace-redirects ["" ""], :error-code :http-error, :error-text " [0]"}
but I see my backend server processing and returning the correct response. I am using composure and [cljs-http.client :as http] What am I doing wrong?

pyr17:01:40

@pfeodrippe I also recommend looking into CBOR

pyr17:01:09

As far as schema-less serializers go, it's very fast and very well supported across a variety of languages

pyr17:01:43

It also supports tagged deserializing a-la EDN

pyr17:01:04

We interact between a couple of languages which took nippy and fressian out of the picture

noisesmith17:01:47

@cmal if the offending items are guaranteed to all be at the front of a sorted-set, this sounds like a perfect case for subseq which takes a condition and returns the items on the right side of the coll

noisesmith17:01:19

and if you literally mean “sorted vector” consider using sorted-set which uses a tree (which is what makes that subseq function efficient)

markbastian18:01:23

hey folks, what's the lein equivalent of mvn clean install -DskipTests? Mostly jsut the skipTests part.

andy.fingerhut18:01:44

I thought that 'lein clean install' without mentioning the word 'test' anywhere should do that.

markbastian18:01:12

You're right. That was easy. Thanks!

andy.fingerhut18:01:02

Almost... 'lein clean' followed by 'lein install' does it, but I've forgotten the syntax for combining multiple lein tasks in a single command.

frenata18:01:38

lein do clean, install

pfeodrippe18:01:51

@pyr Gonna take a look, thanks!!

tjtolton18:01:17

I want to ask a question. Now, be ready. this is a really stupid question.

tjtolton19:01:14

Where can I go to look at the implementation of structural sharing in clojure? I want to play around with implementing it in rust 😂

noisesmith19:01:40

there’s no single implementation, each collection type has it’s own version of the cons method

noisesmith19:01:58

the key is that it can’t work unless you know the collection is immutable

noisesmith19:01:57

@tjtolton the simplest version is the linked list - it shares structurally if you cons a new item on the front, because it reuses the entirety of the existing list as the tail

noisesmith19:01:14

this is so trivial in rust it likely exists already 😄

tjtolton19:01:19

Right, right, because its an abstraction, not a type

frenata19:01:40

Deals with how to structurally optimize immutable data structures.

tjtolton19:01:50

ahh, beautiful

noisesmith19:01:55

yes, that is THE book on the topic, and Rich used it as a reference

frenata19:01:44

Lots of examples and exercises using ML, but you could adapt the examples to Rust and then do the exercises.

noisesmith19:01:51

@tjtolton another good intro is the series of blog posts starting here http://hypirion.com/musings/understanding-persistent-vector-pt-1

sundarj19:01:14

i thought Okasaki's ones weren't efficient enough, which is where Bagwell comes in

tjtolton19:01:18

oh thats perfect. the persistent vector is actually specifically the one I was thinking of when I asked the question

sundarj19:01:09

@tjtolton i think this is the paper rich based his implementation on: https://infoscience.epfl.ch/record/64398/files/idealhashtrees.pdf

frenata19:01:24

I don't think Okasaki claims to be as optimized as possible, but it's a great read for how to think about this stuff.

noisesmith19:01:30

@sundarj yes, but I think it’s useful to start with the clear theoretical premise, then move to the efficient optimization

noisesmith19:01:42

the hypirion link I posted above references the Bagwell paper

tjtolton19:01:51

this is beautiful, thanks, guys!

tjtolton19:01:02

I can't wait to waste my time on this 😂

davidrupp19:01:48

Per https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/EffectivePrograms.md, Bagwell invented the data structure, Rich made it “persistent”, aka “functional” in the Okasaki sense.

davidrupp19:01:26

+1 for the Okasaki book, btw.

andy.fingerhut20:01:39

It has been a while since I read the Okasaki book, or parts of it. It seems to restrict itself to implementations that can be done in a purely functional language, including the implementation of the data structures.

andy.fingerhut20:01:17

The Clojure implementations add something that I haven't seen anywhere else (but could be for lack of looking) - transients. The idea being - it is ok for an implementation of an immutable data structure to use mutation, which can make more efficient implementations possible, and/or easier to write, and you can choose to hide that from the interface/API level, so that above that you only see immutable.

andy.fingerhut20:01:38

Actually that last message of mine is perhaps conflating two things that can be separated. (1) you can take advantage of mutability in implementation of immutable data structures. That is likely from Bagwell's work. (2) transients are something I haven't seen elsewhere yet, and allow mutability-for-the-sake-of-efficiency to peek its head above the Clojure API/interface level, so programs written purely in Clojure can take advantage of the efficiency in some special cases.

micahasmith20:01:21

anyone know of any distributed task submission/retry/reporting frameworks that're fun in clojure

scriptor20:01:38

yeah, you can still use transients and maintain the referential transparency of the api function, as long as the transient stays in the function's scope

scriptor20:01:36

I don't think I've seen any cases yet where transients needed to be directly used in production code though, mostly just indirect usage through into or similar

fantomofdoom21:01:25

Sombody who use yesql, can explain how build project without connection into db?

tanzoniteblack21:01:57

@fantomofdoom if you're creating a new project (or don't have a ton of yesql anyways), you might consider using https://www.hugsql.org/ which is actively maintained (unlike yesql) and by default requires the connection passed in at runtime to the generated functions

itaied21:01:15

Is there any integration of spec with web API? I mean, if we spec the args of a function (or route), we could expose that spec as an endpoint, something like graphql.

mtkp21:01:40

@itaied perhaps some of the (in development) v2 stuff in https://github.com/metosin/compojure-api ?