Clojurians
#clojure
<
2015-11-29
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

albaker03:11:53

do folks still use the friend library, or is buddy the new well supported library?

trancehime04:11:00

I'm new to Clojure and ended up using Friend for authentication, though by the time I knew about Buddy I didn't have enough time to rewrite stuff to use Buddy

jaen07:11:46

I couldn't make head or tails of how to use friend, so I used buddy instead. It's well documented, simple and supports shiny things like JWT.

jaen07:11:52

That said buddy is probably lower level than friend. If you're familiar with Rails then friend woudl be more like devise, while buddy would be more like sorcery.

jonas08:11:03

Same here. I read the friend docs several times but didn’t manage to wrap my head around it. The buddy docs were easy to understand so I chose to use that library instead. I’m sure Friend is great but it was not easy to understand, at least for me.

trancehime08:11:11

It took me a lot of time to comprehend the Friend docs and I admit it took me longer than I expected to get it down

trancehime08:11:45

But anyway, lessons were learned.

rcanepa11:11:02

@andrewtropin: Oh, I will. I thought that lein-figwheel was only for ClosureScript.

jaen11:11:43

If you want easily reloadable Clojure you might want to check out component along with a plugin for boot or lein that automatically restarts your system, but YMMV on writing with component.

jaen11:11:15

It requires you to buy into a certain structure and pass your dependencies around. You can look at mount as a recent alternative that seems simpler (though I must say I don't quite grok how it's supposed to resolve start order of components). There's also yo-yo, but it's pretty monad-ish.

jaen11:11:17

Here's an example of how component + boot looks - https://github.com/danielsz/system/tree/master/examples/boot

rcanepa11:11:08

Thanks… I will check those… I am sure they will be a good starting point. Is boot like a leiningen replacement?

jaen11:11:58

Yeah. It doesn't buy you much over leiningen if you're doing just Clojure but IMO it's considerably nicer when you're also doing Clojurescript.

andrewtropin11:11:04

@rcanepa yep, it's only for clojurescript : ( but it's very live-reloading :)

trancehime13:11:04

Oh... Is anyone still around?

trancehime13:11:20

I had been using "lein run" to check my immutant web app, but I wonder what would be the best way for me to deploy it on a remote server? ec2?

trancehime13:11:27

since it is JBoss, well...

jaen13:11:08

You have two options, really. Well, three. First is install your build tool remotely, ssh in and do the same you do locally. But that's not really all that smart.

jaen13:11:11

Other two options

jaen13:11:54

a) normal uberjar, with -main entrypoint that initialises your application, will just run like a normal application with java -jar

jaen13:11:17

b) wildfly war using the immutant build tool plugin, then you just have to set up wildfly remotely (it's basically untaring and running one shellscript if you don't need much config) and deploying that.

jaen13:11:11

I'm currently doing the third option, but I must tell that packaging a jar is kinda vexing.

jaen13:11:58

