Fork me on GitHub

thanks @meow it is nice to know that in 8 months you achieved a lot, I've been reading clojurians channels for a week and you are very active on them


Lein and boot are the two standard build tools. I use lein for simple things or if there is a good template or with figwheel. For more sophisticated stuff I use boot. Both will be around for some time so it pays to learn something about both.


The #C053K90BR channel provides great support as boot can sometimes be a bit of a learning curve depending on your background.


For unit tests I've just used the regular test library, but there are several good variations like the expectations that @akiva and @donmullen mentioned. There are also libraries that can do generative tests. It really depends on what style of testing best matches your domain and personal preferences, which is not a bad thing at all.


I’m 100% Spacemacs but that’s mostly because of my vim background. There’s a #C09C8GRLY channel, too, btw.


thanks, I will definitely bother you guys a lot simple_smile


@esnunes: Definitely check out simulation testing / generative testing at some point. Good resources are Mike Nygard’s talk and podcast :


Anybody using bool.clj ? After updating boot I get the following exception: Multiple jar entries match : .*/pom.xml Anybody has an idea what could cause that exception.


@msattel You may want to ask this in the #C053K90BR channel. They are very quick to respond.


thanks for that hint


@esnunes: It may take time, but Boot will probably become the build tool of choice for Clojure development. I don't know anyone who switched back. It's just that good.


Is clojuredocs broken? The link to source for if is:


@danielsz: I do. But I still agree with your point. Boot is great. But lein will be around for some time. They work well enough together.


@meow, coming up fine for me.


not for me


the source code link


probably because, you know, what mike is pointing out on #C053AK3F9


@jonahbenton: I just wanted to let you know that I got the thing working and wanted to really thank you for your help


thank you- glad to have helped, i learned something too


Can anyone recommend a maintained for of clj-oauth2 that they use? The original owner did not update it since 2012 and there exists a forest of forks to chose from 😞


That library is in a depressing state, I must say. Are there any precedent cases that show how to consolidate such a mess? I mean, I need to make a change, and given that there are also dozens of published versions of clojars (with the more recent ones pointing to nonexistent upstream sources), the only way to make progress for me seems to also fork, make the modifications in my own repository and then, eventually, publish yet another version in clojars, which seems to be not very good.


Or, alternatively, can anyone suggest another, better-maintained oauth2 library that works with Google's APIs?


@hans: is anything about this problem unique to clj versus cljs because surely the cljs folks are using oauth2 as well so you might want to ask there as well


as well as well as well




@meow: Ah, thanks! friend may indeed me my best option. I've avoided it because I thought it did too much, but it may be better than fiddling around with clj-oauth2


anything is better than a broken 4 year old library


It is not that it is broken, it just was missing a feature that I needed.


oops, my bad


but close enough


And as the article you've linked to (thanks) describes, OAuth is not a rigid protocol, but rather a set of guidelines, so once you have something working with the provider you need (Google in my case), there is quite some reluctance to change horses.


Unless the other horse has a specific Google saddle, of course simple_smile


But anyway, thanks! I'll work with my fork for now and use friend next time I have to deal with this. I wanted to look at it anyway.


The discussion how a forest of forks can be reconsolidated would also be interesting, but it is not even clojure specific.


Is my google-fu just weak tonight or is there no existing Clojure IRC server worth speaking of?


I don't think I've ever seen anything other than so yeah, probably no.


This has been asked many times probably. I still couldn’t find satisfying answer. How can I find what's the latest version of a particular library availible in Clojars, right from the command line? I guess I could use lein search but I can't find right combination of arguments. It keeps giving me crap


@hans from my understanding this helps you to update existing dependencies in a project. What if I’m starting a project from scratch and need to know latest available version of a library


ag: it is common to list the latest version on the project's github page. in fact, that is so common that I never saw that as a problem. is there a specific library that you're interested in?


+1 for lein ancient


it just doesn’t make sense to me that you actually need to go open a web page - either it’s github or to figure out latest available version of a lib. I thought that’s what lein search for. I tried for example lein search “id:lein-cljsbuild version:SNAPSHOT” but the latest version didn’t come up


