Fork me on GitHub
#clojure
<
2017-11-20
>
michaellindon00:11:59

hi everyone, basic question about threading. Why doesnt this work

(-> 10
    inc
    dec
    (fn [x] (* x x)))
I expected output of 100

vemv00:11:31

(-> 10
    inc
    dec
    ((fn [x] (* x x))))

vemv00:11:31

as for the why... this will reveal šŸ™‚

(macroexpand-1 '(-> 10
                    inc
                    dec
                    (fn [x] (* x x))))

michaellindon00:11:20

oh i see it now

michaellindon00:11:22

thanks šŸ™‚

Zach W01:11:08

@ondrej.cermak have you considered a database trigger that writes to a separate logging table on inserts and updates to specific tables?

Andrew01:11:38

@zwhitten Yes I did, but i haven't figured out how to get the current user logged in šŸ˜•

grzm01:11:50

@ondrej.cermak Did I see you're using postgres? If so, CURRENT_USER should give you what you want.

Andrew01:11:38

That would be SQL user, not application user. I would need to find a way to append id of current id to every SQL query for the trigger to work šŸ˜•

Andrew01:11:48

And that wouldn|t be clean anyways šŸ˜•

grzm01:11:53

I'd create a wrapper to the database query functions that takes the logged in user as an argument. Use that data to log anywhere/way you want.

Andrew02:11:23

@grzm that actually sounds good. Are you familiar with sqlKorma ? Im wondering what would be the less possible way to wrap native sqlkorma functions for this to work. There could for example be problem with threading macros

grzm02:11:40

I haven't used Korma before. At a very brief glance, it's too magic for me. I pretty much just use clojure.java.jdbc and write my sql directly.

Andrew03:11:31

Oh, alright .. Well, i came to clojure from OOP languages with frameworks like SpringMVC .. so at least a querybuilder is kinda a must for me šŸ˜„

dpsutton03:11:08

this may be a good time for a simple macro. defquery that takes a user and then just passes everything through to a defn that includes whatever logging form you normally do.

Andrew03:11:41

Oh , that might actualy work.

sova-soars-the-sora03:11:05

Hello, are there any clojure libraries that play nicely with bitcoin, or any bitcoin exchanges powered by clojure?

seancorfield06:11:38

@ondrej.cermak Clojure requires a different mindset to OOP -- but you might want to look at HoneySQL as a composable way to build queries from expressions (which is compatible with clojure.java.jdbc).

qqq07:11:22

is there a way to tell clojure.core/memoize to only keep WEAK references to its arguments ? I need this to be WEAK in both clj and cljs

val_waeselynck08:11:00

@U3JURM9B6 no but I guess it wouldn't be too hard to roll your own version of memoize using weak maps. Be careful of browser support though.

noisesmith17:11:49

@U3JURM9B6 core.cache has these sorts of things https://github.com/clojure/core.cache - itā€™s very flexible but not as easy to use as memoize

noisesmith17:11:36

the key thing for me that made core.cache ā€œclickā€ is that nothing in core.cache knows or cares how your mutable storage is implemented - it has a bunch of functions that accept an immutable hash map, and return an immutable hash-map, and itā€™s your job to figure out what to do with that hash-map in your app

noisesmith17:11:52

compare to memoize, which implicitly uses an atom holding an immutable hash-map that you never touch directly

noisesmith17:11:33

oh, sadly core.cache isnā€™t cljs compatible- I wonder what else is out there

turkkam07:11:57

Has anyone tried Clojure with Google App Engine Java 8 RTE ?

alpeware10:11:40

@turkkam I have been using it for a project for the past couple months and it mostly just works. Most quirks are due to the way the developer server is set up and the REPL. Let me know if you have specific questions and happy to help.

turkkam11:11:07

Have you been using standard or flexible environment ? I was looking at setting up project for standard environment. It seems like you have to do a fair bit of hackery if you want to use leiningen for building the project. šŸ™‚

alpeware20:11:12

Standard environment. Yeah, it takes a little bit, but it's a lot easier now that there are no restrictions on what classes to use. Let me know if you have specific questions and if there's interest, I might publish it as a lein plugin.

alpeware09:11:48

