Fork me on GitHub
#clojure
<
2016-09-21
>
quoll00:09:37

Oh cool! I presume it’ll have a deep dive into Spec? 🙂

fasiha01:09:16

Deepest apologies, this is a dunce cap question. I have an out-of-the-way namespace, bad.core defined in src/clj/bad/core.clj, that does some exploratory stuff. This namespace isn't referenced in any other Clojure code, most of which lives in src/clj/good/, and which lein actually starts: grep -rns bad src/ yields results on in bad/core.clj, nothing outside it. However, I'm seeing that, when I launch the app via lein, at some point, bad.core is loaded and run, and I see its side-effects (files being created and deleted). Why would Clojure be loading and running a namespace that I don't reference anywhere?

bfabry01:09:40

@fasiha are you using clojure.tools.namespace or anything else that walks your source path?

fasiha01:09:45

@bfabry hmm, I'm not using clojure.tools.namespace specifically, I'm trying to think if anything could be walking the source path (which is not something I knew was a thing one could do)

fasiha01:09:59

I wonder if cljs-devtools or dirac would do that though.

bfabry01:09:12

@fasiha well, some testing libs do it, for instance midje in order to do autotesting. I don't have a big list of things that do it though. if you only want to use that namespace in development it might be simpler to just have different :source-paths in different profiles in project.clj than track it down

bfabry01:09:30

I believe a lot of cljs development involves watching the fs for changes and recompiling. that could be something. I don't do cljs myself though

lvh01:09:35

Hm, is the syntax for Annotations ^{Annotation {}} specialcased or something? It doesn’t seem to work through the metadata system although it looks like it

fasiha01:09:52

Thanks @bfabry it's most likely figwheel or possibly cljs-devtools/Dirac re-loading clj files 👿, I didn't even suspect ClojureScript-related paraphernalia because this was a Clojure-only namespace…!

lvh04:09:10

~/caesium> date; and env JVM_OPTS="-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:+TraceClassLoading -XX:+PrintAssembly -XX:PrintAssemblyOptions=intel -XX:-UseCompressedOops"  ~/.local/bin/lein with-profile +benchmarks test > hotspot-asm-output; and date

lvh04:09:31

getting that working was surprisingly painless; I was expecting way worse

lvh04:09:35

jitwatch is pretty easy to use

lvh04:09:46

(I am trying to see what my fancy crypto gets compiled down to in asm)

kurt-yagram07:09:04

design questions: I have a number of namespaces which depend on each other (I struggled a bit with cyclic dependencies, but clojure makes me think harder about this 🙂 ). However, one way to decouple them, is using channels/core.async. I did that, but than, I just wondered if it makes sense to 'decouple the channels from the namespaces'. What I mean here: does it make sense to define a namespace which has as only task 'messaging', meaning, it actually only defines channels? If so: 1. Does it make sense to implement methods to put something on a channels (and/or read from it), so that one can spec/fdef these functions, or do spec/conform inside and possibly other logic inside them (e.g. durability, if applicable)? 2. If defining only channels, should I use a var or atom/defstate (from tolitius/mount). My gut feeling tells me a var (which is globally accessible?) is enough, but I always have a bit of an strange feeling with global vars (however, global atoms might be even worse).

hiredman08:09:22

I dislike mount exactly because it is all globals

hiredman08:09:32

you should checkout component

kurt-yagram08:09:29

yeah... problem with component is: your whole system has to be build around it - makes me think too much about all kinds of bloated java frameworks, not saying that component is bloated, though. component/mount is a nice discussion - but what about separating messaging in a dedicated namespace?

kurt-yagram08:09:51

but I do feel the same about globals, really. I'm always struggling with anything that's global (and not a api-like function)

hiredman08:09:55

I would step back before messaging, it sounds like you have a code organizational issue, and are trying to solve that with messaging instead of re-organizing your code

hiredman08:09:43

component is very minimal (although it has been growing with each release, which is shame)

kurt-yagram08:09:24

yeah, I do agree component is minimal, but still, your whole 'system' has to be build around it.

hiredman08:09:46

