Fork me on GitHub
#clojure
<
2018-04-27
>
danielcompton01:04:20

Is there a common pattern for composing transducers at runtime, where some may not be needed?

danielcompton01:04:35

I'd like to filter on several different things, but some of the filters may not be active

danielcompton01:04:02

I could put them all in a sequence, remove the nils, and apply to comp

danielcompton01:04:29

but wondered if there was a cleaner pattern for this

mfikes03:04:43

That seems like a reasonable approach. I wonder if this alternative reads and performs well, in the special case that the transducers are statically ordered, with some disabled at runtime:

(let [x? true
      y? false]
   (comp
    (if x? (filter pos?) identity)
    (if y? (filter neg?) identity)))
I suspect just (apply comp active-xforms) reads better and is more flexible.

qqq04:04:59

I have a WebGL / CLJS app that is very laggy. What tool is recommended for profiling CLJS code ?

rauh05:04:32

@qqq wrong channel? But to answer: There is nothing CLJS specific, all JS profiling tools apply here. I just use the Chrome dev tools

xtreak2907:04:14

Does lein test run tests in order? I see test 1 setting something and then testing it in test 2. I know I should be using fixtures but just curious

sveri07:04:07

@xtreak29 I dont know about lein exactly but tests in general should be independent of each other. In a best case they should even be able to run parallel. So you should never depend in one test on another.

xtreak2907:04:38

Yes, I just ran with some print statements and you are correct. I need to refactor to use fixtures.

xtreak2907:04:46

I was testing setting 'foo' to 1 and then doing listing the values in the other test and they seem to run out of order causing failure. Thanks

rickmoynihan11:04:18

Is there a bug with reader conditionals and namespaced keyword aliases? It looks like the aliases have to resolve at read time (and therefore can’t be required). Actually thinking about it this might not be a bug but be an implementation detail / limitation…

rickmoynihan11:04:07

e.g. #?(:cljs ::foo/bar) doesn’t work in a :clj environment… even if above it there is a (ns blah.blah #?(:cljs (:require [foo.bar :as foo]))

rickmoynihan11:04:17

I’m guessing keyword aliases have to be resolved at the time the reader conditional is read

rickmoynihan11:04:27

cool. Makes sense, just surprised me at first

rickmoynihan11:04:08

I do frequently find myself wishing for a decomplected way to alias keywords without loading a namespace… though I know this isn’t a new conversation 🙂

rickmoynihan11:04:59

(Not that that would solve the limitation above)

mfikes12:04:22

FWIW, the same is true with regex literals.

mfikes12:04:02

If you write

#?(:clj #"some-re-1" :cljs #"some-re-2")
The :clj branch has to be a valid literal in ClojureScript (for self-hosted), and I believe the converse is true where the :cljs branch has to have a valid literal in Clojure.

bronsa12:04:08

ah yeah sure

mfikes12:04:11

We encountered this when porting test.check to self-hosted ClojureScript and solved it by not using literals in a few places: https://github.com/clojure/test.check/commit/ebcc57dd631e25ee39bc059899e3bbd9ddf24ee9#diff-8e9504630b7d3914b74409188fc969e8L78

bronsa12:04:14

if this is an issue we can work around it in t.r btw

mfikes12:04:07

I've only encountered it once (in the above). It might be nice to address from a "completeness / correctness" standpoint, if that aligns with the language semantics, etc. But, as far as I can tell, it is not a pressing issue, per se.

borkdude12:04:01

Why don’t disj and dissoc share the same name?

mfikes12:04:22

Perhaps a corollary question: Why is disj not polymorphic like conj?

borkdude12:04:49

hmyeah. btw, I met the author last weekend again, it’s a small small clojure world 😛

mfikes12:04:11

As a "meta" point sometimes I worry that our discussions in here are trapped in a world that is not as visible as something like SO.

orestis12:04:24

I’d love if more questions like this end up in Clojureverse. Esp. with timezone differences it’s hard to stay on top of slack...

👍 4
jeff.terrell13:04:29

Agreed. Also, if you find a good Q&A exchange on this Slack, you can [ask those involved for permission and] summarize the exchange on SO, like I did here: https://stackoverflow.com/q/47358416/202292 It takes some work, but SO provides good exposure for worthy topics.

Alex Miller (Clojure team)13:04:38

@borkdude @mfikes I don’t know anything special but disj == remove element, dissoc == remove association and these are the opposite of conj and assoc. conj means add element and that has natural “fast” impls for all Clojure collections. But disj does not have “fast” implementations on sequential collections like lists or vectors. It could theoretically be implemented on maps (disj {:a 1} [:a 1]) but it seems unlikely that you would ever prefer to do that over (dissoc {:a 1} :a). So it’s only on sets. Maps are the only associative collection that allows removal (vectors can’t be removed in the middle).

Alex Miller (Clojure team)13:04:19

a good place for short entries like this is https://clojure.org/guides/faq and I’m happy to consider PRs adding q’s there

Alex Miller (Clojure team)13:04:56

most of the entries on that page are questions that came up either here or on the reddit “new user” topics that I answered on the faq page and linked to

borkdude13:04:44

Well, dissoc is remove association, that’s why I expected it to work on sets since they are keyed by their elements