@arrdem: ancient helps you to update dependencies that you already added. But what about figuring out latest available version before adding a dependency?


@ag: I don't know of a good tool for doing that. Even the clj-refactor tooling for adding project deps only shows you versions in your ~/.m2


It may look like I’m complaining, I’m not. I’m just very new to Clojure and already see how amazing it is. Not just the language, but the entire ecosystem and the community and practices. It feels strange to me that I could’t find the equivalent of npm install or cabal install or pip install or gem install, but for clojars


@ag: I can see where you are coming from and sort of felt that same way but it just isn't an issue


find the github project or clojars page


super simple


not sure if boot has any kind of search like that


Eh... that I'm not sold on.


if you just want to add the latest one.


Due to performance limitations of Clojure startup time and transitively leiningen, lein is pretty minimal as language build tools go 😐


> Due to performance limitations of Clojure startup time and transitively leiningen, lein is pretty minimal as language build tools go yeah, now it makes sense to me, it’s just quicker to open clojars page


Right. You can start a JVM in milliseconds, but Clojure's self-bootstrap takes ~2.6s on a good day.


I had a project a while back.. Oxcart.. which tried to fully AOT Clojure so it didn't need to do that and well it's dead for reasons.


but dependencies are based on Maven structure, aren’t there generic java command line tools for what I want that would be a lot faster?


There may be mvn plugins to do this, but it looks like stock Maven does not have a user visible search feature either.


oh! I got an idea. maybe have a public api and I could use curl or whachacallit to find things, no? simple_smile


@solicode: yay, nice! thanks


if anyone needs it

