Fork me on GitHub
#clojure
<
2017-04-07
>
didibus05:04:24

@st3fan You can also set defaults

(defn string->integer [s & {:keys [base] :or {base 10}}]
    (Integer/parseInt s base))

didibus05:04:59

I use this pattern a lot to take configuration on a function.

didibus05:04:27

Though I'd say taking a map is probably more idiomatic, as it let's you continue to use overloaded function arity.

didibus05:04:06

Like

(defn string->integer [s {:keys [base] :or {base 10}}]
    (Integer/parseInt s base))
instead. Useful if you needed arity overloading.

qqq06:04:59

What clojure library allows me to throw arbitrary clojure data as an exception ?

xiongtx06:04:35

(throw (ex-info …))?

seancorfield06:04:05

@qqq Slingshot? (but I'd suggest trying @xiongtx suggestion first -- before you stray too far off the reservation 🙂 )

qqq06:04:11

@xiongtx is correct, ex-info suffices

qqq06:04:21

totally forgot ex-info = arbitrary clojure data

qqq06:04:35

actually, what can slingshot throw taht ex-nfo can't throw?

seancorfield07:04:38

I believe Slingshot obviates exceptions altogether and lets you just "throw" arbitrary data? I'd have to go read the docs to be sure tho'...

seancorfield07:04:04

I know it's pulled in by several projects I depend on but I've never used it directly!

luxbock07:04:00

I'm really liking hara.event

gazaxian07:04:50

I have a question, I have protocol and record and can call protocol functions on that record like so

gazaxian07:04:02

(defprotocol IProtocol
    (foo [_]))

  (defrecord Record []
    IProtocol
    (foo [_]
      (println "hi from Record foo!")))

  (def record (->Record []))

  (foo record) ;; hi from record foo!

gazaxian07:04:43

What I want is a way to get a ptr to a function foo that will work with record

gazaxian07:04:45

from a keyword

gazaxian07:04:02

(defn get-fn-ptr [protocol record-type key-word-fn]
    ;; What do I put here?
    ;; I can see func
    )

  (def xxx (get-fn-ptr IProtocol Record :foo ))

  (xxx record)  ;; calls foo for record

gazaxian07:04:24

I can see the :method-builders has when I dump IProtocol

gazaxian07:04:50

but don’t really know enough about java to understand what they are

gazaxian07:04:21

And my clojure fu is poor, looking the clojure source on github isn’t elucidating me much 🙂

gazaxian07:04:34

Any help greatfully received

gazaxian07:04:51

FWIW I have a state machine and the states are keywords

gazaxian07:04:27

I want to generate state entry / exit funcs based on the methods supported by a record or reified object

gazaxian07:04:42

so state :game-start

gazaxian07:04:13

would call on-game-start and exit-game-start if the functions were found at bind time

qqq10:04:44

I need a doseq to keep some state around. Is there soething more efficient than an atom? It's thread local, so I'm willing to use weird hacks.

qqq10:04:31

thheller: is this faster than https://clojure.org/reference/vars ?

qqq10:04:41

Changes to references made volatile are always "written through" CPU caches all the way to main memory (which is somewhat expensive), this means changes are guaranteed to propagate to other threads (nescessary in stateful transducers). 
seems to suggest they are expensive

rauh10:04:58

@qqq Well there is nonvolatile versions:

gklijs10:04:50

Depending and how the state looks like, a transient also might work.

qqq10:04:10

with transients, you ahve to "pass new var back"

qqq10:04:16

we can't just 'bash in place"

gklijs10:04:08

true, but you can use a reduce on a transient for example

qqq10:04:04

but then it's no longer doseq

qqq10:04:13

if I give up doseq, both reduce + loop/recur would work

bronsa10:04:04

@thheller volatile! is the fastest reference type that clojure offers

qqq10:04:30

how does it compare with per thread binding ?

qqq10:04:44

it seems like volatile has to write out to ram, whreas per thread things don't need to do that

qqq10:04:57

in my limited understanding of computer arthiceture, it seems like bindings would be faster than volaltiles

qqq10:04:15

to me, it seems like 'volaltile` here doens't mean fast -- it means "oh shit, another thread can change this behind my back"

thheller10:04:49

@qqq (vswap! the-ref do-some-work)

thheller10:04:07

will only cause one write after everything is done

qqq10:04:22

yeah, but the right ahs to go all the way out to RAM

qqq10:04:33

so it doesn't seem like a good idea for something neste withint two do-seq's

thheller10:04:54

not sure what kind of performance you are going for here, if it matters that much use java (or just loop/recur)

qqq11:04:18

it needs to be cljs compatible

qqq11:04:24

java is out of the question

qqq11:04:38

I'm writing indexing routines for a db, something like a mini-{datomic, datascript}

bronsa11:04:11

just use a volatile! and look into performance if that becomes an issue

bronsa11:04:47

performance between cljs and clj are completely different

gazaxian11:04:28

Does volatile really have to write thru the cache?

gazaxian11:04:36

they’re not thread safe

gazaxian11:04:39

This looks like the code

gazaxian11:04:59

it just wraps java volatile which is only supposed to be used thread locally

imetallica11:04:18

Hi folks, I've posted this question on #architecture but didn't got an answer, so I'll ask here: what libraries have you been using for PubSub/Presence? Also, thoughts on Pulsar? I’ve an Erlang/Elixir background so I’m trying to find similar tools. 🙂

kurt-yagram07:04:54

I have the same issue I'm struggling with. I've been using vert.x, I've been thinking about Pulsar but never used it so far and I'm experimenting with 0MQ and RabbitMQ (written in Erlang, which is basically all about messaging). My current setup (rewriting some stuff): it depends on your level of abstraction 🙂. Between deployables, I use 0MQ or RabbitMQ, inside deployables, on the JVM, I tend to use vert.x, although just using netty may be ok as well. Inside 'components' (parts of deployables) written in clj, core.async, although I'm moving towards manifold from time to time.

kurt-yagram07:04:42

Rationale: high level abstraction: as tech independent as possible. low level abstraction: deployables and certainly components thereof have to be able to choose their internals; the lower the abstraction, the less 'generic' the lib can be. (less generic usually being faster/more performant)

gazaxian11:04:34

oh I’m wrong 😄 it means the opposite

qqq11:04:59

I already have:

(s/def ::entity (s/map-of keyword? any?))
how do I add the additinoal constraint that :db/eid must be an integer AND :db/table must be a keyword ?

mpenet11:04:06

use s/keys not s/map-of in that case

qqq11:04:05

I think it's (s/and (s/map-of ....) (s/keys ... ))

qqq11:04:16

s/keys for :db/eid and :db/table, s/map-of to assert the other fields

grav13:04:34

How do I easily get indicies with for? Best thing I have so far is

(for [[i v] (map vector (range) ['a 'b 'c])]
     ...)

grav13:04:12

But that ain’t pretty. Resorting to map-indexed is another option, but I like for 🙂

spei13:04:54

i think the canonical way to get the indicies is to use map-indexed

spei13:04:40

@grav for is really much for for list comprehension

grav13:04:38

I probably understand the difference between doing list comprehension and mapping over a list?

mpenet13:04:00

I personally only use for when I need to loop over a "deep" data structure

mpenet13:04:51

(for [xs coll
      y xs] 
...)

grav13:04:18

Yes, that’s a good case for for. I don’t know, I just think for is really easy to use in the context of Reagent

grav13:04:44

Where I need to create a vector of vectors (a component containing sub-components)

joshjones13:04:03

creating lists is exactly for's use case -- (not looping, which loop is good for)

joshjones13:04:17

so, do your thing man 😉 🙂

mpenet13:04:04

yeah looping was not the right term, it only make sense if you do something with the return value obviously

mpenet13:04:18

there are better alternative otherwise

mpenet13:04:34

doseq/run! etc

joshjones13:04:28

since for is a looping construct in most every language, people already come to clojure misusing it, not realizing it is for list comprehension, so my mission in life is to dispel the notion that for is for looping in clojure 😉 (j/k about the mission in life part)

joshjones13:04:29

@grav if you are using for to create nested structures, you can still do that, but use the appropriate map-indexed to create the indexed structure, right?

(for [[i v] (map-indexed #(vector %1 %2) '[a b c])
      sub-v '[x y z]]
  [i [v sub-v]])

noisesmith19:04:25

#(vector %1 %2) is vector

grav13:04:08

@joshjones Yes, that’s kind of what I’m doing now, though I’m doing (map vector (range) ['a 'b 'c]) instead of (map-indexed ...

grav13:04:03

In my case, I’m creating nested data structures, so no worries 😉 I really like for for this purpose, it’s very clojuresce imho. But there should be a for-indexed 🙂

nfisher15:04:29

Hi all, I noticed clj-webdriver is no longer maintained as of Dec 2016. Anyone have a suggestion to succeed it?

nwjsmith16:04:25

and it’s been great

nwjsmith16:04:00

It’s not a Selenium wrapper, so it might not be exactly what you’re looking for, but if you need to drive a browser it is nails

nfisher17:04:55

@nwjsmith thanks! Will take a look. I was using clj-webdriver, but it means I’m pinned to an old version of FF (47) and selenium(2.x). 😕

creese18:04:18

I have project with integration tests that I would like to run locally as well as in other environments. When I put them in /test (which intuitively makes sense), they aren't added to the JAR so I can't run them in other environments (UAT, staging, etc). What is the best place for these?

creese18:04:32

The project is using Leiningen.

octopuscabbage18:04:02

you could make another jar which when run runs the integration tests

octopuscabbage18:04:07

have another project essentially

creese18:04:29

Is it possible to include namespaces that are in /test in the JAR?

creese18:04:49

Would I just at this to :source-paths in the uberjar profile?

creese18:04:43

You still wouldn't be able to run them using lein test without a main

josh.freckleton18:04:22

I have (defn myfn [] (shouldnt-be-called)) and I want to stub it out with with-redefs, like this:

(with-redefs [myfn (constantly nil)] ...)
but when myfn is called, it doesn't return nil but instead tries to call the original shoudnt-be-called am I doing something wrong?

josh.freckleton18:04:32

I've found I can successfully stub out shouldnt-be-called, but I don't think I should need to stub things down stream from myfn

ghadi18:04:38

where is your usage of myfn?

ghadi18:04:58

you may be accidentally capturing the value of myfn pre-redefs

josh.freckleton18:04:19

somethings do cross namespaces, is that what you mean?

josh.freckleton18:04:36

and shouldnt-be-called comes from a defd var

ghadi18:04:29

if you do a lazy sequence with (map myfn ....), and then redef myfn, the lazy sequence will use the old definition

ghadi18:04:21

(lots of gotcha with with-redefs -- it's not a recommended function, but an occassionally necessary evil -- lots of previous discussion on this)

josh.freckleton18:04:45

hrm... thanks for helping me get out of this earlier!

josh.freckleton18:04:50

i thought i was going crazy!

ghadi18:04:56

we'd need to see some context around where you are using myfn

josh.freckleton18:04:06

i just need it for testing, but, perhaps i need to find another way

ghadi18:04:21

it's occasionally useful in testing

josh.freckleton18:04:32

myfn lives in (def thing {:myfn myfn}) in another ns than the one getting tested...

ghadi18:04:39

yeah there's your problem

ghadi18:04:57

Just like in the map example, you're using myfn as a value.

ghadi18:04:12

Clojure will dereference the myfn value when that def happens

josh.freckleton18:04:43

oh, that totally makes sense I think. not obviuos, but makes sense now 🙂

piotr.owsiak18:04:10

hi guys, quick question: why (= 1024 1024.0) returns false and (== 1024 1024.0) returns true, I thought that = compares values

firstlast18:04:24

I’m new to clojure but if it work like it does in JS then the == compares types too

piotr.owsiak18:04:29

it does not, those are two different types (Long vs Double)

piotr.owsiak18:04:53

so it's kinda the opposite of JS 🙂

nrussell18:04:08

interestingly, the docs both say each are type-independent, but the example for = shows (= 1 1.0) => false https://clojuredocs.org/clojure.core/= https://clojuredocs.org/clojure.core/==

nrussell18:04:18

so … good question 🙂

piotr.owsiak18:04:01

and both functions were added to Clojure 1.0 so it's not like they introduced == later and the docs are out of date

firstlast18:04:45

There is a difference between "=" and "==". For primitives you definitely want to use "==" as "=" will result in a cast to the wrapped types for it's arguments. This may not be the case come Clojure 1.3 (see [1]) [1] http://github.com/clojure/clojure/commit/df8c65a286e90e93972bb69392bc106128427dde

firstlast18:04:08

'== is defined only for numbers, where '= is general equality. The example showing (== :foo) as true is a bit misleading because (== :foo :foo) produces an exception. Unary == always returns true as an optimization.

piotr.owsiak18:04:27

ok, thanks guys, that gives me some clarification

piotr.owsiak18:04:46

I gotta start using http://clojuredocs.org more, the samples and notes are great source of knowledge 🙂

ghadi18:04:00

For your case @josh.freckleton , better to parameterize your side effect:

(defn myfn [impl] (... use the impl))
rather than always assuming the impl is shouldnt-be-called -- this usually requires a few refactorings in a codebase

ghadi18:04:50

Another quick hack that you can do is: (def thing {:myfn #'myfn}) but I recommend parameterizing 100 million times more

ghadi18:04:08

#' means the var itself, not the value inside the var

josh.freckleton18:04:58

thanks @ghadi , I couldn't have solve that otherwise!

josh.freckleton18:04:40

@ghadi, so #' solved it easily, why do you recommend against it?

piotr.owsiak18:04:50

am I confused about it? the docs for = state that "Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner."

ghadi18:04:50

because the reason for #' here is to make the with-redefs work - there are better ways to mock things in Clojure (like making the implementation a passed in argument)

dpsutton18:04:42

@piotr.owsiak I don't think you are confused. That's precisely what the doc says.

dpsutton18:04:24

or at least the first half. > Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison

nrussell18:04:22

= also says > Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner

ghadi18:04:44

Yeah the verbiage is a little confusing

dpsutton18:04:08

he had already quoted that so i just finished it out

nrussell18:04:58

ah, sorry 🙂

ghadi18:04:16

The type-independent part of that sentence refers to collections

piotr.owsiak18:04:12

really?! that's confusing as hell 😄

ghadi18:04:35

english needs s-expressions sometime

ghadi18:04:09

instead of : > Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner. should say: > Same as Java x.equals(y) except it also works for nil, and compares numbers and (collections in a type-independent manner).

noisesmith19:04:39

it compares numbers type-independently as long as both numbers agree on how lossy they are - so doubles/floats or bytes/ints/longs/bigints but nothing is equal to bigdecimals except other bigdecimals

piotr.owsiak22:04:08

@noisesmith thx for detailed explanation

dpsutton18:04:25

i was being snarky because he asked if he was confused and just pasted the doc string 🙂 (without stating what the potential confusion could be)

ghadi18:04:32

Not numbers and collections. It's an English ambiguity

dpsutton18:04:47

user> (= [1 2] '(1 2))
true

ghadi18:04:42

== is type-independent around numbers and only numbers

dpsutton18:04:40

and it doesn't use an epsilon factor

dpsutton18:04:51

user> (== 0.3 (+ 0.1 0.2))
false

piotr.owsiak18:04:27

ok guys, thanks for clarification

fantomofdoom19:04:32

Hello guys, can you give me some link of moder best practice in clojure/clojurescript. thanks

qqq19:04:15

Without manually doing lots of transient/persistent management away, is there an easy way to: (1) do a bunch of assoc-in update-in on transients, then make the whole thing persistent ?

not-raspberry20:04:20

qqq: check if the functions you use use transient themselfves. For example into already does it.

mbcev21:04:14

I know it's all personal preference generally speaking, but say I have a function whose purpose is to update/populate state in an atom and this function only runs once and on app startup. What would be an idiomatic return for that function? Is there a good design pattern for such a thing? Returning a reference to the atom in question? Returning true? Leaving it as a nil return?

harold21:04:53

We like to end the names of functions like that with a bang !, and have them return a keyword, e.g., :done-building-indexes. --- returning a keyword instead of, say, the contents of the entire index, tends to be friendlier on one's repl during development.

mbcev21:04:53

Agreed. Would you say that it is idiomatic for the returned keyword to be more informational like :done-building-indexes for the sake of the repl, or would you find yourself ever using that keyword for something? Again, obviously this is all relative and personal preference, I'm just trying to understand what "clean" or idiomatic Clojure would look like in the generic case.

harold21:04:08

I can't say too much for idiomatic, our team is perhaps a bit insular 😉, I can't think of a case where the actual value returned from a function like that was ever used. I guess I try to keep those keywords unique/grep'able in case they do end up in some log somewhere, but yeah, something friendly for development more than useful-as-a-value.

noisesmith21:04:10

@mbcev ideally I write functions that update an atom such that they have no atom related logic in them - I write the function to take a foo, and return a foo, and then use the function as an argument to swap! on an atom containing a foo

mbcev21:04:02

Ahh, thanks guys. I like both of those ideas.

noisesmith21:04:18

another way to say that is that I don't write functions that update atoms (ideally at least) and just write arguments to swap!

harold21:04:19

@noisesmith --- now that sounds idiomatic. ha! What does your function that calls swap! return? I think that's the question at hand...

noisesmith21:04:40

your function to swap! must return the new value to put in the atom

noisesmith21:04:48

that's the only correct result from such a function

harold21:04:08

Not the argument to swap! but the function that itself calls swap!.

noisesmith21:04:29

oh, it should return the new value

mbcev21:04:56

So in other words, it should return what swap! returns, typically

noisesmith21:04:56

the reason I called it is to swap! on something, so the reasonable return is the resulting data

harold21:04:25

I find that with realistic data I end up blowing up my repls when I do that. 😉 But, then we're back to personal preference/tools. 😄

noisesmith21:04:51

your repl won't blow up if you stop using your editor as a repl btw

noisesmith21:04:03

it might take a few moments to print, but not much

noisesmith21:04:13

sorry, that's another topic

harold21:04:32

haha, no apologies needed. There's a joke in here about "Big Data" I think. 😛

noisesmith21:04:07

"big data is when your application data is large enough to stall your debug console"

harold21:04:37

I appreciate the thought about factoring the pure functions used to swap!.

noisesmith21:04:19

I have definitely had the case where my repl went unusable a bit because I looked at the data coming from kafka, for example

noisesmith21:04:36

but I always had a usable repl again after a control-c or just waiting

mbcev21:04:22

I appreciate both of your responses and I will use your advice accordingly!

jstokes21:04:45

to avoid blowing up your repl you can always set *print-level* and *print-length* in the repl profile

harold22:04:58

That's a good idea, I had that for a while, but then I copy/pasted some edn for a colleague and data was lost. 😐

bradford22:04:33

Which #kafka clj library should I use? there appears to be a dozen

bradford22:04:30

clj-kafka or kafka-clj. hrmmmmmmmmm 😉

noisesmith23:04:03

clj-kafka has worked OK for me, haven't tried kafka-clj

noisesmith23:04:20

a lot of my code is using direct interop with kafka itself though