borkdude13:04:38

but on the other hand assoc doesn’t work on it either, just a blurb of my mind

Alex Miller (Clojure team)14:04:47

sets are not conceptually associations (even though they are implemented that way)

alexeiz17:04:45

Why is it that I can use my Java class directly i.e. (com.my.Class. params), but if I try to (require '[http://com.my]), I get "could not locate com/my__init.class"?

bfabry17:04:40

require is for clojure namespaces, use import for java classes

alexeiz17:04:38

It works. Thnks!

asolovyov18:04:00

Hey all! What would be the most efficient way to grow an ordered sequence (any - list, vector, ...) while simultaneously limiting its length? I'm okay with adding values in the front or in the back of said sequence... cons + take seems a bit wasteful for me, is there anything better I could do?

asolovyov18:04:17

okay, I seem to overestimate wastefulness 🙂 cons/take executes 1m times in 200 msec, I guess I could live with that 😄

hiredman18:04:43

the simplest way to keep a ring buffer is something like {:items [] :read -1 :write 0}

hiredman18:04:04

(using the existing persistent collections)

asolovyov18:04:13

I'm not sure how do I make this work though 🙂

hiredman18:04:17

insert is something like (fn [{:keys [items write} :as buffer} value] (assoc buffer :items (assoc items write value) :write (mod (inc write) 10)))

hiredman18:04:24

you an use assoc to change items in a vector and an assoc at the index of size+1 becomes a conj on to the end

asolovyov18:04:13

hm, cool 🙂

hiredman19:04:36

it is also pretty easy to write a custom persistent (tree and path copying) ring buffer, because you can just preallocate a full balanced binary tree and never have to worry about balancing it

tbaldridge19:04:52

if it's small enough just use an array and clone it

tbaldridge19:04:26

although I'm not sure I've ever needed a immutable ring buffer, so perhaps just mutating an array is good enough?

tbaldridge19:04:00

depends on what the use-case is here

hiredman19:04:40

like, if you were implementing a core.cache cache, which the model is the cache is a value and you wrap it in an atom, and whatever cache algorithm you were implementing was some complicated thing based on layers of ring buffers, you would want a ring buffer as a value

hiredman19:04:21

but the core.cache model is just kind of odd

☝️ 4
asolovyov19:04:15

well, I get some updates coming in once a second and I need to store them, but I want to limit them by 100 or 1000 items

asolovyov19:04:26

so really simple

asolovyov19:04:08

"ring buffer" is something I need to remember for next time though, I found some right now on github to study code 🙂

hiredman19:04:14

you may just want to use a core.async channel with a sliding or dropping buffer

asolovyov19:04:34

heh, that's an interesting way to do it, but I'm not sure I want to bring core.async into that codebase yet

asolovyov19:04:55

https://github.com/amalloy/ring-buffer - this seems like a good enough solution

eraserhd20:04:55

Hey, are we aware that hash isn't consistent for regular expressions? e.g.

dev=> (hash #"foo")
738015301
dev=> (hash #"foo")
793194086

scriptor20:04:23

probably hashing the instance of the regex object

tanzoniteblack20:04:03

@eraserhd regex's in clojure are instances of java.util.regex.Pattern, and hash just uses the java hashCode for the java instance. So yes (not= #"foo" #"foo"), and also the hashes don't match, since java regex objects don't support equality based off the values of the regex

eraserhd20:04:21

Yesyes, but we have hash specifically to make instances of Long, Integer, Short, and clojure persistent collections equal... So, do we know that regexp literals aren't equal - is that an oversight or intentional?

eraserhd20:04:11

(It came up for me today, in expecting that two code forms were equal and had the same hash code.)

scriptor21:04:35

@eraserhd looks like there was some discussion on this a few years ago https://dev.clojure.org/jira/browse/CLJ-1182

triss22:04:09

i really wish clojure had a -> that threaded to the second argument for when I chain a number of reductions together.

joelsanchez22:04:08

just made up, may have problems, still should get you what you want

triss22:04:39

lovely thankyou @joelsanchez!

joelsanchez22:04:09

(and please update the docstring.)

seancorfield22:04:24

@triss I'm curious... what sort of code needs to thread the second argument? I can imagine threading the first argument (data) or last argument (collection).

triss22:04:23

I’m building a graph with a few different types of connections.

triss22:04:54

I iterate over lists of connections and apply add them to the same graph

triss22:04:20

what I’d like to do is:

triss22:04:09

(second-> (reduce f graph coll-a)
  (reduce g graph coll-b)
  (reduce h graph coll-c)
  (reduce i graph coll-d))

triss22:04:35

well without saying graph!!!! so:

triss22:04:52

(second-> (reduce f graph coll-a)
  (reduce g  coll-b)
  (reduce h  coll-c)
  (reduce i  coll-d))

triss22:04:31

sorry for the all edits - I’m obviously a bit tired!

joelsanchez22:04:02

ah but you can do that with as->

👍 4
joelsanchez22:04:27

(as-> graph %
      (reduce f % coll-a)
      (reduce g % coll-b)
      (reduce h % coll-c)
      (reduce i % coll-d))

triss22:04:57

lovely! thanks again @joelsanchez