it is not global, and it separates the runtime relationship between components and the relationships between clojure namespaces

hiredman08:09:56

that depends

oscnet08:09:29

what's wrong?

kurt-yagram08:09:31

... that depends? You mean you shouldn't build your whole system around it?

hiredman08:09:31

and it is very flexible, at my last job some people weren't a fan of protocols, so we replaced the lifecycle protocol stuff with multimethods, which we could do with component without rewritin the library

hiredman08:09:43

I mean it depends

hiredman08:09:16

at some point you will be calling clojure functions to get things done

hiredman08:09:28

you can decide where that is

kurt-yagram08:09:38

@oscnet (my.a/hello (->Prec ""))

hiredman08:09:24

I worked for about four years on a clojure system that organized runtime state very similar to what mount does (mount didn't exist at the time), and given the chance on a new project we went with component (only worked on that for about a year)

hiredman08:09:10

component is great, and simple enough that if I couldn't use the library for whatever reason I would just implement it myself

kurt-yagram08:09:37

@hiredman Going back again to my code: it has some organizational issues... I'll try to explain where I'm at... give me a sec 🙂. Anyway, just to be clear: I can use component just in a small fraction of my code, right? (I should check component again, probably)

hiredman08:09:52

a lot of code organization issues in clojure come from conflating the sort of static structure of the code (defs in namespaces) with the dynamic runtime structure of whatever you are doing

oscnet08:09:07

ok, thanks

hiredman08:09:29

you can break up the static dependencies by saying, instead of this code being hardwired to call function f over in that namespace, it will have the function it needs to call passed in

hiredman08:09:37

then you can either wire that all together yourself or use something like component to do it

kurt-yagram08:09:26

Allright, this is the use case: I have two main methods: in-message and out-message, let's call namespace mess 😉. The names are somewhat self-explanatory. If receiving a message, the message is dispatched via a dispatcher (separate namespace) to the right handler. After the message is handled, it may send a reply. Very very basic. So, the namespace mess depends on dispatch (since it just calls dispatch whenever a messages is sent to in-message). However, if there is a reply, dispatch must call out-message, which is in the mess namespace. Yeah, I could use higher order function passing, but this tends to result in a kind of pretty messy 'keep on passing a function down a few levels' and such.

kurt-yagram08:09:34

- yeah, I keep struggling with these dependencies. Will check component 😛

hiredman08:09:22

break mess in to mess-in and mess-out

hiredman08:09:59

another thing, namespaces are always too large

hiredman08:09:20

if you are luck you'll get three namespaces out of mess

hiredman08:09:02

mess-in mess-out mess-common

kurt-yagram08:09:05

yeah, breaking up mess was another thought. I probably really need to do that.

kurt-yagram08:09:57

so, now we're about: component or breaking up mess? - just to have your thought.

hiredman08:09:25

it sounded like the only reason you added messaging was to deal with dependencies

hiredman08:09:45

if that is the case, get rid of messaging and use component

kurt-yagram08:09:04

True about the messaging stuff. Will try component. Thx!

jba08:09:28

Someone has any experience with Maven and Lightable ? It seems that maven don't run the middleware.

sveri09:09:30

@hiredman @kurt-yagram I have been using component almost exclusively (trying mount when it was new several times) and I prefered it, because somehow the reloading went smoother. Also I have to disagree, I think you can perfectly use component for some components and bypass it for other stuff. Its not intended to be used like this, but totally possible.

kurt-yagram09:09:06

@sveri allright, thx. I'm trying to define a system which is only part of my application now.

dominicm09:09:11

I've also noticed that I prefer dependency-passing in the function arguments over globals anyway. I think it would be quite easy to move from component to mount when using this pattern.

sveri09:09:18

thats true, when I was trying mount I took an existing application and switched between mount and component like 3 or 4 times. All it was, was some tedious comment / uncomment

dominicm09:09:34

I overall prefer component as it more strongly encourages passing in state as an argument instead of referring to vars. Even if mount can be used in this way.

martinklepsch12:09:45

In Schema, how can I make a Schema that checks if two map values are identical, e.g. {:password s/Str :password-confirmation s/Str}

crocket12:09:16

On https://news.ycombinator.com/item?id=11233866, I read I believe that's 220ms. Which isn't too bad. But Clojure can usually match that if you AOT everything.

crocket12:09:28

I could never make a clojure program execute in 220ms.

crocket12:09:41

How could it be possible?

pawel.kapala12:09:51

As mentioned, do you AOT your clj files? Otherwise AFAIK they would be compiled by JIT which takes some time doesn’t it?

crocket12:09:16

I turned on AOT in leiningen project file.

crocket12:09:22

I created an AOT uberjar.

martinklepsch12:09:14

Is the default Clojure jar fully AOT?

martinklepsch12:09:50

@crocket run this java -cp clojure-1.8.0.jar clojure.main and make sure the jar file is fully AOT

martinklepsch12:09:20

I think as soon as you include any dependencies that time will grow even with AOT

martinklepsch12:09:46

@crocket not sure what that ^:skip-aot does exactly but you may want to try without it

pawel.kapala12:09:06

@crocket I just run a couple of tests, and if I run uberjared with or w/o aot I get the same time:

1.38s user 0.09s system 171% cpu 0.856 total
same goes with downloaded clojure-1.8.0.jar
time java -cp clojure-1.8.0.jar:. foo.core
Hello, World!
java -cp clojure-1.8.0.jar:. foo.core  1.38s user 0.09s system 173% cpu 0.849 total
all of that compiled with :aot :all

crocket12:09:38

A bit disappointed.

crocket12:09:19

AOT doesn't make much difference.

quoll12:09:33

Clojure compilation is pretty fast! It’s the JVM and Clojure runtime startups that take all the time

akiroz12:09:12

well AFAIK, most of clojure's startup time actually comes from loading all the built-in namespaces and not JIT compiling code

crocket12:09:44

Haskell also has a huge runtime, but startup time of a haskell program is usually fast.

akiroz12:09:21

because of LISP's dynamic nature, there's no way to tell what needs to be loaded so it just loads everything.

akiroz13:09:00

you can check out this clojure implementation for faster startups: http://clojure-android.info/skummet/

crocket13:09:16

How decent is clojure-android support?

crocket13:09:28

How stable and useful is skummet?

plexus13:09:50

@crocket from what I've seen it's pretty decent, you can build real world stuff with it, but it doesn't have much traction, and so lacks a lot of polish

crocket13:09:12

skummet or clojure-android?

plexus13:09:15

If you want to build mobile apps the clojurescript+react-native route is much more popular

plexus13:09:19

clojure-android

crocket13:09:03

HTML apps are taking mindshares away from native apps.

plexus13:09:45

both skummet and clojure-android seem to not have much activity anymore, although that might just be impression. you can ask in #clojure-android . I see an occasional burst of activity in there

crocket13:09:11

What options do I have if I didn't want react-native?

plexus13:09:28

react-native is not HTML, it uses native components, just orchestrated from JS

plexus13:09:47

and it provides a much more functional model for composing UIs

crocket13:09:49

There are apache cordova, ionic, and honegap, too. But, I don't know any of them.

plexus13:09:11

these are completely different animals, they are just wrappers for a web view, react-native is very much not that

crocket13:09:25

Oh, ionic is not a competitor.

crocket13:09:48

i used react, and I didn't like it much.

crocket13:09:05

I didn't dislike it, either, but I didn't like it much.

pawel.kapala13:09:03

@crocket just out of curiosity, as I’m gaining speed at project in react-native, what didn’t work for you that made you look for alternatives?

crocket13:09:48

I didn't try react-native.

crocket13:09:57

But, react is a javascript project.

crocket13:09:12

It doesn't discourage you from abusing internal mutable states.

crocket13:09:24

Oh, I am looking into functional reactive programming.

crocket13:09:22

I don't like teenage mutant ninja that is javascript.

pawel.kapala13:09:31

I see, but I’m exploring this path: http://cljsrn.org

crocket13:09:01

I don't know if react would be compatible with FRP.

val_waeselynck13:09:55

@crocket React doesn't prevent you from using mutation, but it doesn't prevent you from programming functionally either, I'd say it's too low-level for those considerations. Reagent, via reactions, provides something close to FRP atop React IMHO. While not perfect, I think that React-native is by far your best shot for mobile

crocket13:09:27

Why not cordova?

crocket13:09:36

By the way, I'm primarily working in haskell nowadays.

val_waeselynck13:09:42

@crocket Cordova, which is really the same thing as Phonegap, is way more limited as a platform (poor access to native functionality, and quite slow too).

val_waeselynck13:09:31

note that I haven't used either platforms extensively, just heard a lot of feedback 🙂

val_waeselynck13:09:50

Most people I know who tried Cordova eventually dismissed it as non viable for mobile

val_waeselynck13:09:14

for mobile, you really want native, and to get native, it's either the default SDKs with their mutation-based UI kits, or React Native

crocket13:09:36

Why do I want native?

crocket13:09:56

I think react is quite based on mutation, too.

val_waeselynck13:09:02

because mobile web works poorly 😕 really no rational argument here, just an experience report

val_waeselynck13:09:17

.. and trust me, at that point, you're not picky about what language you want, you just want a sane API

val_waeselynck13:09:43

@crocket there are plenty of React wrappers out there that prove that you can live without mutation in React

val_waeselynck13:09:21

look at quiescent in the Clojure community for example

akiroz14:09:15

Haha, this made my day. Sounds like a pretty accurate description of JS to me 😄

val_waeselynck14:09:22

@akiroz I think JavaScript has an undeserved reputation amongst Clojure programmers. Of all mainstream languages, it's the one from which the principles of Clojure are most accessible IMO (e.g immutability, data-orientation, first-class functions, polymorphism à la carte, etc.). I remember having a very bad initial reaction when I was introduced to JavaScript as a Java programmer, but then I realized that once you're past the superficial twarts it can be quite elegant and powerful.

akiroz14:09:51

It depends on which part of react you're referring to. It's core concept is pretty functional: - you have a data struct representing the DOM you want - react does a tree-diff against the existing data struct to find the minimal DOM operations needed to make it into the shape you want it and applies them the the actual DOM. The component API however is very much based on OOP and mutations but this part is completely optional if you're got a better way to manage your state.

mpenet15:09:50

maybe we're not talking about the same "component" tho, I am just realizing now (react vs clj component)

akiroz15:09:40

@val_waeselynck I don't necessarily mean it in a bad way, It's just that: teenage -> rapidly growing language (think ES6 / ES7) mutant -> strange syntax semantics (things like == vs === and the list goes on....) ninja -> does tricks, lots of features and gadgets though I personally do in fact hate JS mainly because of it's syntax.

akiroz15:09:02

@mpenet yeah, I'm referring to the react ones (which could still be functional, but their official guides teach the OO way so that's how people will use them in real life)

