Fork me on GitHub
#clojure
<
2017-05-30
>
d-t-w00:05:23

Hello everyone, long time lurker first time caller.

d-t-w00:05:03

If you're interested in real world Clojure and/or HA systems this may be interesting:

d-t-w00:05:34

I'm hiring in Melbourne right now. If you want to talk please come to either the melbourne-distributed or clj-melb meetups

d-t-w00:05:52

I'm afraid I'm not considering remote this year, though almost all my clients over the last five years have been remote

d-t-w00:05:07

So with a good wind that will change. Ciao!

bherrmann02:05:02

I’m tired. What is the simple way to split a string, ignoring space, comma, or newlines?

bherrmann02:05:31

(filter #(not (empty? %)) (clojure.string/split “table \n, , , flock” #“[ ,\n]“))

bherrmann02:05:47

That works, but it seems long winded

mfikes02:05:19

@bherrmann One small bit of golf: (remove empty? ...)

dpsutton02:05:38

i believe that \s is whitespace so you could use #[,\s+]

dpsutton02:05:03

> A whitespace character: [ \t\n\x0B\f\r]

bherrmann02:05:31

Thanks @dpsutton yea, and tabs are good to pull out. @mfikes thanks, remove and empty good idea

weavejester03:05:13

@bherrmann (re-seq #"[^ ,\n]+" "table \n, , , flock")

weavejester03:05:25

Invert the regex, use re-seq.

lvh04:05:17

do people use edn as a configuration format? How’s that working out? It seems like clojure-the-language really wants me to use namespaced keywords, but that seems very verbose when using EDN since it doesn’t seem to have ns aliases.

noisesmith04:05:53

edn has the namespace aliases of the namespace reading it, I use edn for some config, without any namespaced keywords

noisesmith04:05:18

I stand corrected - namespace aliases don't actually work when using clojure.edn

noisesmith04:05:50

namespace aliases do work with regular read / read-string though

dominicm07:05:04

@noisesmith read-string will evaluate code though.

noisesmith16:05:06

dominicm: the #= reader macro does not exist on cljs

dominicm16:05:38

I mean, I wouldn't rely on that being forever right?

noisesmith16:05:00

it only remains on clj because they don’t break compatibility

noisesmith16:05:13

it’s considered a misfeature as far as I know

dominicm16:05:05

There's also the fact that it wouldn't work with other, true, edn readers.

noisesmith16:05:20

yes, that’s a good point

dominicm16:05:56

If some way to evaluate during read-string was discovered in cljs, I doubt anyone would rush to fix it. As that's not it's purpose, right?

danielcompton07:05:56

You can also use the new namespace aliased maps in EDN (at least with clojure.edn):

(edn/read-string "{:test-key #:test{:key \"a\" :foo :bar :tie/fighter :pewpew}}")
=> {:test-key {:test/key "a", :test/foo :bar, :tie/fighter :pewpew}}
thats:
{:test-key #:test{:key         "a"
                  :foo         :bar
                  :tie/fighter :pewpew}}

laujensen09:05:03

First public look at Sabres editor, 100% clojure/clojurescript-driven CMS/eCommerce platform. Feedback is welcomed: https://news.ycombinator.com/item?id=14443969

rauh09:05:07

@laujensen Just FYI: Upvoting this with the direct link will probably trigger voting ring detection and pull it real quick. Better to go to /new and upvote there.

rauh09:05:22

Better to link to new IMO.

laujensen09:05:41

rauh, thanks for the tip, I wasnt aware it wold trigger voting, I just wanted to focus the discussion to that page

burke10:05:01

Hello everyone, I have an atom which stores hash-map. Is there a way to create a reference which points at an specific key inside an atom-hash-map, that whenever I change that reference, the hash-map-atom is also changed?

not-raspberry11:05:40

@burke Something like cursor in Reagent? A) Use a function that derefs and dispatches the map. +laziness; -read-only, unless you implement another arity for swapping with update; -the API (function call) is different from atoms (deref) B) Create a watch to listen for changes in the source atom and update the destination atom with the part of the source you're interested in. +same API as atoms; -read-only, unless you implement a watch the other direction, but then you have to deal with a recursive dependency; -eager C) implement your own 'computed' data type. This is tricky, but should be doable by implementing deref in deftype. -serious business, race conditions if you're not careful I'm honestly wondering why I'm not able to find implementations of C on the internet. Someone must have wanted to something like that in the past. Maybe there are some serious issues with computed values, depending on atoms? I'd go with A.

