Fork me on GitHub
#clojure
<
2016-12-21
>
noisesmith00:12:20

also hello I have seen you on stack overflow

richiardiandrea00:12:53

what is the best library to display a directed graph where the nodes can have little + button for expanding children?

gfredericks00:12:03

does "directed graph" mean tree? otherwise children can be shared, right?

richiardiandrea00:12:38

nodes can be shared but maybe not now 😉

noisesmith00:12:31

@gfredericks I think maybe a ring is a directed graph without shared children that is not a tree

noisesmith00:12:55

(it's cyclic though, acyclic is often also mentioned in these contexts)

noisesmith00:12:48

@richiardiandrea there's a funny little used not quite complete namespace in clojure that shows a GUI widget to examine data structures like that

noisesmith00:12:19

(I'm trying to remember the name...)

richiardiandrea00:12:04

I need to deploy it as interactive tool on a website so maybe D3, or some mind map format

noisesmith00:12:13

aha! totally different

gfredericks00:12:01

@noisesmith yeah I inferred acyclic, probably from the word "children"

noisesmith00:12:18

aha, I need to work on my inference engine

gfredericks00:12:27

Funnily the word children seems most appropriate for a tree, even though the biological analog is not

richiardiandrea00:12:29

lol you guys are funny AND clever 😄

noisesmith00:12:02

phd thesis: incest taboo and it's usefulness in clarifying data relations

hugesandwich00:12:14

Are there any libraries out there containing additional implementations of core.async channels, i.e. implementing the protocols used by ManyToManyChannel like MMC, ReadPort, WritePort? I'm looking for some implementations using alternative backing data structures and I'd rather not have to write any of these myself if possible.

hugesandwich00:12:30

Thinking about it for a second, I guess the closest I know of would be some of the things in Pulsar/Quasar

noisesmith00:12:24

I think manifold might have a few handy things too

hugesandwich00:12:15

Thanks, I'll try to dig through manifold. I already use it in a couple of projects, but as it relates to core.async, I've only seen stuff bridging between other abstractions and core.async.

noisesmith00:12:38

hmm, that might be all you find

tbaldridge02:12:44

@hugesandwich: what sort of backing?

tbaldridge02:12:42

The buffering tech has its own protocol. But be very wary of anything working agains ReadPort and WritePort the semantics are super tricky

tbaldridge02:12:22

In short don't touch those instead use channels to implement different buffering starategies

kenny02:12:02

Why does this return nil instead of "x"?

(with-redefs [get (constantly "x")]
  (get {:a "a"} "a"))
=> nil

tbaldridge02:12:34

What version of clojure are you using?

bronsa02:12:59

@kenny get has an inline version

bronsa02:12:08

that messes with with-redefs

tbaldridge02:12:32

Consider not using with-redefs there's almost always a better way

kenny02:12:18

It seems like the only way in this case. 😞 Every time an object is accessed, I need to know about it. And it has to work with the default data structures.

bronsa02:12:27

if you (alter-meta! #'get dissoc :inline :inline-arities) before that, it should work (assuming you also have direct linking turned off), but it's not something I would recommend

mingp02:12:38

Why is it a hard requirement to make it work with default data structures?

mingp02:12:07

Alternatively, why is it a hard requirement to make it work with regular out-of-the-box get?

bronsa02:12:19

well, you can access data structures through way more paths than via clojure.core/get so even with-redeffing that wouldn't work

mingp02:12:32

If you could relax one or the other of those requirements, sounds like it would lead to a cleaner solution.

kenny02:12:35

If someone wrote code like this:

(let [thingy {:a "a" :b "b"}
      a (:a "a")]
  )
I need to know that :a was access on thingy and I need to register it in my app.

mingp02:12:53

To rephrase, even if what you wanted were possible, it seems like it would be introducing some very unexpected/surprising behavior.

kenny02:12:05

This is a very experimental idea. It is also targeting cljs

kenny02:12:55

I need that info in order to update components when the global state changes

kenny02:12:17

And in order to know what component to update, I need to know what that component accessed

bronsa02:12:28

I very much doubt that with-redef is the way to go

kenny02:12:56

It might not be but it was the first thing that came to my head so I thought I'd give it a shot 🙂

tbaldridge02:12:04

So you're doing data dependency tracing.

kenny02:12:14

Trying to avoid static analysis

tbaldridge02:12:37

If you want to do that, I'd recommend a cleaner, but yet more verbose solution: Write wrappers for PersistentVector, and PersistentHashMap

bronsa02:12:56

some access patterns like (:foo the-map) don't use vars (hence there's nothing you can redef, even ignoring that it won't work when combined with inlining/direct linking)

tbaldridge02:12:57

When you do a get from one of those don't return the data, return your wrapper, and do your tracking in the wrapper.

tbaldridge02:12:06

In short, it's the decorator pattern from OOP...

bronsa02:12:35

in cljs what @tbaldridge suggests shouldn't even be too painful to write, using specify!

kenny02:12:15

What is specify!?

kenny02:12:32

Or rather, where is it? 🙂

bronsa02:12:53

it's like reify, but works on concrete instances rather than types, so you can redefine e.g. lookup for just some instances of maps rather than for all of PersistentHashMap/PersistentArrayMap

bronsa02:12:26

or having to write a wrapper type that implements all the protocols and delegates to the wrapped object

kenny02:12:43

Sounds perfect! I actually asked that question in #clojurescript but no one has replied yet 😛

bronsa02:12:12

it's specify, not specify! tho, sorry apparently specify! is the mutable version, while specify clones the object

kenny02:12:40

@bronsa Any idea if this was what was actually implemented? http://dev.clojure.org/display/design/specify+i.e.+reify+for+instances I'm looking for example usages 🙂

bronsa02:12:32

I think the syntax is the same as reify except it takes the instance rather than the type as first argument, but I've never actually used it

kenny02:12:05

Any idea how to call the original method impl?

kenny02:12:14

(let [x {:a "a"}
      _ (specify! x
          ILookup
          (-lookup 
            ([o k] "x")
            ([o k not-found] "y")))]
  (:a x "a"))
=> "y"
but this
(let [x {:a "a"}
      _ (specify! x
          ILookup
          (-lookup 
            ([o k] (-lookup o k))
            ([o k not-found] (-lookup o k not-found))))]
  (:a x "a"))
throws a maximum call stack size exceeded.

kenny02:12:04

Just trying to not duplicate code 🙂

bronsa02:12:32

yeah I would expect that. I think you need to grab the original impl via e.g. (.-lookup x) or something, but not 100% sure you can do that or what the best way would be. You'll probably need to ask somebody in #clojurescript for this

kenny02:12:56

(.-lookup {})
=> nil

bronsa02:12:06

I can imagine the munging cljs does when compiling method names could actually make this not trivial

kenny02:12:02

I think it would just work as long as I used non-string method names

kenny02:12:14

e.g. This probably won't work

(aget {} "-lookup")
=> nil

kenny02:12:46

Of course that output isn't what I want anyway 🙂

bronsa02:12:48

@kenny I think if you use specify rather than specify! you could then do something like

(let [x {:a "a"}
      x (specify x
          ILookup
          (-lookup 
            ([o k] (-lookup x k))
            ([o k not-found] (-lookup x k not-found))))]
  (:a x "a"))

bronsa02:12:59

I don't have a cljs repl at hand tho so I can't try

kenny02:12:09

Same maximum call stack

bronsa02:12:21

try again, I slightly edited my example

bronsa02:12:03

note the -lookup impl is invoking -lookup on x rather than o (so not on this, breaking the cycle)

kenny02:12:05

That worked

bronsa02:12:26

it's a bit of a hack but it should work

kenny02:12:39

Ah you used specify instead of specify!

kenny02:12:26

Wonder what the performance implications of that will be. It may be worth code duplication if it is significant

kenny03:12:07

@bronsa @tbaldridge Thanks for your help 🙂

sound2gd06:12:16

how to get java class function's console out put when working in clojure?My java class has System.out.println but I have not seen them in clojure repl.what happened?

gdeer8106:12:36

are you calling the java methods in the repl

gdeer8106:12:14

like (.method-that-uses-println (new MyClass)) ?

sveri08:12:16

I am using the clojure.java.jdbc library to write a date into a postgresql database "date" field. It does work, basically, but, on loading the written data it creates an "inst" type which automatically applies an offset. So I use clj-time to create a date with (today), write it into the database, load the data and instead of today I get a timezone adapted date which is yesterday. This is the code with the output: http://pastebin.com/ZrezguSt Any idea what the correct way is to do what I want?

the-kenny09:12:56

@sveri: Check the timezone your JVM is using. It has to match the timezone expected by your database. My advice is to run everything in UTC. :jvm-opts ["-Duser.timezone=UTC"] is likely what you want.

sveri09:12:04

@the-kenny That works, at least for the tests 🙂 I guess when running an uberjar I have to add the option to the java call

sveri09:12:21

like so: java -Duser.timezone=UTC ...foo.jar

the-kenny09:12:03

I'm quite sure jvm-opts is added to the uberjar's manifest

the-kenny09:12:35

You can also set it at runtime via System/setProperty but that's quite ugly

sveri09:12:18

@the-kenny I have not found it in the generated uberjars Manifest

the-kenny09:12:58

@sveri hm you're right

thheller11:12:06

has anyone written a "pretty" human-readable printer for clojure.spec explain yet?

vandr0iy11:12:38

I've got a question for whomever is using timbre for logging: how in the world do I configure my logging levels per namespace? can I even do that? The README.md on github tells me that I can configure the log level and the namespace filter white/blacklist in 3 different ways; But with logback I could do this:

<logger name "my.awesome.namespace" level="TRACE" />
<root level="ERROR">
  <appender-ref="FILE" />
  ...
</root>
which would mean that I can actually log up to the TRACE level from my.awesome.namespace, and up to ERROR from other places. How do I do this in timbre?

Alex Miller (Clojure team)13:12:03

@thheller: I have a few pending tickets that should make this a little easier. And I've been tinkering with some things.

dominicm13:12:49

I know there was some talk about the ::blah/foo syntax, google isn't turning it up though. Did it go anywhere in the end?

Alex Miller (Clojure team)13:12:33

That's been part of Clojure since the beginning

Alex Miller (Clojure team)13:12:56

They are autoresolved keywords if that helps searching

dominicm13:12:48

@alexmiller java.lang.RuntimeException: Invalid token: ::db/uri I think the part that doesn't work is the blah/ prefix

Alex Miller (Clojure team)13:12:51

The namespace has to be a valid alias in your current namespace

Alex Miller (Clojure team)13:12:54

That's what the "resolve" part refers to

Alex Miller (Clojure team)13:12:26

If you literally want db, just use :db/uri

dominicm13:12:01

Oh, I've misunderstood the purpose of the auto-resolved keywords, I thought they expanded to :my.ns.blah/foo

thheller13:12:34

@dominicm that would be ::foo without alias 😉

dominicm13:12:02

@thheller But I'm in my.ns, not my.ns.blah

thheller13:12:09

yeah that would need the :require alias

dominicm13:12:11

my.ns.blah doesn't exist. I'm just trying to pseudo-scope within my config map.

thheller13:12:12

@alexmiller is there an official way to determine if something is a spec thingy? other than (or (s/spec? x) (qualified-keyword? x) (regex? x))

thheller13:12:14

@dominicm either you can create an empty namespace and just require it

dominicm13:12:32

Maybe I'm moving into the territory of asking about spec best practices now really

thheller13:12:35

FWIW I went with the empty namespaces and they tend to get not-empty over time

lvh13:12:50

Is there something like clojure.core.walk that has a context? e..g I want to walk down a tree and replace values (I’m redacting a deeply-nested data structure), but there is some state I need to keep track of as I walk down the tree (e.g. a key gets redacted, but it’s important that repeat keys point to the same redacted value, so I need to keep track of previously-redacted keys)

gfredericks13:12:34

if you aren't aiming for purity then a memoized function might be easy

gfredericks13:12:59

I expect the algorithm you're describing exists somewhere but I don't know where

dpsutton13:12:35

@lvh i know tellman has a walk in ridley (i think) that maintains state so you can use gensyms across different scopes

dpsutton13:12:38

no, i was thinking of unify-gensyms in potemkin

gfredericks13:12:26

@lvh the redacted value needs to be nondeterministic?

lvh14:12:34

@gfredericks I guess it can be deterministic; not sure where you’re going with that

lvh14:12:38

like, PRF?

lvh14:12:39

It’d work

dpsutton14:12:40

i don't think its directly applicable but its an example of walking and keeping state

dpsutton14:12:50

so it unifies all gensyms to be the same gensym

gfredericks14:12:05

@lvh e.g., just based on what you said it's not obvious why putting "*" everywhere doesn't suffice

lvh14:12:08

memoized fn or keep some explicit state per walk (as in an atom) is what I came up with

lvh14:12:32

gfredericks: “secret-1” and “secret-2” both need to be redacted but they need to be reacted to consistent values

lvh14:12:36

also, distinct values

gfredericks14:12:44

okay so hash it with a big salt

lvh14:12:00

low input entropy

lvh14:12:04

enumeration’s easy

lvh14:12:15

PRF with a secret key would work though

gfredericks14:12:31

I assumed the salt wouldn't be exposed; maybe salt is the wrong word for that

lvh14:12:15

yeah; salts are not generally considered secret, and plenty of algorithms explicity expose it or an equivalent

lvh14:12:04

(”key” does the right thing though; and most keyed hashes are PRFs or MACs — the problem is that people think “prefix-SHA-256” counts, and it is not a MAC and certainly not a PRF)

lvh14:12:14

Sorry; I don’t mean to be pedantic — that’s just my hobby horse, as you know 😄

lvh14:12:14

@gfredericks So now I need all sorts of objects (e.g. dates), generated from a deterministic random seed… Sound familiar? Is there a way to tell test.check to generate 1 from a particular seed? (I’m sure there is, because otherwise shrinking could never work, but it doesn’t seem very exposed.)

gfredericks14:12:42

No it's not very exposed, because doing it by hand circumvents the normal system

gfredericks14:12:03

But if you're not running tests, just generating, then:

gfredericks14:12:48

(rose/root (gen/call-gen g (random/make-random seed) size))

lvh14:12:15

thanks! awesome 🙂

lvh14:12:59

golden-gamma

lvh14:12:04

I am having a good time reading that ns

gfredericks14:12:31

I had a good time writing it

lvh14:12:56

seed is a uniform random long, right?

lvh14:12:00

or can it be whatever

gfredericks14:12:05

Maybe there are uniform random requirements, you can check the SplittableRandom docs

gfredericks14:12:00

test.check uses current-time-millis, so let me know if uniformity is important

deactivateduser15:12:11

@rickmoynihan yes I have, and I ❤️ it!

rickmoynihan15:12:25

pmonks: do you use it with leiningen?

rickmoynihan15:12:26

pmonks: and does it run tests before deploying the build? Or does it skip tests? Just wondering if we adopted it what it would mean for our CI processes?

deactivateduser15:12:01

Not sure if it runs tests, sorry.

rickmoynihan15:12:55

I’m assuming it doesn't

rickmoynihan15:12:14

how long do you typically need to wait for the builds to be deployed? It says upto 15 minutes - and 15 minutes seems like quite a long time

deactivateduser15:12:17

Yeah first time it takes a few minutes (and the local build fails in the meantime with a timeout).

deactivateduser15:12:45

But after that the built artifact is cached by jitpack, and so nice & fast.

rickmoynihan15:12:38

sure - but what about changes… i.e. if I push a commit to fix an issue a colleague has - will she have to wait upto 15 minutes to get the update on jitpack?

deactivateduser15:12:48

Yep - that would be a new version (jitpack versions are commit ids)

deactivateduser15:12:34

But once built, anyone else who's also using that version will get the cached one, quickly.

deactivateduser15:12:42

To be clear, I haven't used it in a team setting - I've mostly used it for other people's libraries that haven't deployed anything to Maven central / Clojars. And in that case the versions typically don't change very fast.

rickmoynihan15:12:52

ok - yes I understand the version/commit thing… I was referring more to the branch-SNAPSHOT style

deactivateduser15:12:13

Ah I hadn't seen that before - it might be new.

rickmoynihan15:12:22

will need to think about the workflow a little - as I expect it’ll have to skip tests (it’s not a CI server after all) - and in complex builds where you have dependent builds in a chain waiting potentially 15 minutes for each change to propagate will be a problem

rickmoynihan15:12:01

also it being async to the deploy step will probably lead to co-ordination/build failures

rickmoynihan15:12:00

still - I really like the idea

mf17:12:15

Hi, hoping someone can help me out. I'm using the defun macro to define a function with pattern matching. As you can see the function accepts an options map:

(defun foo
  ([{:a a :b b}]
   (str a b))

  ([{:a a}]
   a))


(foo {:a "foo" :b "bar"}) ;; => "foobar"
Is it possible to use destructuring to bind the whole options map to some-symbol within the parameters definition?

abarylko17:12:03

you mean {a :a b :b :as some-symbol} ?

mf17:12:14

@abarylko yes that's what I'm trying to do

mf17:12:39

Don't think you can use :as with map pattern matching

mf17:12:24

@djjolicoeur let me try again 🙂

djjolicoeur17:12:01

may have jumped the gun, you can when destructing args or in a let and what not

noisesmith17:12:27

a pedantic point - destructuring is not pattern matching and your multiple arities can only dispatch by argument count, not by destructured contents

noisesmith17:12:13

@mf so your example is flawed because two "arities" are really the same arity with different contents - you need actual pattern matching with that, and defn doesn't offer that

mf17:12:36

@noisesmith I'm using defun

noisesmith17:12:48

where is defun defined?

noisesmith17:12:55

I misread, sorry

mf17:12:18

I'm not including the require in my snippet

mf17:12:41

@djjolicoeur :as doesn't seem to work

noisesmith17:12:03

@mf what library defines defun?

mf17:12:46

[defun "0.3.0-RC1"]

mf17:12:27

(:require
   [defun.core :refer-macros [defun]])

noisesmith17:12:31

OK - so those binding vectors are not clojure destructures, they are whatever it is defun defines

mf17:12:16

defun is built on top of core.match

noisesmith17:12:04

for what it is worth, this is what core.match has to say about :as https://github.com/clojure/core.match/wiki/Overview#as-patterns

noisesmith17:12:26

I guess it uses () for that? weird

mf17:12:21

@noisesmith yup using the parentheses worked:

mf17:12:34

(defun foo
  ([({:a _ :b _} :as options)]
   "foobar")

  ([({:a _} :as options)]
   "foo"))


(foo {:a "foo"}) ;;=> "foo"
(foo {:a "foo" :b "bar"}) ;;=> "foobar"  

mf17:12:57

@noisesmith thanks for your help

mf17:12:06

^ needless to say options is bound as you would expect (although my contrived example not accessing options)

noisesmith17:12:11

very cool, glad it worked

josh.freckleton18:12:29

---------------- my workflow in clojure is, I think, needlessly complex, but I can't think of how I can stop duplicating work: not necessarily in order: * create a schema in Postgres * write SQL bindings my backend can call (using YeSQL). Every subset of data I want requires it's own SQL. * tie those YeSQL functions to a service (protocol + extension) to be used by Component * tie those services to endpoints in Compojure * on the frontend, write glue to the api endpoints. Make sure you did auth right! * and massage the incoming/outgoing data for how the frontend/backend expects it * finally, shove the massaged data into a re-frame/db * UI components need to understand how to interpret data from the re-frame/db, and how to dispatch according to the appropriate data shape as well * oh, I need to change something? make sure you don't over look one of those steps! * oh, I need to add something? spend a bunch of time on all those steps! The Ideal Situation, or so I think, looks something like this: * data is data, so define the shape of it once. Or never (IE dynamic, like datomic/datascript's EAVT model?) * and use it as data from wherever I am - backend, endpoints, frontend, db, etc. (instead of a treating data like some set of specific cases whose implementation details "should" be the same, but end up varying, and becoming brittle) * everything is sensibly, i dunno, generated?, such as an API that makes sense as far as GETing, and POSTing, and paths are nouns, etc., with sensible, albeit customizable, auth stuff built in It seems unecessary that a human should need to do this book keeping by hand, ... Is there a better workflow, or tool, or philosophy, or something to return my sanity?

sveri18:12:30

@josh.freckleton I started working and using for some time: https://github.com/sveri/closp (still using that) and https://github.com/sveri/closp-crud (not using currently). Both tackle most of the problems. Closp is a web framework providing everything I need out of the box (component, auth, some standard web ui, ...) similar to luminus and Closp-crud is a crud generator for korma, selmer, routes and the create sql scripts I need. I might rewrite it in some time to use clojure.java.jdbc instead, but I liked the workflow. One might extend that to use re-frame UIs instead of selmer. It served me pretty well, especially closp, as I try a lot of different stuff and helps not having to redo all the basic stuff again and again.

xsyn18:12:37

Can I ask a stupid n00b question? I have a vector of vectors, and I want to run a transform fn on certain indexes of the vectors. So that 1 -> “Yes”, 2 -> No. Can I map an fn onto only certain indeces?

noisesmith18:12:53

xsyn (mapv (fn [transform item] (if transform (f item) item)) (cycle [true false]) coll) is one approach to that

noisesmith18:12:49

xsyn since vectors are immutable, you need to generate a new vector, so the questions becomes how to best generate the new vector

jr18:12:12

(mapv #(update 0 transform-fn) vectors)

noisesmith18:12:32

oh, I think I misread the question

xsyn18:12:32

@jr so if I wanted to do something like (mapv #(update [0 4 7] transform-fn) vectors) ?

xsyn18:12:56

I know that reads poorly, I get what you’re saying. I’m just trying to get it on multiple keys

josh.freckleton18:12:59

@sveri I'm checking it out now, seems interesting, thanks... In the experience of clojurians, is my problem generally addressed with frameworks? Because frameworks seem in disrepute, and is the only alternative just doing it all by hand like I listed?

sveri18:12:48

@josh.freckleton I call it framework, although it is not in the classical sense. It is just a leiningen template that you can alter and adapt to your needs afterwards. There is no lockin, everything can be replaced, updated, whatsoever.

xsyn18:12:50

@noisesmith thank you anyway 🙂

sveri18:12:23

You could even adapt the template to your needs (which is what I did years ago with the luminus template)

noisesmith18:12:28

xsyn

(mapv (fn [e] (reduce (fn [v i] (update v i f)) e [0 4 7])) coll)

noisesmith18:12:54

so for each item in the vector, it updates indexes 0,4,7 with f

noisesmith18:12:33

but! there's a library for this kind of stuff, one I don't use yet but keep meaning to check out

ag18:12:58

@josh.freckleton have you evaluated om.next? maybe it could help reducing complexity?

noisesmith18:12:42

that is the one! I forgot the name and was just looking it up

noisesmith18:12:05

@ag has om.next reduced complexity for you?

xsyn18:12:15

I was struggling with the path traversal, and decided to come down a layer of abstraction

josh.freckleton18:12:40

@sveri thanks, ya it looks useful, and creating a "pseudo framework", or opinionated list of libs and best practices has kind of been my approach too, but, it seems like it should be possible to offload most of this work/bookkeeping... at least in my dreams 🙂 Like, it really seems to me like you could have an entire app complete simply fall out of, say, 100 lines of a clojure map describing the shape of some data

noisesmith18:12:27

josh.freckleton the design principle that seems to prevent that so far is that we don't go in for implicit behaviors

josh.freckleton18:12:38

@ag I evaluated om vs re-frame about 6 months ago, when I first got serious with clojure, and went the re-frame route. is om.next pretty good? My impression was that it hasn't really hit it's stride yet.

noisesmith18:12:58

convention over configuration implies (neccessitates?) methods and behaviors that are never explicit in your actual code

noisesmith18:12:16

which is something most clojurists are wary of

xsyn18:12:28

That’s magic, thank you

josh.freckleton18:12:18

@noisesmith your point sounds interesting, could you clarify?

sveri18:12:04

@noisesmith @josh.freckleton I just want to make sure that closp / closp-crud is not a convention over configuration framework, in case it sounded like this.

noisesmith18:12:25

@josh.freckleton I think it derives from simple vs. easy - convention over configuration is easy but not simple, the implications of the conventions leads to complex behaviors that are never present in the code itself

josh.freckleton18:12:52

@noisesmith I think what I mean about my search for what you call "implicit behaviors" is that once a problem is really nailed down, you want to stop needing to think about it anymore, and it becomes implicit. For ex: clojure maps, or garbage collection. I don't have to think about their implementation details at all.

josh.freckleton18:12:33

and i think my web app problem is (close to) sufficiently "nailed down"

noisesmith18:12:46

@sveri cool - I think it's possible to have a lot of good defaults without going the way of hidden complexity and spooky action at a distance, but I think people's experience with this taken too far (eg. in rails with many plugins turned on) scared them into the clojure "everything explicit" approach

noisesmith18:12:01

just speculation

ag18:12:36

@josh.freckleton we use both re-frame and om. The first project I worked on was done in re-frame. Then later we decided to try out om.next and we really liked it.

noisesmith18:12:49

@josh.freckleton yeah - if you understand the domain well enough and really have a solid abstraction that can work very well. I think where people get burned is by combining multiple such setups that have unexpected interactions, or using combinations of features that the original devs never expected, where suddenly you go from "it just works" to "it's just broken" with no solid basis to know what was going on in either case

noisesmith18:12:19

but I was more trying to provide a rationale / community worldview that leads to avoiding magic

noisesmith18:12:37

kind of say "this is where clojure is coming from, as a community"

noisesmith18:12:34

I'm all for solid, well thought out abstractions that reduce the amount of work we have to do, but getting it nailed down is often trickier than we think

josh.freckleton18:12:13

@noisesmith To me, my problem feels like this. I have a data shaped like {:user {:name ... :email ...}}, and at every single waypoint, I need to define separate getters, setters, updaters, etc. Which is crazy, if you just think about updating a map, when you have useful primitives such as assoc, and update. But those primitives don't exist at each way point, so I have to implement them each by hand, which is a brittle approach. I'm not arguing against your idea of explicit > implicit, because in general I think you're right. But I think that point runs a little orthogonally to the problem I'm trying to solve. IE there could be an explicit way of solving my problem too, I just don't know what

sveri18:12:27

Thats why I went with the "generate all the code" approach, so I am free to change everything at any time.

josh.freckleton18:12:20

@ag I'll check out om.next again, thanks for the recommendation!

josh.freckleton18:12:23

(to clarify my "primitives at the waypoints" idea, it's like I can assoc to any map, but I need to PUT to an endpoint, and SELECT from a db, and subscribe to a reagent/atom, and all of these implementation details need to exist for each plethora of use cases)

sveri18:12:25

Btw. if you use .cljc you can define the shape of your data and take it all the way through from backend to frontend. Also, thats why I switched to java.jdbc lately, because it works with the maps that I use anywhere else.

ag18:12:59

@josh.freckleton go straight for Tony Kay’s Untangled tutorials.

noisesmith18:12:17

spec and even plumatic/schema are great here too (both work in cljc)

noisesmith18:12:27

or I think spec works in cljc...

josh.freckleton18:12:16

@ag, awesome, checking em out now 🙂

jr18:12:02

@xsyn do you need to apply the transform-fn to the value or just replace it with a static value?

jr18:12:40

specter is pretty good but a bit heavy

xsyn18:12:50

@jr applying a transform-fn worked nicely, because I actually want to transform it into a dataframe (spreadsheet) and if I do a static replace, I lose my headers. So by applying a transform-fn I get to do some checking on that too

xsyn18:12:10

@noisesmith’s one-liner worked beautifully

josh.freckleton18:12:37

@sveri cljc is a good idea, is there a way of handling compojure providing endpoints, and the frontend consuming them with cljc (this is a big clumsy step in my workflow)

josh.freckleton18:12:59

I would think not really...

noisesmith18:12:59

@josh.freckleton if you use something like bidi or polaris that supports data structures defining routes, the same data structure could be used in the front end to generate requests

noisesmith18:12:13

iirc compojure doesn't make this straightforward though

noisesmith18:12:34

but it's easy to swap out the router and still use the other ring/compojure features (eg. middlewares)

noisesmith18:12:41

or you could use the kind of model om.next leads you toward (as I understand it...) where instead of hitting a bunch of endpoints for your data, you describe the graph of data you need and that gets filled in as needed in a front end cache

noisesmith18:12:20

you are violating abstraction by exposing the schema of your data directly to the frontend, but it can also simplify things quite a bit

josh.freckleton18:12:33

> describe the graph of data you need and that gets filled in as needed in a front end cache oooo, that sounds like exactly a piece of my puzzle I was looking for!

josh.freckleton18:12:53

@noisesmith so, I'll look into this further, but real quick: does this mean that you don't really build REST endpoints, but, just like one endpoint and it deals with any shape of data you ask for, and any CRUD?

noisesmith18:12:30

I'm not 100% certain - I haven't had a chance to build an app this way (currently working on one app for a long time now...) but my recollection is that you would build a query endpoint with GET to retrieve the graph of data and POST to submit alterations?

tankthinks18:12:21

those won’t solve your problem entirely, but you should be able to define your resources as data in cljc

noisesmith18:12:39

@josh.freckleton regarding the general idea / design you could look at graphql which is a mainstream js way of doing this same pattern

josh.freckleton18:12:59

@noisesmith that sounds cool. @tankthinks a while ago I looked at them, but never used em. I'll revisit em as I'm solving this!

jfntn19:12:04

I’d like to conditionally enable fixtures on a per-test basis with deftest. I looked at using metadata on a the test definition but it doesn’t look like this would work. Any way to achieve this?

josh_tackett19:12:58

what is the best way to transform a vector into arguments? I have a vector of strings that I want to use as arguments to a format function (format "%s \n %s, %s" ["a" "b" "c"]) like this but I need to remove the vector

josh_tackett19:12:11

so: (format "%s \n %s, %s" "a" "b" “c”)

noisesmith19:12:56

josh_tackett (apply format s v) where v is your vector

noisesmith20:12:31

this works for other, non-format functions as well

mikerod20:12:18

I believe at one point before I found an earlier JVM based langauge Rich Hickey worked on.

josh_tackett20:12:26

@noisesmith Yes I remember using it for this: (apply str ["a" "b" “c”])

mikerod20:12:29

It was available still on some website. am I wrong?

josh_tackett20:12:33

just didn’t think to use it here

mikerod20:12:34

or does anyone know hwo to find this

mikerod20:12:41

(I can’t seem to find it in searches)

shaken20:12:16

I recall Rich talking about his previous projects in the Clojure for Lisp Programmers talk. They sounded more like a glue between Common Lisp and Java, rather than a full-up language.

noisesmith20:12:02

it might have been something with clr?

mikerod20:12:03

@shaken it does look more like a glue

mikerod20:12:09

there are some links in there

mikerod20:12:22

@noisesmith I think the clr was involved somewhere in here

noisesmith20:12:33

well, it says .Net so yeah

mikerod20:12:38

and he used to do Clojure on both JVM and CLR earlier on (I believe, not sure how long that went on)

mikerod20:12:47

yes it does say .net 🙂

noisesmith20:12:50

clojure-clr still works!

noisesmith20:12:05

(like with new clojure releases even)

mikerod20:12:15

I guess whoever is maintaining it is keeping up then

noisesmith20:12:00

it just doesn't have a leinclr or bootclr or whatever I don't think

mikerod20:12:18

that’s interesting

noisesmith20:12:21

@mikerod - fun fact, clojure-clr is how I found out how slow nrepl and lein are - when I first tried it I was all like "wow, clojure-clr has great startup time!" until I learned that the startup time I had been experiencing all came from the tooling I was using

mikerod20:12:27

looking at that commit history

mikerod20:12:11

I’ve never used the CLR variety

johnnyillinois21:12:45

It's great to see CLR getting attention

johnnyillinois21:12:02

I would like to get a support native implementation of clojure too

johnnyillinois21:12:59

If one linked to openjdk or used JNR, you can have a java jar link to native code and a native binary link to java jars

noisesmith21:12:06

@johnnyillinois - pixie isn't a clojure but it is very much inspired by clojure and its interop is with native code https://github.com/pixie-lang/pixie

johnnyillinois21:12:35

So I should fork and just make it a clojure compatible? I like it

noisesmith21:12:10

I bet an emacs plugin could convert valid clojure into valid pixie and visa versa with 99% accuracy

johnnyillinois21:12:27

I'll to look at the licenses, it isn't eclipse or MIT

johnnyillinois21:12:48

yeah, should be good to go

johnnyillinois21:12:39

oh cool looks like tbaldridge is a maintainer

noisesmith21:12:38

he's the primary author

johnnyillinois22:12:09

There are like 4 different half finished native clojure implementation repos on github

johnnyillinois22:12:26

Not like that is bad thing

noisesmith22:12:30

haha, I would be surprised if any of them are more than 5% done

noisesmith22:12:16

the problem with native is you go from one of the best vms available (jvm) to one of the worst (the one you just started writing)

noisesmith22:12:31

pixie gets around that by using a vm generator

johnnyillinois22:12:50

I was thinking about that

johnnyillinois22:12:00

I was hoping to bootstrap it with LLVM

noisesmith22:12:24

llvm is a toolkit for making a vm though, you still need to write your vm (though llvm makes this much easier...)

tungsten23:12:16

I'm planning to write a chatroom with core.async and websockets... any recommendations for a framework/library?

shaun-mahood23:12:09

@bfast: Not sure if this helps, but might be a useful reference for some ideas - https://github.com/tonsky/datascript-chat

olslash23:12:24

sente looks really cool, starring that for later