fellshard15:09:14

The warts are, arguably, more than superificial. Just too many strange / bad decisions continuing to be made over time.

fellshard15:09:45

Ones that tend to make programming in it directly continually hostile to the focus of the developer. Too many background concerns to watch out for.

fellshard15:09:53

Especially polyglot programmers.

eslachance15:09:02

@lukism well look who's here lol

eslachance15:09:46

I mostly hang out in #beginners though. Because, well, I'm still a clojure noob!

val_waeselynck15:09:45

@fellshard warts like == vs === are much more superficial and easy to fix to me than, say, the limitations of classes in Java

val_waeselynck15:09:52

while there are warts that are not superficial, you can actually avoid them

val_waeselynck15:09:58

although I acknowledge that they still bite you when consuming non-functional js libs

val_waeselynck15:09:18

@akiroz I don't actually think there's a point in having a debate about this, just want to encourage people to give JavaScript a second chance 🙂

fellshard15:09:19

Not talking about == vs ===. Talking more about its choices around primitives, hoisting, scope, etc. Sure, you can do some cool and funky things with them, but they'll more likely than not bite you in the tail when you're not paying close enough attention.

val_waeselynck15:09:54

yeah hoisting and coercion rules are awful, no excuse for those

akiroz15:09:31

@val_waeselynck sure, there are worse languages out there but that doesn't really make JS a good one... I currently have to write JS almost every day at work and it pains me to know that stuff I wrote could have been so much more elegant in cljs 😞

