Fork me on GitHub
#clojure
<
2016-06-17
>
yogidevbear09:06:01

If I didn't have def as an option for assigning the result of a function to something, what would an alternative method be? For example, if I was using map to run some functionality against a list, and I wanted to store the result of the applied map, but I wasn't allowed to use def

yogidevbear09:06:24

Ok, I was thinking along those lines, but I'm not entirely sure on the syntax

yogidevbear09:06:10

I have something similar to:

(fn [lst] (map (fn[x] (...do some stuff...)) lst))

yogidevbear09:06:46

How would I alter this to include the let for later reference within the top level fn?

Prakash09:06:36

(fn [lst] ((let [mapped-value map (fn[x] (...do some stuff...)) lst]) (...)))

yogidevbear09:06:59

Thanks @pcbalodi, I'll give that a try

Prakash09:06:49

let has two parts, a vector where u can create bindings, and other where can use those bindings

m3tti11:06:22

does anybody have experience with cli4clj ?

m3tti12:06:12

i want to have a command prompt with multiple autovompletes like "lin<tab> goo<tab>" -> "link http://google.de"

priort13:06:56

Spending Friday afternoons in work re implementing a Java Microservice in Clojure. Then I'm presenting it to whole Dev team in about 6 weeks. It's a thin service running Cassandra queries but it also needs to run with Dropwizard and Smartstack and include Prometheus health metrics. If anyone has any pointers or experience in integrating these in a Clojure Microservice, I'd love to get some advice, thanks!

mpenet13:06:48

@priort: shameless plug: for the cassandra part you might be interested in alia (and potentially hayt): https://github.com/mpenet/alia https://github.com/mpenet/hayt

parrellav14:06:05

Hell to the yes. I’m using Hayt and Alia right now and it’s aces.

priort14:06:20

@mpenet Yep, I've been using both Hayt and Alia and they are amazing! Thanks a million! I love just specifying my cassandra queries as maps 🙂

mpenet14:06:27

glad it's working for you, feel free to privmsg if you need some info or have suggestions

priort14:06:45

Cool thanks!

meowy15:06:11

So here's an intriguing little problem I'm dealing with.

meowy15:06:41

I'd like to deploy a Clojure app to my server, but as with any JVM project, the uberjar I generate for this is far too large for me to upload, as my upstream speed is awful.

meowy15:06:03

Is there any clever solution to work around this? What I found to work with Gradle is that I could have it build a "distribution" that has a handy shell script to start the app, along with a directory containing the app's jar and its dependencies. This would let me rsync it over without having to copy all the dependencies over and over again, which makes updating my remote app a lot more manageable.

sveri15:06:06

@meowy: You might checkout the sources on your server and build the uberjar there?

meowy15:06:36

That's an option, too, but it's kind of time consuming and messy... prone to issues, too, due to varying system dependency versions.

sveri15:06:15

meowy: Or run some CI server that does that for you and pushes changes to your server?

meowy15:06:46

I've got Drone CI running, but sadly, that only supports pulling from a single source per instance - either GitHub, Bitbucket or GitLab. I do have public projects on GitHub, and while I could set up a GitLab instance for private projects (I don't need private GitHub repos), I'd need to set up another Drone instance.

rauh15:06:47

@meowy: Why not just create a jar instead of an uberjar?

rauh15:06:50

lein jar

meowy15:06:59

That would work, buuut... I need to pull in the dependencies, too.

meowy15:06:26

And that's ultimately what my problem is: My app's dependencies are huge, and I don't wanna push them over my tiny pipe to the server every time I want to deploy.

rauh15:06:04

lein classpath -> rsync them over

sveri15:06:06

@meowy: the point of creating a jar is that you put your dependencies on your server once and pass a classpath option when running your jar

meowy15:06:53

@rauh That sounds like a viable option, though I'd have to create a script or something to parse the classpath and transfer stuff over (likely via rsync).

rauh15:06:04

Well, yeah, you need something non-standard, you won't get around scripting 🙂

rauh15:06:55

The run script then takes the output of lein classpath and runs the jar with it. If you update a dependency you only need to rsync over the new jars, and the (new) run script will also use the new ones.