not-raspberry11:05:24

also https://github.com/aaronc/freactive.core, this looks better. But still alpha.

burke11:05:48

@not-raspberry thanks for your answer. 👍 Luckily I have this problem while working on a reagent app, so maybe using cursor is the best way to go. I thought that something like cursor/pointer is part of clojure.

not-raspberry11:05:53

Then you're in luck. It's as easy (not really simple) as (:require [reagent.core :as r]) in ns and then e.g. (def date-to (r/cursor filtering [:date-to])) in the code.

burke11:05:36

not-raspberry: Why do I need to :refer [reaction] instead of :refer [cursor], and then use ... (cursor filtering [:date-to])?

not-raspberry12:05:07

because I copied the wrong code. And the second thing is just an example.

not-raspberry12:05:47

you only need (:require [reagent.core :as r]) 🙂

not-raspberry12:05:59

reactions are nice too, btw.

not-raspberry12:05:19

I'll fix the example in the parent message.

josh.freckleton16:05:34

I have a fn with :pre assertions, and I'm struggling to with-redefs it...

josh.freckleton16:05:20

IE (defn some-fn [input] {:pre [(valid-schema? input)]} ...) (with-redefs [valid-schema? (constantly true)] ...)

hiredman17:05:04

the most likely reason to have issues with with-redefs are not forcing lazy values inside the scope of the with-redefs, or doing with-redefs from multiple threads

hiredman17:05:49

a new reason for with-redefs to not work is the direct linking stuff, but you have to opt in to turning that on

qqq17:05:02

what is the idiomatic way to build something that: (1) is similar to atom, EXCEPT (2) (swap! atm f) <-- f can have side effects (3) instead of doing things optimistically, it's basically:: lock atom run f unlock atom Is there a primitive like this? If not, how can I build it?

jsa-aerial17:05:05

Isn't that pretty much exactly what the STM is for??

hiredman17:05:26

no the stm also will retry

hiredman17:05:04

you might look at agents, since they do not, but they are asynchronous

qqq17:05:28

alright, so maybe I have XY problem

qqq17:05:35

I'm writing a wrapper about JCuda and it has functions like: (JCuda/Pointer.) (JCuda/cudaMemalloc pointer size) (JCuda/cudaFree pointer) (JCuda/cudaMemCpy pointer host) (JCuda/cudaMemCpyToHost pointer host) ...

qqq18:05:01

and I need a nice way to wrap this "Pointer" object so that [1] I can only have access to latestcopy, and not historical values

qqq18:05:08

so I want to use an Atom, but Atoms can retry

qqq18:05:15

agents being async is also bad -- I want this to be sync

qqq18:05:06

agents sound way too slow, since they involve thread pools

noisesmith18:05:10

of the clojure mutable containers, agent is the one that will actually serialize access in a way that is safe for wrapping an immutable value, but they are a little tricky to use properly

noisesmith18:05:02

but are you sure you need a mutable container? couldn’t a deftype that has access to JCuda api also own access to the API ?

qqq18:05:47

perhaps I am overthihnking thiks and a deftype or a defrecord will do

noisesmith18:05:37

do you need to control access to the state, apart from the access control provided by the lib?

noisesmith18:05:06

or is the wrapper a question of having a nicer api to what it offers already?

qqq18:05:41

I'm not sure how to answer your question. THe line of reasoning I had ias as follows:

qqq18:05:02

As long as everything is pure, it's fine to have access to "naked/raw data"

qqq18:05:15

However, once we have side effects, and we have state variables s0 s1 s2 s3 s4 ...

qqq18:05:25

then, by the time we get to s4, I really want s0 s1 s2 s3 to be INACCESSIBLE

qqq18:05:39

so this leads to "well, suppose I have an s-atom"

qqq18:05:52

where @s-atom always shows the latest value ... then the old ones are not easy to access

noisesmith18:05:02

but atoms should never be used to wrap something stateful