val_waeselynck15:09:15

I once did the js->cljs transition, and by far the biggest difference to me was hot-code reloading. Damn that rocks.

val_waeselynck15:09:33

But I'd much rather use React from javascript than Angular from cljs

shaun-mahood15:09:53

Just saw this in twitter, looks pretty relevant to the discussion - https://purelyfunctional.tv/infographic/functional-javascript/

shaun-mahood15:09:55

There are also hot code reloading solutions in JS (I think you can even use figwheel for it). My first experience with figwheel was so amazingly eye opening too 🙂

val_waeselynck15:09:28

@shaun-mahood yeah I think the JS ecosystem has caught up a bit since when I did that

val_waeselynck15:09:41

re: hot-code reloading I mean

shaun-mahood15:09:14

Oh yeah, JS it getting tons of good ideas from ClojureScript as far as I can see.

val_waeselynck15:09:09

I mean, for instance, when working in JS I missed multimethods, so it was pretty easy to re-implement them. Not so in most other languages I believe

val_waeselynck15:09:48

biggest challenge remains educating the developers I guess 🙂

shaun-mahood15:09:19

Yeah my view of JS is that you can do pretty much anything, good or bad.

akiroz15:09:26

JS' class / object system is still pretty much "broken" but the majority of the community are embracing OOP. anyone ever seen this? console.log.bind(console)