rmuslimov15:06:27

did I get the idea: 1. lein jar 2. lein classpath 3. start app with java -jar <jarname> —classpath <output from second step>

henriklundahl15:06:01

There's lein lib-dir.

meowy15:06:23

@rmuslimov: You'd have to copy the deps somewhere else and fix the classpath, I think. When you're running your app remotely, which is what I want to do.

meowy15:06:00

Oooh, that's neat.

meowy15:06:34

A really wacky idea would be deploying the JAR to a private Maven repo on the server and using a Boot script to run it.

meowy15:06:16

As far as I'm aware, this should pull in the current deps automatically, so I don't even have to transfer them to the server in the first place.

meowy15:06:33

The Boot script would be trivial, like this one: https://github.com/boot-clj/boot/wiki/Scripts

meowy15:06:57

I actually think this might be the neatest slash least hackiest solution because it doesn't require mucking around with copying dependencies.

meowy15:06:58

Pull in my app as dependency from the local repo (using LATEST as version), then require its entrypoint function and bam.

meowy15:06:33

Thoughts?

hiredman15:06:10

uberjar + unzip + rsync

hiredman15:06:14

you will almost certainly end up with a partial deploy at some point

meowy15:06:27

With which approach?

hiredman15:06:55

anything that enables partial transfers (rsync)

meowy15:06:52

Well, you just suggested that.

hiredman15:06:18

because you wanted rsync

rauh15:06:26

@meowy: If you want to avoid rsyncing the dependency jars you can also just copy over the project.clj and run the lein deps on the server. Or create a lein pom locally and download them with maven on the server. Lots of ways to get it done.

jcromartie15:06:54

I'm trying to use https://github.com/weavejester/environ but I can't get it to stop overwriting my .lein-env file

jcromartie15:06:02

I don't want to put my configuration in the project.clj

hiredman15:06:17

there are lots of ways to do things, doing builds on the server is one, but I cannot say I am a fan

jcromartie15:06:33

and I can't easily put it in environment variables (I think?) because I'm running from Cursive

hiredman15:06:56

you will end up with a different guava jar on your classpath from the one the build was tested with

jcromartie15:06:06

actually maybe a Cursive run configuration is the way to go

meowy15:06:30

Well, yeah, but that's a matter of not forgetting to extract your deps before deploying.

jcromartie15:06:56

ah ha, I missed this part of Environ docs: "The most common way during development is to use a local profiles.clj file in your project directory. ..."

hiredman16:06:53

what I've done in the past is have the ci node push built artifacts to s3, and then the nodes pull new releases from s3, but I haven't tried that in some kind of bandwidth constrained environment, and of course that assumes you have access to s3

rmuslimov16:06:50

may be a noob question, so I runned lein libdir which copied all jar to lib folder. Now I’m calling: $ java -classpath ./lib -jar target/specd-0.1.0-SNAPSHOT.jar Error: Could not find or load main class clojure.main

rmuslimov16:06:55

why I’m doing wrong?

hiredman16:06:26

java doesn't let you use -jar and -classpath together

hiredman16:06:40

(the manpage says they are mutually exclusive)

hiredman16:06:51

but also doesn't throw an error explaining that when you do

rmuslimov16:06:02

cool strategy

rmuslimov16:06:24

so, what to I have this small jar, and all dependency jars. How to start the app?

hiredman16:06:00

java -cp ./lib:target/specd-0.1.0-SNAPSHOT.jar http://whatever.your.main.class.is

cemerick16:06:39

only about 10 minutes into checking out spec; is there already a helper function equivalent to conforming-fn here that will take a value-returning "spec" function and wrap it in a Spec impl so conform will return the value it returns? https://gist.github.com/cemerick/fd824dea77c9736225531a5cc97affee

cemerick16:06:47

(yeah, I know the nomenclature in that gist is off, apologies)

hiredman16:06:55

you can also use the clojure main class and tell it to run a function from a namespace if you don't want to aot compile a main

hiredman16:06:19