clj-search () {
    curl -s -H "Accept: application/x-yaml"  | grep latest_version;


@arrdem: 2.6s is nowhere realistic, java -jar clojure.jar takes 0.5/0.6 to start on my laptop


it's lein repl that takes ages, but that has nothing to do with clojure


Hi there! I need some help understanding the exact flavor of laziness you get with sequence + transducers. Here's a little gist: In particular, I'm wondering about partition-by running 331 times. Any help is greatly appreciated!


@hemmvm: I don’t know how it works internally, but I’m guessing this has something to do with chunking.


instead of doing things 1 at time, things being done by 32


@solicode: Sure -- that's why identity* getting called 33x seems ok-ish to me. But 331x for magnitude ?


@solicode: I would have expected magnitude to be called 33x -- i.e. for each of the 32 items of (range)'s first chunk


Hmm, I’m not sure to be honest. I’d have to look at the source


@solicode: I think I understand it... (I'll be right back in 5mins)


ok simple_smile I’m curious too


Transduction is fundamentally push based. So sequence basically works in reverse: lazily consuming inputs from the original source (pull), feeding it to the transducer (push).


In the case of (first (sequence (partition-by* magnitude) (range))) you basically ask for 33 partitions (due to chunking!!), thus calling magnitude 33 * 10 times.


Another catch is that some transducers may not produce any output for a given input (push) -- think filter. So sequence has to consume inputs from the original source (pull) until the transducer actually produces at least one output, i.e. possibly being somewhat less lazy than you might expect.


More generally speaking, you'll pretty much get that partition-by kind of behaviour for any kind of "reductive transducer"


Anyone know why promotion is disabled on All of my projects are showing a “promotion is currently disabled” message.


@hemmvm: don't understand how you see transduction as push?


Basically, the transduction / any single transduction step will not run unless explicitly called. i.e. the transducing context is responsible for actively driving the process ("pushing into the transduction")


are you sure


> The other thing that's tricky about this is it sort of changes the notion of what it means to be lazy. And I don't really want to change that. I just want you to think about another notion of lazy. Transducers are fundamentally push. You supply input and then the logic runs. They're not fundamentally pull like lazy sequences are.


just thinking out loud I think this part is important:

You know, we like our words in Clojure, so reduce means to lead back. I'm not going to talk much about the ingestion part in the rest of this talk, but transduce means to lead across, and that's definitely what transducers do. They're leading the input across the series of transformations on the way to, well, maybe reduction or maybe something else, some other process. But they lead them across a transformation process, so the name makes sense.


Sequence will take a collection and produce a lazy view of that collection, having pulled it through a transducer.


I have to catch the train -- I'll be back in about 4-5 hours


ok, I'll flesh this out


Okay, so what does transduce do? It calls reduce.


I think I see


rich is saying that transducers are fundamentally push. transducers not transduction


Sequence, the function, implements pull by going around the other end and saying, well, you wanted something, so I'm going to take another input and feed it to the step function. Now we just said one tricky bit is you may ask for something and I put it through the step function, and the step function gives me nothing, in which case I've got to keep doing this until I have one thing to return to.


But what else could this have done?

[Audience response]

It could have returned one thing each time I ask. It could return nothing. It also could return what?

[Audience response]

More than one thing. Where is that going to go? I asked for one thing. You called the step function. It gave you, like, six things. What's going to happen?

[Audience response]

Yeah, I'm just going to attach them to the linked list, which means that it's not quite this laziness we're used to.


We're used to saying, "Don't run any little part of the calculation until I ask for one thing, and then just do exactly that much work," which ends up being a huge amount of overhead. Now we're saying you're going to ask for one thing. What's actually lazy is not your consumption, but the production. In other words, we're lazily going to add only as much to this to produce an output to give you, but each step might produce more than one thing, so it's kind of pushy.


make sense now?


I wanna get with you, only you, and your sister, I think her name's Debra!!!!


sorry, beck, good stuff


It's lazy in the input consumption, which means if you have something that expands through an infinite sequence, it's not going to work. If you have something that, in a single step, expands to something that consumes all of your memory, that's also not going to work. In particular, it's not going to work because, even if your result produces something lazy, it's going to be eagerly consumed. Nothing inside any of the transducers uses laziness at all because we want to be able to have these other semantics.


That's something to be aware of. A lot of people initially trip up over, you know, trying to use something lazy in a step and are surprised that it got fully realized. But that's the nature of this.


@ag: this isn't exactly what you were asking about, but you can always get the latest release (non-SNAPSHOT) or latest version (could be SNAPSHOT) with [foo/bar "RELEASE"] or [foo/bar "LATEST"], respectively. You can then see what version the tool actually downloads, and pin to that.


I still think this is a useful granularity for laziness. I don't think people are consuming all their memory in a single step. Otherwise, this gives you the best of both worlds because you get very high performance and only as much caching as you need per step, and it still is sort of windowed, so I think it would work for most things, but it's something to be aware of.


that should about do it


@bronsa: huh that's what I was measuring during Oxcart weirdness. Delighted to hear it's gone down.


I don't think it's ever been any different


1.47s via

time java -jar ~/.m2/repository/org/clojure/clojure/1.6.0/clojure-1.6.0.jar << EOF    


might have improved by a couple of deciseconds maybe, definitely not more than 2 seconds


@arrdem: well, that runs in 0.9s on my machine. I get it down to 0.55 by using -server -Xverify:none -XX:+AggressiveOpts -XX:+TieredCompilation


$ time java -server -Xverify:none -XX:+AggressiveOpts -XX:+TieredCompilation -jar ~/.m2/repository/org/clojure/clojure/1.6.0/clojure-1.6.0.jar 2&>1 > /dev/null <<<''
1.22s user 0.05s system 212% cpu 0.599 total


most of that time is spent downloading more RAM


Hi im running lein migratus create and getting this error: Does anyone have any insights?


isn't it lein migratus migrate?


@tmtwd: I want to to create the file


I was under the impression that create would generate the file for me


not sure tdh


@datajohnny: looks like the create fn is only in the lib, not in the plugin. so you would need to be in a repl to do migratus/create


@meow: I was thinking about Boot vs Lein, maybe the main difference is declarative vs functional.


comparing to nodejs world, webpack vs gulp


@jonahbenton: I was able to figure it out, the issue was a bug on the version of the lib that I was on,


in case you would start a project today, would you use stuartsierra component or danielsz system ( library?


Although system has LOTS of great stuff.


yeah, the question is more between component and mount. system is component, with some pre-fab components.


thanks guys