Jeremie Pelletier15:09:20

I still like JS’s OOP better than Java’s or C#’s, prototypes are great

val_waeselynck15:09:30

@akiroz yeah JS ecosystem moving towards classes makes me sad

Jeremie Pelletier15:09:30

even tho I use it as little as possible

val_waeselynck15:09:55

but at least the prototype system of JS can pretty much emulate all class systems

Jeremie Pelletier15:09:47

what I don’t like about JS is the bloat, its become SO easy to include 20 libraries into your project and every single minifier except google closure is really bad

val_waeselynck15:09:33

@lambdacoder yeah always funny to compare a CLJS project's project.clj to a JS project's build file

Jeremie Pelletier15:09:47

im constantly amazed at the output of cljs

Jeremie Pelletier15:09:13

its often an order of magnitude faster than the exact same code through uglify

Jeremie Pelletier15:09:22

er not faster, smaller

val_waeselynck15:09:57

@lambdacoder isn't that because you run it on CLJS -generated code ?

Jeremie Pelletier15:09:28

no I mean the libraries’ code getting stripped, regardless of the project’s language

Jeremie Pelletier15:09:49

uglify will bundle everything cause it has no static analysis of the code

akiroz15:09:54

oh yeah, google closure's advanced compilation is pretty magical IMO.

Jeremie Pelletier15:09:32

so even if I know cljs will be heavier in its raw output than the JS equivalent, once through closure whats left is much much smaller

shaun-mahood15:09:13

Probably worth moving this conversation to #clojurescript or somewhere else though - not really clojure related anymore 🙂

val_waeselynck15:09:57

What I find amazing about cljs is that's it's probably the most complete answer to the issues of front-end development, and it's not even in JavaScript

val_waeselynck15:09:25

Although ClojureScript is Clojure, don't let anyone say otherwise

Jeremie Pelletier15:09:35

for the most part

Jeremie Pelletier15:09:20

going back to clj to write macros feels different 🙂

georgek18:09:49