noisesmith18:05:17

and the stateful thing already provides the functionality to access its latest value

qqq18:05:18

yeah becaues the functions can retry

noisesmith18:05:37

I don’t see what an atom even adds there that has value

mobileink18:05:42

these are state variables or states?

qqq18:05:58

I think I just want good-old-fashioned objects.

qqq18:05:13

@mobileink: I don't know what diff between "state variable" and "state" is.

noisesmith18:05:24

right, then use the original thing provided by JCuda, or wrap it in deftype if you need something more friendly

mobileink18:05:30

variables hold state. s0, s1, etc. are distinct variables?

qqq18:05:23

no, they're one varaible, getting different valuesover time

mobileink18:05:07

smells like deftype to me.

noisesmith18:05:55

but also consider whether deftype actually adds anything - what would deftype do that just using the object JCuda offers directly wouldn’t?

mobileink18:05:04

right. do you need syntactic simplification or abstraction? if not, stick with interop.

qqq18:05:12

deftype + ^:volatile-mutable may be what I want

noisesmith18:05:23

why do you need to mutate anything?

bfabry18:05:28

@qqq I would just define a single random object to use as your lock, and then use locking https://clojuredocs.org/clojure.core/locking

noisesmith18:05:30

the object you wrap already mutates

noisesmith18:05:39

having your own mutation on top just adds complexity

qqq18:05:05

let me rethink these

bfabry18:05:16

you could even use locking on an atom that you update inside the locking body if you want to also update some state

qqq18:05:20

these are very good questions, and the fact I can't anwer them off the top of my head means I haven't expl9ored the possible impl space

noisesmith18:05:56

@bfabry no I am sorry that is just pathological

noisesmith18:05:16

that’s not what atoms are for, and it is just asking for deadlocks or race conditions

qqq18:05:18

it is interesting that it exists though, good to know 🙂

mobileink18:05:06

how is this different than dealing with e.g. a db or other network connection?

bfabry18:05:37

I don't see how you could get a deadlock or a race condition doing that

bfabry18:05:16

unless a thread up and dies altogether, which is going to cause deadlocks in most transactional things

bfabry18:05:40

if you're in a situation where threads can get killed mid-work and the system continues then yeah you need to think harder

noisesmith18:05:45

OK, to back up a moment, we haven’t established that atoms have any feature that qqq actually needs here. He’s already interacting with a stateful object.

bfabry18:05:48

that would be odd though, and probably only occurring in a case where you're already using some higher-level thread coordination abstraction. in which case you should use that

bfabry18:05:05

ok, if he's interacting with a stateful object, call locking on that object

lxsameer18:05:41

hey guys, Is there anything like inheritance for protocols ?

qqq18:05:04

here's the real problem

qqq18:05:12

I don't understand the jcuda api well enough to formulate a question

qqq18:05:23

qed 🙂

mobileink18:05:15

@lxsameer that depends on what you mean by "like". composition is "like" inheritance, to me.

lxsameer18:05:57

hmmmm, Let's say I have three protocol with almost the same interface, how can I check whether a record satisfies one them ?

bfabry18:05:53

