Fork me on GitHub
#clojure
<
2017-08-13
>
seancorfield00:08:35

@juanjo.lenero What, specifically, are you trying to achieve? There's probably an easier, more functional way to do it (without a macro).

juanjo.lenero00:08:06

I’m going through the clojure for the brave and true book and there is an example with a vector of maps that contain body parts.

juanjo.lenero00:08:21

(def asym-hobbit-body-parts [{:name "head" :size 3}
                             {:name "left-eye" :size 1}
                             {:name "left-ear" :size 1}
                             {:name "mouth" :size 1}

juanjo.lenero00:08:55

You have to then define a function that constructs a symmetric hobby.

juanjo.lenero00:08:45

So I wanted to do something like:

(reduce (fn [full-hobbit part] (into full-hobbit [part (only-if (left-part? part) (right-part part)])) [] half-hobbit)

juanjo.lenero00:08:57

But I extracted that whole [part (only-if …] expr into a function that returns either 1 or two parts depending on if the part has a counterpart.

juanjo.lenero00:08:18

So I guess you were right, I didn’t need it.

seancorfield00:08:20

Macros are very rarely needed. Always try to write a function first. Sometimes you need a macro, but it's not often -- and they don't compose like functions. Sometimes a macro can provide useful syntactic sugar -- but those are usually just wrappers around functions that do the real work @juanjo.lenero

seancorfield01:08:26

BTW @juanjo.lenero You might want to look at cond->: (cond-> [part] (left-part? part) (conj (right-part part)))

juanjo.lenero01:08:04

@seancorfield Thank you, I did run into it, I’ll keep it in the back of my mind, but I’ll avoid it in the meantime.

deva04:08:26

I am referring to an example from http-kit. I am new to clojure

(defn -main [& args]
  ;; The #' is useful when you want to hot-reload code
  ;; You may want to take a look: 
  ;; and 
  (reset! server (run-server #'app {:port 8080})))
From the above example what is this construct called
#'app
?

seancorfield05:08:43

@gdrte What is your question?

seancorfield05:08:09

(and, btw, if you're new to Clojure, #beginners might be a useful channel for you)

seancorfield05:08:00

#'app is a Var reference -- so it provides a level of indirection over just app -- does that answer your question?

andrea.crotti10:08:26

I'm a bit confused about how to exactly set up honeysql and postgres depedencies in a project

andrea.crotti10:08:19

I added at the moment

[org.clojure/java.jdbc "0.7.0"]
                 [org.postgresql/postgresql "9.4-1201-jdbc41"]
                 [honeysql "0.9.0"]
                 [migratus "0.9.8"]
                 [nilenso/honeysql-postgres "0.2.3"]
                 [clj-postgresql "0.7.0"]
which I think it's correct

andrea.crotti10:08:53

but following the docs from honeysql and this code

(def db
  {:connection-uri (get env :database-url LOCAL-DB-CONN)})

(def all-people
  {:select [:first-name] :from [:people]})

(j/execute! LOCAL-DB-CONN (honey/format all-people))
I get
PSQLException A result was returned when none was expected.  org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate (AbstractJdbc2Statement.java:371)

andrea.crotti10:08:42

If I instead do (j/execute! db (honey/format all-people)) I get No suitable driver found for postgresql://....

andrea.crotti10:08:02

and the last thing I don't get is that looking up org.postgresql in Clojars returns nothing, and what actually instead comes back is

andrea.crotti10:08:13

which I'm not sure if it's the same thing or not, but surely it's a different version

schmee11:08:11

@andrea.crotti have you tried using query instead of execute!?

schmee11:08:34

IIRC execute! is used for things that doesn’t return results

andrea.crotti11:08:59

@schmee query seems to work, and I understand the error

andrea.crotti11:08:11

but that's in the honeysql docs so I thought it was correct

schmee11:08:18

hmm, according to jdbc docs execute! “…performs a general (non-select) SQL operation”, so I guess the example is just wrong

andrea.crotti11:08:21

and I don't get the driver error though

andrea.crotti11:08:55

ah ok I can open an issue about that then

andrea.crotti11:08:24

the driver error though I think it's just misleading then

schmee11:08:26

these are the dependencies I have:

[org.clojure/java.jdbc "0.6.2-alpha2"]
                 [org.postgresql/postgresql "9.4.1212.jre6"]

schmee11:08:49

and those work for me at least

andrea.crotti11:08:07

uhm jdbc there is 0.7.0 stable, and you have "jre6" instead of "jdbc41"

schmee11:08:29

yeah I haven’t updated those in a while

schmee11:08:39

but those two are enough to make everything work

andrea.crotti11:08:50

anyway if with query it's fine then I don't really mind, I thought it was related with my dependencies

schmee11:08:08

then I think you’re good 🙂

andrea.crotti11:08:47

it also looks like I never really need to use {:connection-uri (get env :database-url LOCAL-DB-CONN)} but I'm passing LOCAL-DB-CONN directly

andrea.crotti11:08:10

which is a DATABASE_URL, and also seems to differ from what the docs say

andrea.crotti11:08:18

but well as long as it works

gcast12:08:42

hello all. I'm new to clojurians and wondering, do I need to pay money to see the full slack history or is that not even an option?

hmaurer13:08:15

@gcast have you looked at https://clojurians-log.clojureverse.org/clojure/index.html ? I don’t know if it’s complete though

hmaurer13:08:22

Slack’s search feature should work too?

gcast13:08:46

@hmaurer no I have not. thank you.

lxsameer18:08:47

hey folks, how do you use clojure.spec.test.alpha/check with clojure.test ?

beoliver18:08:49

Is there an official way of testing expression equality in clojure? https://stackoverflow.com/questions/45663629/testing-equality-of-clojure-expressions

noisesmith19:08:40

@beoliver no, there's nothing that does this in clojure itself, and I'm not aware of libraries that have the feature either.

beoliver19:08:04

@noisesmith ok cool... Im writing a function to do it now. Just wanted to check that I wan't reinventing the wheel 🙂

noisesmith19:08:25

interesting - I guess that would involve a deterministic renaming of symbols for all locals?

noisesmith19:08:46

so that (let [a 0] a) and (let [b 0] b) would be equal

beoliver19:08:20

Yeah, just implemented it. Seems to work... It also means that (-> foo :blah) = (:blah foo)

beoliver19:08:17

@noisesmith if you are interested a minimal "working" example is

(defn normalize [expr]
  (let [hygenic-form (-> expr jvm/analyze emit-form/emit-hygienic-form)]
    hygenic-form))

(defn unify
  "throws an assetion error if impossible to unify"
  [mappings expr1 expr2]
  (if-let [bound (get @mappings expr1)]
    (assert (= bound expr2))
    (swap! mappings assoc expr1 expr2)))

(defn zipCompare [mappings expr1 expr2]
  (assert (= (type expr1) (type expr2)))
  (cond
    (symbol? expr1) (unify mappings expr1 expr2)
    (coll? expr1)
    (do (assert (= (count expr1) (count expr2)))
        (map (partial zipCompare mappings) expr1 expr2))
    :else (assert (= expr1 expr2))))

(defn unifiable
  [expr1 expr2]
  (let [mappings (atom {})]
    (if (zipCompare mappings (normalize expr1) (normalize expr2))
      true)))

beoliver19:08:50

and

(:require [clojure.tools.analyzer.passes.jvm.emit-form :as emit-form]
            [clojure.tools.analyzer.jvm :as jvm]))

bronsa19:08:36

not sure that would work, tools.analyzer uses the base name to generate hygienic let symbols

bronsa19:08:56

e.g a becomes a__0# and b becomes b__0#

bronsa19:08:14

it can be tweaked to do what you want, but that's how it behaves by default

beoliver19:08:16

@bronsa, yeah, so I just create a series of mappings

beoliver19:08:55

i pass an atom that keeps track so if a__0# ~> b__0# then it must always hold

beoliver19:08:16

(unifiable '(let [a 10] (-> {:a a :b 20} :a)) '(let [b 10] (:a {:a b :b 20})))
true

bronsa19:08:20

ah, gotcha

beoliver19:08:13

although something is going wrong... as the following should not be equal

(unifiable '(let [a 20] (-> {:a a :b 20} :a)) '(let [b 10] (:a {:a b :b 20})))
true

beoliver19:08:54

but when I step debug after instrumenting zipCompare, it throws the correct assertion error on the branch :else (assert (= 20 10))

beoliver19:08:35

just removed the assert and using bools has fixed it.

hmaurer20:08:23

Hi! Quick question: what would be the idiomatic way in Clojure to pipe data through a number of function, each of which may or may not be applied based on a condition (the condition does not depend on the data). Something like this:

(-> data
    (#(if condition1 (f %) %))
    (#(if condition2 (g %) %))
    ...)

chrisjd20:08:46

juxt might be what you’re looking for. It takes a number of functions and returns a new function that applies the arguments to all, returning a vector of the results.

chrisjd20:08:46

user=> ((juxt inc dec #(str "hello, " %)) 123)
[124 122 "hello, 123"]

hmaurer20:08:45

@chrisjd thanks but not quite! I want the data to be piped through: the result of applying the first function (if the condition passes) should be used when applying the second function, etc

gcast20:08:55

or cond->

chrisjd20:08:58

Ah, sorry.

hmaurer20:08:00

The example I added to my message works, but it’s ugly

hmaurer20:08:50

@gcast cond-> seems to be exactly what I was looking for; thank you!

gcast20:08:25

@hmaurer no problem! never actually used it but seen it enough on

Aleh Atsman21:08:22

Hi guys. I have faced such problem. I write my personal ai assistant(chatbot), using http://api.ai, clojure as backend and deploy it to aws lambda. My problem is, that on cold requests, it takes up to 5 seconds to respond. I understand that it happens because of 2 reasons. First is aws internal container/server start up time. And second, jvm start up time. So i want to optimize my side - jvm. I don’t want to write backend in ClojureScript and then use Node.js as host platform. Do someone know, some methods of optimisation of jvm start up time. GC params or something. I appreciate any answers.

hmaurer21:08:00

Not quite the answer you are looking for, but if I was you I would try to keep the AWS function warm

hmaurer21:08:06

e.g. by pinging it every 10 minutes

Aleh Atsman21:08:03

@hmaurer yeah, i was thinking about that. That will work, but if i found a way to increase for 1-2 seconds start up time, that will be definitely better. Now i play with memory settings. Oracle says that big heap sizes lead to big startup time. So i am identifying the minimum at the moment. Will see if it help… Thank you for reply.

Aleh Atsman21:08:27

Oh also. It is impossible to pass jvm param in aws lambda. You use it as is.

seancorfield01:08:40

@U4N27TADS You might try these options to see if they help startup time -client -XX:+TieredCompilation -XX:TieredStopAtLevel=1

seancorfield01:08:58

(I think I got those from the Leiningen site?)

hmaurer21:08:19

Another question: is there an “if-let” construct in Clojure that short-circuits? if-let only allows one binding. I would like a version which allows multiple bindings but short-circuits if any of those bindings are nil

hmaurer21:08:09

Nevermind, found answers on stackoverflow…

lepistane23:08:08

do i need to manage serialization/deserialization of requests on server/client manually? (from transit/json to clj/cljs data structures) i am using luminus template for web apps meaning do i use libs like transit.clj/cljs, chashire.. it's not magically done for me via some built in thing?