Here's a preview of the latest setup I'm working with. Main draw back at the moment is no nrepl support, but using a socket repl. Definitely a couple of other rough edges, but thought I'll share. For anyone else interested, feel free to reach out. https://gist.github.com/alpeware/f18bef80cb521347d22b85f1ad07ada7

Andrei Zah09:11:43

does clojure have any libraries pertaining to data analysis/data science?

mikejcusack10:11:33

Howdy. What would you guys recommend for putting together a simple ReSTful API for passing JSON from Mongo to a web client?

alpeware10:11:40

@turkkam I have been using it for a project for the past couple months and it mostly just works. Most quirks are due to the way the developer server is set up and the REPL. Let me know if you have specific questions and happy to help.

carocad10:11:55

hey guys, does somebody know the owner of ? I just tried it today and it says that the domain name has expired šŸ˜• Just putting it here hoping it that the owner sees it.

cvic10:11:55

maybe a clone on The repo is here https://github.com/Raynes/tryclojure

bronsa10:11:08

unfortunately the owner passed away last year (see https://cemerick.com/2016/12/07/rip-anthony-grimes/), not sure if anybody else has access to the domain

carocad10:11:27

oh, didnt know that. Well there are now some other websites out there with Clojure repl so it shouldnt be a problem.

tvalerio10:11:49

Guys, is there a beautiful way to implement this in clojure?

(defn handle-job-entity
  [result {:keys [new_agent new_job job_request] :as entity}]
  (when new_agent
    (handle-new-agent entity))
  (when new_job
    (handle-new-job entity))
  (when job_request
    (handle-job-request entity)))
Every time I receive an entity that has this three keys but only one is true at a time

tvalerio11:11:54

ok, Iā€™ll take a look into it tks

vemv11:11:26

@tvalerio I had this in mind:

(defmulti a (fn [result command]
                 (->> command (filter second) ffirst)))

(defmethod a :new_agent ...)
hope it helps!

carocad11:11:42

@tvalerio if all functions use the same argument, why dont you just pass the function as argument? (handle-job-entity new-whatever entity) and inside it, you just do (new-whatever entity)

tvalerio11:11:25

But in that case, how can I know what function to pass? I think Iā€™d have to check that three values

tvalerio11:11:52

Iā€™m having a hard time to go from OOP to funcional

tvalerio11:11:40

Itā€™s a whole new way to think

carocad11:11:34

@tvalerio the code that calls handle-job-entity must know which function to call, otherwise it would not be possible to pass it as an argument as you show above. I assumed that you were in control of that code.

tvalerio11:11:26

Yes, I am. The function that calls handle-job-entity is handle-job-entities

(defn handle-job-entities
  [job-entities]
  (reduce handle-job-entity {} job-entities))

tvalerio11:11:20

So in this function will I have to check some how that same values Iā€™m receiving in handle-job-entity and pass the correct function right?

tvalerio11:11:53

Is this a better approach than implementing using multimethods?

carocad11:11:54

@tvalerio it depends. Multimethods are much more flexible but if you are just starting I would recommend you to stay with the basics. That way you can avoid overloading yourself with new stuff.

tvalerio11:11:53

I see. Good idea šŸ˜¬ But in that case where I pass the function depending on the value of that three keys, wouldā€™n I end up with the same problem before?

tvalerio12:11:56

Iā€™ve tried to do like this:

(declare handle-new-agent handle-new-job handle-job-request)

(def entity-functions {:new_agent handle-new-agent, :new_job handle-new-job, :job_request handle-new-job})

(defn handle-new-agent
  [result entity]
  (prn "handle-new-agent: " entity))

(defn handle-new-job
  [result entity]
  (prn "handle-new-job: " entity))

(defn handle-job-request
  [result entity]
  (prn "handle-job-request: " entity))

(defn handle-job-entities
  [job-entities]
  (reduce (fn [result entity] ((entity-functions (first (keys entity))) result entity)) {} job-entities))

tvalerio12:11:21

But it gives me an Attempting to call unbound fn: #'job-queue.job-queue-core/handle-new-agent

vemv12:11:46

put the def before the last defn

vemv12:11:36

i.e. you cannot do this :new_job handle-new-job before the defn handle-new-job

tvalerio12:11:58

sorry, I forgot that before the defI have:

(declare handle-new-agent handle-new-job handle-job-request)

vemv12:11:01

in that case code looks fine!

vemv12:11:26

might it be that it's inconsistently evaluated into the repl? try loading it from scratch

tvalerio12:11:12

if I remove the declareand put the def after the last defnas you said, It works

tvalerio12:11:43

but why is that? the declare did not bind with the function?

vemv13:11:27

@tvalerio at first sight I would have said the code worked tbh

vemv13:11:37

here's the fix: (def entity-functions {:new_agent #'handle-new-agent, :new_job #'handle-new-job, :job_request #'handle-new-job})

vemv13:11:03

(that's 'var quote' syntax)

tvalerio13:11:26

oh my.. can you please tell me why is it necessary?

vemv13:11:39

declare returns special clojure.lang.Var$Unbound objects, you aren't supposed to handle them directly as the (def entity-functions ... code does

vemv13:11:25

a simpler lesson would be: define things in a way that the compiler can resolve at every moment

vemv13:11:47

coming from other languages you might be tempted to define higher-abstraction-level functions first, it would be nice if Clojure favored that style but it doesn't

dominicm13:11:20

(condp #(get %2 %1) entity
  :new_job
  (handle-new-job entity)
  :new_agent
  (handle-new-agent entity))

dominicm13:11:21

@tvalerio This is how I would approach this problem ^^

tvalerio14:11:24

Thanks guys. I really appreciate the help @dominicm @vemv @carocad !

igrishaev14:11:07

could anybody remind me the easiest way to get start/end of the year for the datetime instance? I checked clj-time sources but without result (or did I skipped those functions?). thanks.

tvalerio14:11:38

@igrishaev did you try clj-time?

igrishaev14:11:14

@tvalerio> I checked clj-http sourcesā€¦

vemv14:11:37

http != time šŸ˜œ

igrishaev14:11:26

oh, my bad. meant clj-time of course.

igrishaev14:11:18

are there any functions to jump at the beginning/ending of some period: week, month, year etc?

rauh14:11:18

It's Java 8's datetime API

rauh14:11:04

Beginning/end of year should super easy, no? Just get the current year and create a new date with Jan 1 & Dec 31st?

igrishaev14:11:21

@rauh thank you, the code looks interesting. Yes, dealing with the year issue would be easy. I just expected some general functions to exist.

igrishaev14:11:43

for example, in PostresQL, there is a great date_trunc function

igrishaev14:11:05

select date_trunc('week', current_timestamp);
       date_trunc
------------------------
 2017-11-20 00:00:00+03
(1 row)

rauh14:11:57

@igrishaev Read the doc string of TemporalAdjuster, it has TemporalAdjusters/firstDayOfYear, and month (and last respectively)

iGEL14:11:48

Hi, y'all! Is there a way to stub clj-time to return a certain time instead of now, when I call (t/now)? I want to write tests and I am looking for something like timecop (a Ruby gem)

danm14:11:44

@igel with-redefs?

iGEL15:11:26

Sounds like it šŸ™‚

danm15:11:27

We tend to write our stuff so that most time-based functions take in a definition of 'now' as an argument. Makes testing easier, and then we generally only generate 'now' in one place in the live code and use it where needed

iGEL15:11:20

let me read about that, found it being used in the tests of clj-time šŸ™‚

hjrnunes15:11:08

Hey guys, I'm trying to manipulate a record in Java. It seems assoc returns an Associative type. Is there a way to get back the same record type or do I have to just cast it everytime?

hjrnunes15:11:02

example:

// c is a record of type "Context" created in Clojure with (defrecord Context [foo bar])
// this returns Associative rather than Context
c.assoc("some_key", "some_val")

//ideally I could just do this
c = c.assoc("some_key", "some_val")

igrishaev15:11:34

@igel you could try using mocking library for that: https://github.com/igrishaev/mockery

(with-mock _ {:target :clj-time.core/now                 
                  :return (date-time 2017 12 31)}
  ... code goes here))

danm15:11:12

What does that get you that a simple with-redefs doesn't?

igrishaev15:11:03

It accumulates info about numbers of calls and arguments.

ghadi16:11:39

There was a recent library I saw that implemented some sort of computation DAG, very much like AWS Step Functions. I lost the link, does it ring a bell for anyone?

ghadi16:11:05

(It's not prismatics/graph)

ghadi18:11:08

that was it, thanks @lovuikeng

lovuikeng22:11:56

from r/Clojure/ šŸ™‚

rnagpal18:11:12

How can I run lein in verbose mode and see the source paths that are used

rnagpal18:11:48

I have set source path in :dev profile

rnagpal18:11:09

:source-paths ["dev/src/clj" "dev/resources" "test/resources"]

rauh18:11:34

@rnagpal One option: run (clojure.java.classpath/classpath-directories) in your repl

rnagpal18:11:12

my main file is not able to find other files in source paths

noisesmith19:11:03

@rnagpal if you look at the classpath in the running repl, all your source directories need to be on the class path (and the namespace needs to form a path starting at a classpath entry matching the namespace name)

noisesmith19:11:31

(System/getProperty "java.class.path")

noisesmith19:11:24

a ā€œsource pathā€ is a leaky leiningen abstraction, all clojure itself cares about is the classpath

rnagpal19:11:29

@noisesmith I do see the directory in class path

rnagpal19:11:46

but I get file not found

rnagpal19:11:53

when I do lein uberjar

noisesmith19:11:56

then the path to your file does not match the namespace, or it failed to load for some other reason and you misunderstood the error

rnagpal19:11:45

Exception in thread "main" java.io.FileNotFoundException: Could not locate ****/system__init.class or ****/system.clj on classpath., compiling:(server.clj:1:1)

noisesmith19:11:53

well, the part where the problem is would be in the somewhere - double check that - is translated to _ and that the file path from the classpath root matches the full namespace

rnagpal19:11:33

is just a single word

rnagpal19:11:39

name of our project

rnagpal19:11:03

without any - or _

noisesmith19:11:16

and you have a //system.clj on the classpath during uberjar creation?

rnagpal19:11:55

How can I check the classpath while uberjar ?

noisesmith19:11:39

lein with-profile uberjar cp

rnagpal19:11:00

yeah @noisesmith its not there

rnagpal19:11:08

Its in dev profile

noisesmith19:11:18

dev profile is for things you only use in dev

rnagpal19:11:19

and isnā€™t dev profile loaded by default ?

rnagpal19:11:40

lein with-profile dev uberjar

noisesmith19:11:40

itā€™s specifically for things you want during dev but not while making an artifact

rnagpal19:11:47

should this work ?

noisesmith19:11:05

donā€™t do that! if you need the source files in your uberjar, put them in the normal source paths, donā€™t put them in dev

noisesmith19:11:40

if you add the dev profile to your uberjar command, you also pull in things that are only needed during dev (especially a risk with tools like cider that add to your dev profile)

noisesmith19:11:01

it would also mean your test files would end up in the jar - not usually what people want

rnagpal19:11:18

Thanks @noisesmith I was stuck on it for some time. Didnt know how to check class path.

rnagpal19:11:37

Can you please explain this command

lein with-profile uberjar cp
in one line

noisesmith19:11:07

it says ā€œuse the uberjar configuration, and run the cp commandā€

noisesmith19:11:24

ā€œlein cpā€ would run lein with the default profile and show the classpath

noisesmith19:11:55

you can also use lein with-profile +foo ... to merge rather than replace profiles

rnagpal19:11:22

okay so :uberjar it self is a profile

rnagpal19:11:42

one that comes as default with lein ?

noisesmith19:11:45

uberjar is a profile, yes - you can see a lot more example and info in the output of lein help sample

h.elmougy19:11:11

any recommendations of mocking libraries ??

ghadi19:11:44

clojure folks tend to avoid mocking

bostonaholic19:11:14

depends on the features you need, but we (CircleCI) use https://github.com/circleci/bond

ghadi19:11:01

I have had good success in the past with making protocols that represent external side-effects (e.g. a mail server) and then reifying dummy impls.

bostonaholic19:11:04

very simple and light

h.elmougy19:11:08

@ghadi but how can i test a function that depends on another one that calls external systems or has side effect

h.elmougy19:11:35

@ghadi I got your point

ghadi19:11:44

if you feel the need to mock, you might have a global that needs to be an argument.

bostonaholic19:11:10

^^ thatā€™s an awesome way to think about it

ghadi19:11:12

(I'm speaking in vast generalities)

noisesmith19:11:15

ideally the external functionality has a thin wrapper that you can easily cover with integration tests, and you can pass in an alternate stub implementation for testing things that use it

noisesmith19:11:27

(I think this expands on what ghadi was saying)

noisesmith19:11:28

sometimes itā€™s even worth making a protocol, in order to have two implementations (the stub and the one that uses some external / stateful / side effecting resource)

ghadi19:11:59

If you're using Ring or similar, you can make a middleware that inserts the appropriate implementation into the request context, that way you don't have to grab it from a global var

h.elmougy19:11:07

@noisesmith @ghadi I got the point but I really don't know why we should avoid mocks? aren't they easier than stubing protocols?

noisesmith19:11:53

they lead to unneeded complexity, you end up wrangling an implicit global state in order to verify something that shouldnā€™t care about it

noisesmith19:11:15

with-redefs for example causes a multitude of problems, including preventing parallel testing

noisesmith19:11:25

if you really want the easier / global / implicit thing, at least implement it in terms of something that uses an explicit argument to the function - you can easily build implicit / global / stateful out of explicit immutable arguments, but it is much harder to go the other way

h.elmougy19:11:24

valid point but this will add too many types and records which i try to avoid most of the time

noisesmith19:11:38

you can do it without a protocol or record - I only mention using a protocol (which in my practice means using a reify in the test, and either a record or reify in the implementation) - because that can simplify the swapping of implementations

noisesmith19:11:49

if you prefer functions, use functions, it does work

johanatan20:11:19

are there any known gotchas involving partial application around a stest/instrumented function ?

rnagpal20:11:25

I get this error Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method, or the namespace has not been AOT-compiled.

noisesmith20:11:32

you can run an uberjar without AOT if you can specify the java command line: java -cp my-uber.jar clojure.main -m my.ns

noisesmith20:11:53

if you need the jar to be startable or loaded by some other java process, you probably need aot though

rnagpal20:11:19

Thanks @noisesmith. I was missing (:gen-class)

rnagpal20:11:22

in the main file

josh.freckleton21:11:22

I have a wrap-auth fn in compojure-api, and an endpoint where I'd like it to be conditionally applied contingent on a query parameter is that possible?

josh.freckleton21:11:00

ex, either they're authenticated, or a query param has a valid signature (in which case, non-authd is fine)

noisesmith21:11:15

yes, you can make a middleware that either returns the handler unchanged, or applies a middleware, based on some property of the request-map

noisesmith21:11:22

something like (defn conditional-middleware [pred? middleware handler] (fn [request] (if (pred? request) ((middleware handler) request) (handler request))))

noisesmith21:11:43

if you donā€™t like (( you can use let to bind the wrapped handler

josh.freckleton21:11:00

oh nice, I think that'll work thank you!

noisesmith21:11:20

the devilish thing with ring is itā€™s very flexible and things like this are easy to apply, but it can be very hard to debug when you have enough wrappers like this - my theory is that pedestal interceptors are an improvement as they are data you can investigate on the fly but havenā€™t used them in anger

josh.freckleton21:11:46

I'm in the same camp, anytime I can convert "effects" to data, it tends to be a win

tbaldridge22:11:35

Ring is also rather anti-async, you can bolt-in async stuff, but it doesn't work super well.

josh.freckleton23:11:51

relatedly, I have a :path-param that I'm trying to pull off the request in my wrapper but the best I can find on there is :path-info which has my route un-parsed is there place I can get a parsed :path-param, eg for myroute/:x, (get-in request [:path-params??? :x)

hiredman23:11:34

basically "no"

hiredman23:11:57

longer answer is it depends on which library you using for routing

hiredman23:11:58

even longer is it depends on which library you use for routing and if you use it to do routing before or after your middleware is run