(some #(satisfies? % foo) [Protocol1 Protocol2 Protocol3]) 😛

ghadi18:05:22

lxsameer: why do you have three protocols with almost the same interface

mobileink18:05:40

you can extend protocols, i believe. sorta like inheritance.

noisesmith18:05:44

mobileink: you can implement a protocol, that’s as close and as far as you’ll get

noisesmith18:05:56

a protocol can’t extend another protocol

mobileink18:05:57

i stand corrected. you can compose protocol implementation using extend stuff, though, which is almost as good.

noisesmith18:05:40

right, I’m certain that the right answer is just to have separate protocols and extend each of them as apropriate (whether he’s ready to accept it or not)

mobileink18:05:35

yeah. haven't ever really thought about extending prorocols. i guess if it filled a real need RH would have thought of it. ;)

noisesmith18:05:17

if it was a feature, it would be easier to have eg. an extensible hashmap type

noisesmith18:05:31

but hey, defrecord is a nice replacement for that

mobileink18:05:18

i've crossed the tipping point, where i stop saying "they didn't think of x" and just accept that in fact RH undoubtedly did think of it, better than i did, heh.

noisesmith18:05:55

heh, that’s a good rule of thumb for sure

lxsameer18:05:02

@ghadi it's like each of them is an extension to previous one

bfabry18:05:23

you can extend an object/type with a protocol, you can't extend a protocol

bfabry18:05:52

extend-protocol sounds like it extends a protocol, but it actually extends multiple types with a single protocol

ghadi18:05:23

That's a strange use-case. Usually you see one protocol with multiple related/shared implementations, like this: https://github.com/clojure/clojure/blob/d7e92e5d71ca2cf4503165e551859207ba709ddf/src/clj/clojure/java/io.clj#L209-L224

bfabry18:05:48

actually above I said object/type should've been type/class. You can't extend objects in clojure. I was thinking of ruby

lxsameer18:05:08

@ghadi I'm aware of that

lxsameer18:05:38

the thing is I'm trying to have different components. normal components follows the Lifecycle protocol. But database components should follow DatabaseLifecycle protocol which have two more functions than Lifecycle

noisesmith18:05:54

that’s when you implement two protocols

lxsameer18:05:10

but t database components won't satisfy the Lifecycle

lxsameer18:05:34

@noisesmith so how is the right way to do it ?

noisesmith18:05:22

(defrecord Foo [] Lifecycle (start [this] …) (stop [this] …) Database (connection [this] …))

noisesmith18:05:47

where start and stop likely invoke methods from Database inside their implementation

noisesmith18:05:56

which is why we have a this arg, totally normal

lxsameer18:05:42

that is what i need

lxsameer18:05:46

thanks guys

theikkila20:05:30

I have stupid problem, I have 2 files with JSON-files and every line is a JSON-object. I’d like to automatically generate on runtime test-cases for all of the line-pairs to check if they are the same

theikkila20:05:45

I would like to use expectations-library for doing that

theikkila20:05:50

I made this kind of macro, and it works wonderfully in repl - but when running it as a tests it doesn’t work anymore because eval is not allowed inside macro

(defmacro expands [f lst-a lst-b]
  (let [ar (map (fn [[a b]]
                  `(~f ~a ~b))
                (map vector (eval lst-a) (eval lst-b)))]
    `(do ~@ar)))


(expands expect (load-list-1) (load-list-2))

noisesmith20:05:08

why does this need eval?

theikkila20:05:58

well, actually it’s wrong but otherwise load-list-1 and load-list-2 will be forms, not evaluated forms (as in lists)

theikkila20:05:11

I want to generate the test cases from the two lists

theikkila20:05:28

first macro seemed good idea but its not because the evaluation order

noisesmith20:05:28

if they are inside parens in the form you emit, they will be called

theikkila20:05:19

well the map in the second line is generating the code if load-list-x is just evaluated as lists

noisesmith20:05:00

right, but you could emit the whole let

noisesmith20:05:14

there’s no reason not to

noisesmith20:05:46

(I mean yeah it would require some refactoring, but it would get rid of a needless eval)

theikkila20:05:47

there is the reason that the expect-macro cannot be used like that

theikkila20:05:17

and I think that clojure.test/is doensn’t work either with that

noisesmith20:05:31

clojure.test/is can be used in a function

noisesmith20:05:36

it’s very flexible

juhoteperi20:05:52

@theikkila Isn't checking if all line pairs are the same, the same as checking if the lists are same (is (= (load-list-1) (load-list-2))?

theikkila20:05:18

but the lines are pretty complicated

juhoteperi20:05:24

And even if you want to check each item separately why would this need a macro? (doall (map (fn [a b] (is (= a b))) (load-list-1) (load-list-2))

juhoteperi20:05:10

Clojure.test cases don't have to be generated by macro, you can just run these in doseq or map, and I presume expectations will work similarly

theikkila20:05:10

so if one case fails I don’t want to clutter with working stuff, the printing is not very pretty with huge vectors of stuff

noisesmith20:05:20

I’d replace (doall (map …)) with (run! …) except run! only takes one collection arg, anyway dorun is a better fit

theikkila20:05:34

hmm, it looks like it works, maybe I should just use the clojure.test then

juhoteperi20:05:30

Did you try with expectations?