(I had much problems with my migration library for example - inside Wildfly you don't get normal files for resources, but some kind of virtual file so I had to patch it a bit)

trancehime13:11:43

I'll just roll with the uberjar then

trancehime13:11:54

Might have to putz around with -main a little but it should be OK

jaen13:11:54

Well, I've had problems with uberjar as well, immutant is getting confused about SSL ceritifcates that way.

jaen13:11:50

But if you don't need that (I wanted to be fancy and use HTTP2) then maybe uberjar is a simpler solution for you. Otherwise I suggest trying to deploy to wildfly.

trancehime13:11:08

My other web app I had to do in Clojure (I made the mistake of doing that entirely in Clojure, but it's a bit late for me to rewrite everything) was something I had to forced to deploy on Tomcat as a constraint and oh my god that was a headache.

trancehime13:11:44

note to self, be more forthcoming about being tasked to do basically fullstack on my own being a stupid idea

jaen13:11:05

Well, apart from having to hack joplin to deal with those VFS files Wildfly was pretty painless.

jaen13:11:55

Granted, that VFS business made me a bit murderous, but I appreciate being able to just put a WAR in a directory and have it deploy

jaen13:11:11

With uberjar it would be somewhat more involved

jaen13:11:57

You're using a database I assume?

jaen13:11:26

What do you migrate with?

jaen13:11:30

(eww mysql xD)

trancehime13:11:36

Not under my control

jaen13:11:47

Yeah, that happens.

trancehime13:11:58

i want to say migratus

trancehime13:11:50

"Your :main function must return when initialization is complete - deployment will not finish until it does."

jaen14:11:28

Looking at the source it might require patching to work with Wildfly's VFS (joplin had similar code for finding migrations) so I suppose you should start out with an uberjar first, maybe you won't have any problems.

jaen14:11:32

Is that a problem?

trancehime14:11:21

Just not sure how I should handle that, since for everything I've done so far I've just dealt with Ring handlers

jaen14:11:35

It's pretty simple really

jaen14:11:11

(defn -main []
  (web/run handler params))

jaen14:11:26

web/run doesn't block.

trancehime14:11:46

TFW that's what I already do

jaen14:11:03

Then it should just work

trancehime14:11:15

Noted, thanks

trancehime14:11:23

(I'm still rather new to all this)

jaen14:11:33

Sure, feel free to ask

jaen14:11:08

I usually tend to run into corner cases more often than not, so chances are I've come across the issues you will possibly encounter.

roelof15:11:06

how can I tell that a file exist in /resources on cursive

roelof15:11:21

Im now getting a file not found error messsage

jaen15:11:29

(io/resource "path/relative/to/resource/paths") should work. If file is you get an URL you can pass to (io/file ...), otherwise a nil. Just make sure you have this directory specified under :resource-paths in your lein/boot project file.

albaker15:11:16

is buddy the successor to cemerick/friend ?

jaen15:11:48

Wouldn't call it that, it's just a library of authentication building blocks

albaker15:11:51

so is cemerick/friend still widely used/supported?

roelof15:11:48

@jaen : Thanks

andrea.crotti15:11:18

probably doing something silly, but can't get yessql defqueries to find my sql file

andrea.crotti15:11:21

(yes/defqueries "full/path/to/create.sql")

andrea.crotti15:11:31

but even(slurp "full/path/to/create.sql") works

jaen15:11:57

@andrea.crotti: it has to be on the resource path. Is it?

jaen15:11:14

(or generally on the classpath)

jaen15:11:27

Take a look at :resource-path in your project file.

andrea.crotti16:11:09

moving it into resources works

andrea.crotti16:11:27

not sure why it would require to be in the classpath since they are just templates in the end

jaen16:11:54

I dunno, probably a Java-ism.

jaen16:11:54

I think if you're deploying your application as jar or war it starts to matter, since then those files won't be relative to the directory application server is running out of.

andrea.crotti16:11:06

ah yes good point

jaen16:11:49

But that's a bit of a speculation on my part, my only exposure to Java is when it sticks out of Clojure.

andrea.crotti16:11:56

another thing, if I use [environ "1.0.1"] and this little tool https://github.com/kennethreitz/autoenv

andrea.crotti16:11:20

to load all the env variables I need, how can I make these variables available in Cider?

roelof16:11:05

how to solve this one : WARNING!!! version ranges found for: [com.datomic/datomic-pro "0.9.5327"] -> [com.amazonaws/aws-java-sdk "1.9.39" :exclusions [javax.mail/mail org.apache.httpcomponents/httpclient commons-logging]] -> [com.amazonaws/aws-java-sdk-core "1.9.39"] -> [joda-time "[2.2,)"] Consider using [com.datomic/datomic-pro "0.9.5327" :exclusions [joda-time]].

roelof16:11:18

or just do what the consider says

jaen16:11:46

If it's inside a dependency there's not a whole lot you can do about that.

roelof16:11:43

yes, I added com/datomic to the dependencies in the project.cli

jaen16:11:28

Well, then just roll with it. Or you can add an exclusion and your own version of dependency, like suggested:

[com.datomic/datomic-pro "0.9.5327" :exclusions [joda-time/joda-time]]
[joda-time/joda-time "2.9.1"]

jaen16:11:15

But I would probably leave it as is - as long as you're not using version ranges in your own code there's not a whole lot you can do about some dependency doing so.

roelof16:11:03

oke, thanks

bill18:11:40

Looking at counted-sorted-set I see that we use conj to insert items (in sorted order) ✓ (makes sense) https://github.com/clojure/data.finger-tree#counted-sorted-set But looking at the implementation of CountedSortedSet I see no direct implementation of conj. I do see an implementation of cons that seems to do ordered insertion. That cons appears to return a CountedSortedSet which I suppose is ok because that isa ISeq. https://github.com/clojure/data.finger-tree/blob/master/src/main/clojure/clojure/data/finger_tree.clj#L577 Two questions: 1. where is conj implemented on a counted-sorted-set? Do we drop through https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L75 into the runtime and somehow the RT calls stuff in CountedSortedSet that gives us conj-ness? 2. As a general practice, if I’m creating a new collection type, would it be advisable to construct a new collection of that type in cons, or would it be more orthodox to set up a process with e.g. lazy-seq?

bill18:11:02

Ah, here we are in RT.java’s conj() https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L649 and indeed it calls the collection’s cons():

static public IPersistentCollection conj(IPersistentCollection coll, Object x){
	if(coll == null)
		return new PersistentList(x);
	return coll.cons(x);
}
So it appears that conj boils down to cons by default.

bronsa19:11:02

@bill no, unfortunately conj is .cons in the java impl

bronsa19:11:11

cons is new Cons(..)

bill19:11:21

Thank you @bronsa. I see that when I call (type (cons 0 (counted-sorted-set 1 2 3))) I get back a clojure.lang.Cons in accordance with the RT code. (comforting) What I don’t see is how/when the cons implementation in CountedSortedSet would ever be called. I set breakpoints on it with Cursive and I’m not seeing it called when I cons or conj.

bronsa19:11:43

if you conj onto a CountedSortedSet, you're going to use its cons

bronsa19:11:46

user=> (conj (reify clojure.lang.IPersistentCollection (cons [_ _] (println "foo"))) 1)
foo
nil

bill19:11:22

That doesn’t square with the fact that I get back a Cons from that call, whereas the implementation in CountedSortedSet returns not a Cons but a CountedSortedSet https://github.com/clojure/data.finger-tree/blob/master/src/main/clojure/clojure/data/finger_tree.clj#L577

bronsa19:11:36

I said conj, not cons

bronsa19:11:21

the cons clojure function returns a Cons, the conj clojure function invokes the cons method on the collection

bronsa19:11:46

the fact that conj invokes a method called cons is disgusting, but that's the way it is, unfortunately

bronsa19:11:15

IOW clojure.core/conj == clojure.lang.IPersistentCollection/cons

bill19:11:23

so one implements the conj behavior on an IPersistentCollection by implementing a method called cons on that interface

bill19:11:13

^ love your proof above, @bronsa. I suppose I need to improve my breakpoint-fu in Cursive.

bronsa19:11:31

(conj coll item) == (.cons ^IPersistentCollection coll item) (modulo coll=nil)

bill19:11:50

to be clear, you called that “disgusting” because it would seem that the method on IPersistentCollection ought to be called conj (not cons) right?

bronsa19:11:01

it's confusing

bronsa19:11:19

an artifact of clojure < 1.0

bronsa19:11:28

that nobody ever bothered changing for whatever reason ¯\(ツ)

bronsa19:11:43

and I guess we'll be stuck with it forever

bronsa19:11:00

just like rest is called more on the actual interface

bill19:11:13

thank you @bronsa

codemartin21:11:05

I'm trying to use M-x cider-debug-defun-at-point in Emacs, and get the java.lang.RuntimeException: No reader function for tag dbg. cider-version is 0.10.0snapshot (package: 20151129.745). My ~/.boot/profile.boot looks like

(require 'boot.repl)

(swap! boot.repl/*default-dependencies*
       concat '[[cider/cider-nrepl "0.9.1"]])

(swap! boot.repl/*default-middleware*
       conj 'cider.nrepl/cider-middleware)
In my terminal, I did boot repl, and in Emacs M-x cider-connect and specified the url:port etc. What can be done about this? Is it the same as https://github.com/clojure-emacs/cider/issues/1218? Sorry for long post, but thank you to anyone who wants to have a look

benedek21:11:58

any better way to turn a namespace into a symbol than (symbol (str (the-ns 'org.some-ns)))?

benedek21:11:04

@codemartin: not sure but it seems you are using emacs package 0.10.0 snapshot but not the matching cider-nrepl. retry with the cider-nrepl 0.10.0-SNAPSHOT

benedek21:11:15

eg in your profile boot:

(swap! boot.repl/*default-dependencies*
       concat '[[cider/cider-nrepl “0.10.0-SNAPSHOT"]])

codemartin21:11:51

@benedek: are those 2 version numbers always in sync?

benedek21:11:15

yes they should be. there should be warnings in your repl after you connected if they are not

benedek21:11:04

you can think of this as the frontend (the emacs package) and the backend (nrepl middleware) of cider

benedek21:11:20

if they are out of sync some stuff might just fail

bronsa21:11:55

@benedek: -no public api-, but (.getName ^clojure.lang.Namespace (the-ns 'some-ns)) would do it

codemartin21:11:14

@benedek: I see. Thank you very much, you helped me a great deal in my sunday evening hacking!

benedek21:11:15

nice one! thx @bronsa

benedek21:11:33

@codemartin: no worries. happy hacking :wink:

bronsa21:11:44

wait. I just remembered there's ns-name that does exactly that

benedek21:11:05

ha! even better! ta

rcrews22:11:03

Came across an oddity. Entered user=> (+ 10 15 56 12 09 55 2 3 15 89) and got an error. Fixed it to user=> (+ 10 15 56 12 9 55 2 3 15 89) and got the wrong answer 55231589266. Ran again and got the right answer: 266. Is this expected?

ghadi22:11:21

hint:

user=> 017
=> 15

ghadi22:11:00

numbers that begin with 0 are in base 8

ghadi22:11:12

wtf, right?

tmtwd22:11:35

what is the whole snapshots thing?

rcrews22:11:06

@ghadi: Thank you for your attention. The error I got seemed straight-forward: "NumberFormatException Invalid number: 09". So I deleted the "0" so that member became only "9", then pressed enter and got 55231589266, then when I up-arrow to recall the previous expression and enter again to evaluate, I get the correct number 266. Are you saying all the numbers are treated as base-8 for that first calculation? Let me check...

ghadi22:11:34

no, unlikely...

rcrews22:11:08

@ghadi: Oh! I think the error made my list repeat to infinity or something. The full original error is

rcrews22:11:29

NumberFormatException Invalid number: 09  clojure.lang.LispReader.readNumber (LispReader.java:330)
RuntimeException Unmatched delimiter: )  clojure.lang.Util.runtimeException (Util.java:221)

ghadi22:11:02

ah, yeah. Ye olde parser fail

rcrews22:11:21

@ghadi: Got it. Thank you so much! You definitely helped me solve it. I appreciate your help.

ghadi22:11:35

> Almost all currently popular computer languages, including C/C++, Java, Perl, and JavaScript, treat a sequence of digits with a leading zero as an octal number. Proponents of treating these numbers as decimal instead have a very valid point -- as discussed in Supported radices , below, the entire non-computer world uses decimal numbers almost exclusively. There is ample anecdotal evidence that many people are dismayed and confused if they are confronted with non-decimal radices.

rcrews22:11:01

Got it. I was typing random numbers to try out that neat trick of summing a whole list using only one operator. The leading 0 was just a typo. I was just surprised that fixing the typo didn't seem to immediately solve the problem. Thanks again.

bronsa22:11:10

the 0 prefix for octal numbers is disgusting, useless and incredibly confusing

bronsa22:11:36

I don't understand why we keep using it in new languages :confused:

ghadi22:11:24

preach it

clojuregeek22:11:31

anyone used hildebrand for connecting to dynamodb ?

euwyn23:11:13

beginner question here. i'm at the repl, switched to the right namespace, trying to call a function defined in a file. function looks like (defn all-products [db] ...), and in the headers there's (:require [datomic.api :as d] [warpcore.db [core :as db] [query :as dq]])). what's the right way to call all-products in the repl?

martinklepsch23:11:20

@euwyn: how are you switching to the ns?

martinklepsch23:11:27

make sure you also require the ns, just using in-ns is not enough I think

euwyn23:11:16

(in-ns 'namespace)

martinklepsch23:11:38

try (require ‘namespace) and then the in-ns call

noonian23:11:28

you would call all-products like (all-products some-db) where some-db is whatever the function expects for the db param.

noonian23:11:34

something like (all-products (d/db (d/connect "datomic:”)))

noonian23:11:00

assuming all-products is just passing it along to the datomic query functions

noonian23:11:41

you might want to make sure all-products is defined by just typing all-products, in-ns will create a namespace if one doesn’t exist which can happen if the files directory path doesnt match the namespace name or something like that

euwyn23:11:43

awesome, thanks! (coming over from many years of rails. if anyone has any rec'd tutorials for someone like myself, please lmk. tried googling around but not finding anything great)

noonian23:11:14

what type of tutorial are you looking for? http://www.luminusweb.net/ is probably the closest thing in the clojure ecosystem to rails, but if you are just getting started you might want to start with learning the language before building a full fledged application. If you do look at luminus, keep in mind that at its core it is just a collection of libraries chosen to work together, and when building a project from scratch you would build up a similar application by adding one library at a time for the different needs of your application.