I’ve got a (probably simple) macro debugging question. I’ve got a simple datomic query that takes a base namespace arg to construct the query: (defmacro pull-all-items [nsname] `(let [idname# (keyword ~nsname "uuid") uuids# (d/q '[:find ?uuid# :where [_ idname# ?uuid#]] (db-conn)) ] (into [] (flatten (into [] uuids#))))) When I run it I get: java.lang.RuntimeException: Unable to resolve symbol: idname__14091__auto__ in this context macroexpand shows: (let* [idname__19476__auto__ (clojure.core/keyword "test" "uuid") uuids__19477__auto__ (datomic.api/q (quote [:find ?uuid__19478__auto__ :where [ff-server.api.datomic.util/ idname_19476__auto__ ?uuid__19478__auto__]]) (ff-server.api.datomic.core/db-conn))] (clojure.core/into [] (clojure.core/flatten (clojure.core/into [] uuids__19477__auto__)))) So 2 questions: 1. when you use ‘_’ in a macro does it need to get autogen’ed? 2. Why doesn’t this work?! (hahaha)

trptcolin18:09:04

on 2, that error is from idname# - it has meaning inside the syntax-quoted form but you're quoting it inside that datomic.api/q expression, so you pass that exact symbol into datomic. i'm guessing you really want to be passing its value at runtime instead - and since that vector is wrapped in a quote, you lose the ability to get its runtime value.

trptcolin18:09:15

you could quote the pieces of that vector instead of wrapping the quote around the whole thing in order to make sure runtime values get where they need to be

trptcolin18:09:13

and sorry about question #1 - i don't know how datomic queries work so can't answer that one, but in general it depends on your use case / what _ is getting used for.

bfabry18:09:42

@georgek curious, why is this a macro?

georgek18:09:32

@trptcolin thanks! That makes a lot of sense

georgek18:09:16

@bfabry Good question. Its being called inside this: (defmacro defqueries [nsname] `(do (require '['ff-server.api.datomic.util :refer ['pull-all-items ~'simple-query ~'simple-transact ~'simple-enum ~'add-to-list ~'rm-from-list ]]) (defn ~'pull-all [] (pull-all-items ~nsname)) : Which declares a bunch of fns in a calling namespace. When I had it as a simple fn, putting it inside the macro broke it

georgek18:09:20

So I guess in my macro-newbie-ness I thought it needed to be a macro too

bfabry18:09:01

ah. you could define it as a function that returned code and then call it like (pull-all-items nsname), or you could define it as a function that returned items and use it like (pull-all-items 'nsname)

georgek18:09:36

ok cool. That’s cleaner!

georgek18:09:39

thanks y'all

bfabry18:09:45

the second will be a lot easier to test

tbaldridge18:09:24

That's good advice for most macros, btw. Even the source of clojure.spec breaks macros up into "foo" (a macro wrapper) and "foo-impl" (the actual processing of the forms passed to the macro". Also makes it easier to debug at the repl because you can pass data into the -impl function and examine the output without messing with macroexpand.

georgek18:09:26

Yeah, that makes so much sense. I started to despair at the thought that my implementations started becoming 'macros all the way down’… 😛

idiomancy21:09:41

okay, so theres this pattern i regularly come across and I cant find the clojure function to do it.

idiomancy21:09:52

merge-with ???

idiomancy21:09:40

what i want ??? to do is take items and put them into a vector. conj doesnt work, because the first collision

bfabry21:09:41

well, that's a function in clojure.core?

idiomancy21:09:48

hahaha, no wait, there was more

bfabry21:09:52

haha sorry

idiomancy21:09:30

(merge-with ??? {:a 1 :a 2 :a 3}) --> {:a [1 2 3]}

idiomancy21:09:34

that kind of thing

bfabry21:09:48

think you mean {:a 1} {:a 2} {:a 3}?

idiomancy21:09:01

yea sorry, correct

idiomancy21:09:09

or "apply merge-with"

idiomancy21:09:43

and [[:a 1][ :a 2] [:a 3]]

idiomancy21:09:48

which is actually the case here

ghadi21:09:20

group-by key

idiomancy21:09:42

ahhh, right!

idiomancy21:09:45

hahaha, thank you!

idiomancy21:09:49

that was killing me

idiomancy21:09:32

oh, wait, but that doesnt quite do it. that actually aggregates the keyval pairs

ghadi21:09:49

Need to concat the maps together into a sequence of kvs

idiomancy21:09:45

does the same thing. becomes {:a [[:a 1][ :a 2] [:a 3]]}

idiomancy21:09:52

which isnt quite what was desired

ghadi21:09:39

Then clean them up in a second pass

idiomancy22:09:20

yeah, I just keep seeing this so often I figured there had to be a core function for doing it that i was overlooking

idiomancy22:09:25

with a single pass

idiomancy22:09:43

seq of key vals, want to concat the non-unique elements

ghadi22:09:48

You can do it in one pass by modifying group by slightly

bfabry22:09:08

it's an interesting little problem. personally I'd probably modify all the map values to wrap them in a vector, and then merge-with into

idiomancy22:09:29

modify the map values to wrap them in a vector?

idiomancy22:09:38

you mean like (apply map vector)?

idiomancy22:09:42

to get them by themselves?

bfabry22:09:45

(apply merge-with into (map #(into {} (map (fn [[k v]] [k [v]]) %) [{:a 1} {:a 2} {:a 3}]))

bfabry22:09:58

non specter version

idiomancy22:09:08

yeah, just put the values in single element lists

idiomancy22:09:19

then into works fine

idiomancy22:09:43

ah, this sort of hints at how my problem is not as generic as I thought it was. i actually would prefer the unique keyvals to remain unwrapped

bfabry22:09:45

orrrrr I might generate a seed map with all the possible keys with an empty vec as its value. (apply merge-with conj (zipmap (distinct (flatten (map keys maps))) (constantly [])) maps)

idiomancy22:09:58

yeah, a seed map was y initial thought aswell

idiomancy22:09:20

point is though, theres no simple (merge-with aggregate) in core

idiomancy22:09:23

that im overlooking

bfabry22:09:34

there's no merge-with collect that I'm aware of no

idiomancy22:09:36

oh, hey, one more question. how do i convert keywords (or strings, specifically) into namespaced keywords?

bfabry22:09:16

(keyword ns name)

bfabry22:09:33

(keyword "foo" "bar") => :foo/bar

idiomancy22:09:51

oh how about that. didnt realize keyword took extra args

bfabry22:09:04

neither did I till I hit F1 right then 😉

idiomancy22:09:14

oh how bout that, maybe i should rtfm

cddr22:09:16

How do vim users provide hints for the correct indentation of things like prop/for-all?

idiomancy23:09:32

why is this being marked as an "invalid keyword":

:NCPDP-D.0/2M

bfabry23:09:48

keyword name can't start with a digit

idiomancy23:09:22

well thats a pain in the butt

idiomancy23:09:35

but pretty sensible

idiomancy23:09:45

but inconvenient right now for me

lambeta23:09:02

I am reading programming clojure now. But I cannot get the point of > Variable arity is very useful in recursive definitions. any example?

jeremyraines23:09:08

@cddr I use vim-clojure and put this line in .vimrc let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let', 'render', 'for', 'doall’] which could be expanded

idiomancy23:09:25

@Iambeta I think its just the wording that is a bit confusing there

bfabry23:09:29

@lambeta default argument definitions

(defn foo
  ([x y] (+ x y))
  ([y] (foo 1 y))

bostonaholic23:09:37

(defn foo
  ([] (foo :bar))
  ([a] (foo a :bar))
  ([a b] (apply str a b)))

idiomancy23:09:51

I am fairly sure the author is simply saying "defining the function in terms of itself"

bostonaholic23:09:14

the use of “recursive” is confusing there

idiomancy23:09:07

or, said another way "re-using your existing function definition to describe the behavior of your function when passed a different number of arguments"

dfan23:09:01

@lambeta Here’s a silly example, which may be a little opaque if you’re not used to the style

dfan23:09:23

(defn factorial
  ([n] (factorial n 1))
  ([n acc] (if (> n 0) (factorial (dec n) (* n acc)) acc)))

dfan23:09:59

We pass along an accumulator variable into the recursive case, but we want to be able to call the function in the first place without specifying an accumulator value

lambeta23:09:10

the whole sentences here is > Variable arity is very useful in recursive definitions. See Chapter 4, Functional Programming, on page 85 for examples.

idiomancy23:09:14

without the book handy, the rest of that sentence doesnt really provide any additional context