(aot is terrible, don't do it)

jcromartie16:06:56

if I have a :dev profile in my project.clj, and a :dev profile in profiles.clj, will they be merged?

jcromartie16:06:35

is there a way to see the actual value of a profile as calculated by Leiningen?

jcromartie16:06:41

I can use show-profiles to get a list of names

hiredman16:06:56

if you pass show-profiles the name of a profile

jcromartie16:06:27

because I already have a :dev profile in my project.clj, the example in the environ readme is not going to work for me

rauh16:06:27

@jcromartie: lein with-profile .... pprint

lockdown16:06:54

hiredman: so you never use 'lein new app foo' ?

hiredman16:06:48

where app is the template or whatever?

hiredman16:06:21

no, I always use "lein new whatever" when I start a project

hiredman16:06:40

not sure what that question is in relation to?

lockdown16:06:40

hiredman: yeah, app is the template, adds :gen-class

lockdown16:06:59

(aot is terrible)

hiredman16:06:21

hilariously the template adds :gen-class, but also marks the namespace as skip aot

cemerick16:06:33

feh, the helper fn is conformer 😛

meowy17:06:19

Alright, I installed Artifactory on my server and uploaded a dep, let's try running this dep via a Boot script...

meowy17:06:25

The neat thing is, I don't even need to make the Artifactory instance accessible from the web, I can just port-forward via SSH on my dev machine and use localhost:8081 on the server. Might change when I deploy to a VPS, but there's always options.

meowy17:06:55

Alright, it works. Guess it's a bit of a hackish way to get things done, but, hey, can't beat only having to upload a few kilobytes.

josh.freckleton18:06:06

How can i get Algebraic Data Types in clojure, a la haskell: data List a = Empty | Cons a (List a)

josh.freckleton18:06:31

I'm trying to do this with protocols, and multimethods, but I'm not sure how 😞

exupero19:06:07

What are you trying to do? ADTs are mostly useful for static type checking and pattern matching. If you want pattern matching, check out core.match.

josh.freckleton19:06:22

@exupero: it is for static type checks and pattern matching. I'm trying to implement so different monads, and it's awkward building my own types via maps. Just curious if there's a way to use ADTs. Oh, and can core.match match on things like types (ie instances of deftype)?

josh.freckleton19:06:01

It seems like it should be possible to have that using multimethods, or protocols, no?

josh.freckleton19:06:37

@exupero: I see from searching around that ADTs were talked about for clojure quite a bit in 2009, but not much since. Is there a better way of accomplishing what I need?

exupero19:06:13

I don’t know much about Clojure’s static typing offerings, but there’s core.typed, Schema, and now clojure.spec.

exupero19:06:45

The closest thing to Haskell-style pattern matching is probably multimethods.

exupero20:06:11

And Clojure can destructure function arguments much like Haskell can with ADTs.

exupero20:06:52

If you can find a hard way to pull off what you're wanting, you can always wrap it in macros to make it more Haskell-like.

weavejester20:06:09

josh.freckleton: Clojure doesn’t have dispatch on return, so implementing monads is a little tricky.

weavejester20:06:03

josh.freckleton: You might want to take a look at https://github.com/funcool/cats

josh.freckleton20:06:33

@weavejester: ah, interesting you should mention cats, I'm trying to build the Free Monad in cats, and trying to port haskell code, but stumped because I can't see a clean way around ADT's, namely for: data Free f r = Free (f (Free f r)) | Pure r

weavejester20:06:19

@josh.freckleton: I’m afraid I don’t really see the problem. Even without a type signature, there shouldn’t be anything stopping you from creating a data structure that resembles the type.

josh.freckleton20:06:30

@weavejester: I'm admittedly new to clojure, and monads in general, so maybe I bit off a bit much. If you look at https://github.com/funcool/cats/blob/master/src/cats/monad/maybe.cljc it has (deftype nothing ...) and (deftype just ...), so I've been looking to them for inspiration, but they're not recursive types like Free needs to be. Can I make a Free recursive type, that can be either Free or Pure? Also, Free needs a functor (the f in the haskell data type), and I can create types that extend cat's p/Functor protocol, but it's not clear to me how to utilize that within a Free type. Thoughts?

weavejester20:06:12

The recursiveness of the types is just a compile-time definition. Any type can be recursive. You could easily write (just (just (just (just … ad infinitum.

josh.freckleton20:06:09

@weavejester: that makes sense. And how do I convey a functor into the Free type? Or in other words, how can I ad hoc build a type Free X, or Free List, or Free String, etc.?

weavejester20:06:56

(deftype Free [f r] …) and (deftype Pure [r] …)

weavejester20:06:13

Just give the record arguments. In the constructor function, perhaps add a precondition.

josh.freckleton20:06:55

ok, this is starting to make sense. and then if, say, List has an fmap, how could I use List's fmap from an instance of Free List? Would it just be (fmap free-list-instance)?

weavejester20:06:47

It looks like you need to create a context for your Free monad, and then have that context implement the Functor protocol.

weavejester20:06:11

Then yes, you could just call (fmap free-list-instance)

weavejester20:06:35

Or (fmap f free-list-instance)

josh.freckleton20:06:02

ahh, I had been assuming the fmap would come from the Free List type definition. But the fmap you mention is probably cats/fmap, yes? If so, I think I've got it!

weavejester20:06:21

@josh.freckleton: Yeah. If you take a look at the definition for the maybe monad

weavejester20:06:31

You’ll see that Just and Nothing are types

weavejester20:06:46

And they implement Contextual

weavejester20:06:06

Which returns a context type, effectively the monad itself.

josh.freckleton20:06:25

@weavejester: Thanks for this! So, I totally respect you for compojure and hiccup, and I'd be curious your recommendation here. Is trying to use monads outside of a strong static type system more effort than it's worth? I want to use a Free monad for implementing DSLs and interpreters, and I know that Haskell would be more comfortable to write this in. But I want the DSL to output code and i like how in clojure, programs are data, and you can easily manipulate the AST. I don't care at all about performance (since it generates textual code). Just, non-bugginess, decreased programmer-time, and being relatively easy to extend/modular. Or is there a DSL "pattern" you would recommend instead of monads?

weavejester20:06:42

I’ve never actually found a need for monads outside Haskell. The cats implementation seems reasonably good, but monads wouldn’t be the first tool I’d reach for.

weavejester20:06:26

By “DSLs and interpreters” do you mean parsing text, or writing macros?

josh.freckleton20:06:15

more macros, so embedded DSLs. I find that in writing web/mobile apps, so many problem-solution pairs are "shaped" the same, and yet it still takes a long time to "stitch" everything together. For example, if I have a mongodb with certain-shaped data, and I want to expose it through a REST API using compojure, and then the frontend needs to consume it, and then the frontend needs to lay it out. I think an embedded DSL would take me a long way in speeding that up by requiring me to only define a data model, and then interpret it through, eg, a Mongo interpreter, a REST interpreter, a REST consumer interpreter, etc.

weavejester21:06:26

I think you need to be a little careful approaching this problem as you might in Haskell. While both Clojure and Haskell are functional, Haskell has a very different way of thinking about problems. In Haskell, you build up a “skeleton” of types, and then construct the solution around that. Clojure doesn’t have a static type system, so problems are solved differently, and IMO, more directly.

weavejester21:06:54

If you’re just transforming data, then my guess is that you need functions, rather than macros.

weavejester21:06:24

Unfortunately I can’t talk anymore, as I need to get to bed! But good luck regardless 🙂

josh.freckleton21:06:44

@weavejester: thanks so much weavejester, you're a huge help and inspiration!

weavejester21:06:05

You’re welcome 🙂

seancorfield22:06:46

Picking up on that discussion, I’d agree that trying to write Haskell in Clojure is probably going to get you into a world of hurt...

seancorfield22:06:02

…whilst Clojure does have deftype / defrecord etc, they’re really designed to let you do ad hoc polymorphism rather than being a "type system" so they’re not intended to support some of the stuff you’d naturally do in Haskell.

seancorfield22:06:51

I would try to do as much heavy lifting as you can with plain functions first, and only then add a few macros for "syntactic sugar". Macros don’t compose like functions so if you start off with a macro-heavy solution, you may paint yourself into a corner.