Fork me on GitHub
#clojure
<
2017-03-23
>
hiredman00:03:05

when you invoke a function, the arguments are evaluated

hiredman00:03:32

so if you (def x 1), then (vector x), you get [1]

hiredman00:03:29

if you have some function that runs some kind of server and responds with what you give it, the response would always be 1

hiredman00:03:18

what if while you were working on the server, you wanted to change it to server something other than 1, without restarting it?

hiredman00:03:42

(def x (atom 1)) then have your server code deref the atom you pass in

hiredman00:03:54

works great

hiredman00:03:22

if you want to change what your server is serving, (swap! x inc)

hiredman00:03:50

using var quote is basically that, with some conveniences

hiredman00:03:41

you can pass a var in place of a function if the var holds a function, because vars when invoked as functions invoke what they contain

hiredman00:03:57

vars are mutable references like atoms

hiredman00:03:15

when you define a function like (defn foo [x] x) and then define it again like (defn foo [x] (inc x)) you are changing the value of the var #'foo

hiredman00:03:45

just like (atom 1) and 1 are entirely different things, #'foo and foo are different things

seancorfield00:03:52

@stuartrexking Crossposting to #clojure from #beginners is not encouraged. If you post to #beginners give people a little while to respond (2 minutes is a bit abrupt). As you saw on #beginners people jumped in to help after a short while — bear in mind that you posted after 5pm Pacific time so most Americans have left work… 🙂

stuartrexking00:03:22

@seancorfield My bad. Thanks for the tip.

seancorfield00:03:05

NP. We’re generally a pretty helpful bunch but we have #beginners for a reason — folks can opt out of that.

john01:03:49

Suppose I have a javascript function as a string in cljs. Such as: (def s (str inc))

john01:03:57

(= s "function cljs$core$inc(x){\nreturn (x + (1));\n}")

john01:03:31

how could I then call s, as in: (s 1) => 2

xiongtx01:03:38

@john Seems like a better fit for the #clojurescript channel

john01:03:36

@xiongtx hah.. didn't even notice I wasn't there 🙂 thanks

pseud11:03:05

Is there any easy way in clojure.test to define an 'is' which is run over a list of items ?

pseud11:03:19

(foreach-is, if you will)

miikka11:03:07

What would the usage look like?

conormcd11:03:33

You might like are

pseud11:03:48

are seems to be what I want 🙂 cool

pseud11:03:52

Actually, it partially solves what I want, are still requires me to type out each value (e.g. x & y seen in the first example of https://clojuredocs.org/clojure.test/are)

pseud11:03:27

Ideally I'd like to iter over a list, binding one var to the current element at each step

conormcd11:03:43

doseq over is might work better then.

conormcd11:03:29

Either that or something like (is (every? test-fn test-values))

conormcd11:03:53

But that's not as useful when figuring out which value caused the failure.

conormcd11:03:19

You can get around that with something like (is (empty? (remove test-fn test-values))) if it fits your use case.

darshanime12:03:17

I cloned tools.analyzer, cd'd and ran lein repl

darshanime12:03:44

but it fails to resolve this dependency - Could not find artifact org.clojure:clojure:jar:1.9.0-master-SNAPSHOT in clojars ()

darshanime12:03:08

should I change the project.clj file? :thinking_face:

bronsa12:03:56

add ["snapshots" ""] to your repositories

bronsa12:03:13

{:user {:repositories [["snapshots" ""]]}} in .lein/profiles.clj

darshanime12:03:49

where can I find the .lein/profiles.clj file?

bronsa12:03:00

in your home

darshanime12:03:02

it is not in my ~

bronsa12:03:05

if it's not there create it

darshanime12:03:25

tools.analyzer (master) ls -al ~/.lein 
total 24
drwxrwxr-x   3 radar radar  4096 Mar 23 17:26 .
drwxr-xr-x 121 radar radar 12288 Mar 23 17:41 ..
-rw-rw-r--   1 radar radar    54 Mar 23 17:26 repl-history
drwxrwxr-x   2 radar radar  4096 Mar 23 12:25 self-installs

bronsa12:03:31

I'll add it to tools.analyzer's project.clj anyway

darshanime12:03:32

okay, will pull from master when you add it

elenacanovi14:03:06

Hi all! I have a question about transducers in core async channels. is it idiomatic to define a transducer which depends (without side-effects) on a globally defined atom? I posted a longer version of this question with an example here: https://groups.google.com/forum/#!topic/clojure/JCQmEXkIYms

boyanb15:03:55

It feels dirty, but the main reason is the syntax. Extract the anon fn into it's own validation/safeguard namespaced fn and you'll realize that (filter allowed?) is not that bad, with the only thing being a lookup against an actual atom. If that's your use case, there is no problem with it.

raspasov15:03:13

@elenacanovi is it idiomatic - no; have I done that in the past - yes;

raspasov15:03:53

any purer solutions welcome 🙂 I’m actually curious

boyanb15:03:15

Well, it can't be "purer". You do need actual lookup vs mutable ledger.

boyanb15:03:02

(that is, if you have decided to compose with a transducer). Maybe if you define your composition at a higher level, you can find out the flow of receive->validate->process reads better.

raspasov15:03:14

@elenacanovi I think one purer solution is to always pass ‘banned-users’ as part of the map that goes through the channel

joshjones15:03:48

@elenacanovi if this is for an actual production system, FWIW, you'll need some way to prevent a banned user from spamming the channel in the first place. in other words, you should not be processing data that originates with a banned user

raspasov15:03:03

in a decent sized project I would rarely have more than 2-3 “mutable hacks" like that in areas that I feel that they are absolutely necessary and actually bring about a simpler code structure; so it’s your call to make; but if you find yourself reaching for things like that many times, it might be a place to re-think the overall approach

joshjones15:03:33

yes, as @raspasov said, in some other words -- your "security" is very tightly coupled with your server and very embedded, with this kind of approach. abstract out, if possible

elenacanovi15:03:47

@joshjones well, that was just an example. but for an actual chat you’re absolutely right that banned users should not be able to spam

joshjones15:03:25

@elenacanovi I figured as much, but wanted to mention just in case. But yes, filtering out like this should be abstracted out, and not coupled so tightly

borkdude15:03:48

How does one represent an enum of keywords in spec?

borkdude16:03:08

oh, #{:club :diamond :heart :spade} right?

borkdude16:03:20

sorry, I was searching that page for enum

zane16:03:30

No worries! Lots of people wind up having that question.

zane16:03:40

It makes me happy that the answer is so simple. ☺️

borkdude16:03:15

The joy of Clojure

martinklepsch16:03:23

I’m trying to create an appender for Logback programatically but can’t get it to work. This is the XML config: https://github.com/papertrail/logback-syslog4j#logging-via-tcp-with-tls-recommended and this is how I try to emulate that in Clojure:

(def appender
    (doto (Syslog4jAppender.)
      (.setSyslogConfig (doto (SSLTCPNetSyslogConfig. "" 00000)
                          (.setIdent "my-app")))
      (.setLayout (doto (PatternLayout.)
                    (.setPattern "%-5level %logger{35}: %m%n%xEx")))))

  (.setContext ^ContextAware appender ^LoggerContext (LoggerFactory/getILoggerFactory))
  (.start ^LifeCycle appender)
  (.addAppender (LoggerFactory/getLogger Logger/ROOT_LOGGER_NAME) appender)
Does that look about right?

roberto16:03:43

do you have to set the port too?

martinklepsch16:03:30

@roberto yes, replaced it with 00000 in the above example

roberto16:03:49

ah, was wondering about that 🙂

roberto16:03:44

looks fine to me, but I haven’t really tried to do this in clojure. Are you getting any errors? Or just silently does nothing?

martinklepsch16:03:17

It just silently does nothing 😕 There’s a kind of debug mode but I’m not sure how to enable it programatically

roberto16:03:53

oh, silent errors are the worst

mpenet17:03:47

shouldn't you use a layoutpatternencoder and bind it to the appender instead of calling setlayout directly?

mpenet17:03:02

but I doubt that's the root of the issue, the default should just work I think

martinklepsch17:03:35

@mpenet there’s some more context here: https://github.com/pyr/unilog/issues/21 — interestingly there was a slightly different behavior with and without that setLayout call but I’m not sure how to interpret that...

mpenet17:03:41

yeah usually with unilog you setup your encoder separately then assoc it to the builder map

mpenet17:03:57

otherwise it'll override it with the default one I think

mpenet17:03:45

but then again, not sure it matters

mpenet17:03:36

also not sure how you test it, but when doing unilog-sentry I often had to look into the server process in cider to get to exceptions

tjtolton18:03:44

Any of y'all tried to use clojure jdbc with redshift?

tjtolton18:03:01

I can't figure out what value to supply for dbtype

tjtolton18:03:38

the connection uri I use says jdbc:redshift://...

tjtolton18:03:17

but if I try 'redshift' or 'jdbc:redshift', it errors with clojure.lang.ExceptionInfo: Unknown dbtype: redshift

noisesmith18:03:00

tjtolton how did you add the dep for the jdbc redshift adapter?

seancorfield18:03:41

You can’t use dbtype / dbname with types that are not known to java.jdbc — you have to use subprotocol / classname instead.

tjtolton18:03:30

@noisesmith I did a mvn install on the jar

noisesmith18:03:43

tjtolton that doesn’t add it to your project classpath though

noisesmith18:03:31

tjtolton to use it in your project, it should be in your project.clj (or boot config, or whatever) - mvn install just adds it to your local maven cache, which is not visible by default

tjtolton18:03:45

oh, right, yeah, its in my project.clj too

tjtolton18:03:04

okay.. subprotocol.

tjtolton18:03:20

whats the difference between a subprotocol and a subname?

tjtolton18:03:29

which one should be "redshift" hahaha

seancorfield18:03:19

(I’ve no idea why it’s called subname 🙂 )

tjtolton18:03:53

ahhh, you're amazing, thank you

seancorfield18:03:04

I can add built-in RedShift support to java.jdbc once I have more details about it. I just added the Impossibl PostgreSQL alternative implementation because someone created a JIRA issue with details for me.

tjtolton18:03:32

well, if a line in documentation is cheaper, these values worked perfectly for me:

{:classname "com.redshift.jdbc.Driver"
 :subprotocol "redshift"
 :subname "//<host>:<port>/<database name>"
... <other keys>}

seancorfield19:03:46

I can add a RedShift entry here https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L148-L159 and that will enable built-in support. I definitely need to document this better 😐

seancorfield19:03:21

@tjtolton What’s the Maven coordinates for the RedShift JDBC driver? Or does it have to be manually downloaded?

tjtolton19:03:15

I manually downloaded it, used the mvn install command, then added the dependency to the project.clj. it turned out to be much simpler than I thought

tjtolton19:03:52

the command to install the one I used was

mvn install:install-file -Dfile=/path/to/RedshiftJDBC41-1.1.13.1013.jar -DgroupId=com.amazon -DartifactId=redshift.jdbc41 -Dversion=1.1.13.1013 -Dpackaging=jar -DgeneratePom=true

tjtolton19:03:35

then, the project.clj uses dependencies with the format [groupID/artifactID "version"]

tjtolton19:03:48

so it was [com.amazon/redshift.jdbc41 "1.1.13.1013"]

tjtolton19:03:16

im not sure if it even mattered what I set the groupID and artifactID etc to, since I installed it myself

tjtolton19:03:40

maybe I could have done -DgroupId=bananas -DartifactId=muffins

seancorfield19:03:52

Shame they don’t have it up on Maven Central 😞

seancorfield19:03:01

I’ve added ”redshift” as a known subprotocol for the next release of java.jdbc but I think I’ll enhance how dbtype is used so you can specify a driver that is not known to the library.

seancorfield19:03:24

@tjtolton BTW, did you mean com.amazon.redshift.jdbc.Driver as the classname?

seancorfield19:03:34

That’s what Amazon’s docs say.

tjtolton19:03:59

hmm, interesting. that's not what I used. I just pulled some values out of DataGrip's connection settings

seancorfield19:03:09

Did you use a RedShift JDBC driver downloaded from a non-Amazon site? There seem to be several around.

seancorfield19:03:35

Hmm, just noticed that Amazon have a Maven repo for their driver so you can use that directly in project.clj without needing to manually download anything: http://docs.aws.amazon.com/redshift/latest/mgmt/configure-jdbc-connection-with-maven.html

seancorfield19:03:20

OK, once org.clojure/java.jdbc 0.7.0-alpha3 hits Maven Central (in a few hours), that will be built-in and you can use :dbtype “redshift”, optionally with :classname “com.redshift.jdbc.Driver”.

josh.freckleton20:03:19

I have a piece of code that should be off in development is there an easy way to see (programmatically) what :profile I'm running on, to switch on that?

josh.freckleton20:03:36

or some other recommended way, hopefully without an adhoc environment config variable?

noisesmith20:03:09

your code should not depend on the state of leiningen

noisesmith20:03:32

you can use env to set an environment variable or java property from leiningen that the app can see though

josh.freckleton20:03:40

that's a good point, i'll just stick with something like that

noisesmith20:03:12

@josh.freckleton in particular it’s good to be able to run from an uberjar without leiningen present at all (it’s nice not to have lein on prod)

josh.freckleton20:03:48

true, than you 🙂

noisesmith20:03:22

@josh.freckleton I might not have made it clear, but by env I mean https://github.com/weavejester/environ which makes it easy to set properties from project.clj when using lein and access them in your code (and in prod you can use your java args or shell environment to set the same values)

josh.freckleton20:03:25

totally, that's what I'm using so your advice was well recieved, thank you. I mistakenly didn't want a new environment variable, but that is a better way for solving my current problem

schmee21:03:12

is there any reason to not use clojure.tools.namespace.repl outside the repl?

schmee21:03:46

I’m currently using it to require all namespaces for my applications (-main) method

noisesmith21:03:46

schmee shouldn’t requiring the top level namespace already do that?

noisesmith21:03:56

since require is recursive and all

noisesmith21:03:52

(I use a shim where -main is what requires my real code, but even then I only need to require the top level implementation namespace and that causes everything else to load)

plins21:03:02

hello everyone, im developing a compojure app, and the code inside the handler is getting way too big. i.e:

clj
 (ring/POST "/beneficio" []
       :summary "Cadastro de Beneficio"
       :return {:valorLimiteBeneficio s/Num}
       :body-params [cpf :- s/Str
                     nomeSegurado :- s/Str
                     emailSegurado :- s/Str
                     telefoneSegurado :- s/Str
                     clausula :- s/Str
                     motivo :- s/Str
                     atendimentoId :- s/Str
                     referenciaId :- s/Int
                     dataInicioBeneficio :- s/Str
                     dataFimBeneficio :- s/Str]
       (match
        (benefit-service/create-benefit
         telefoneSegurado
         (benefit/->Benefit cpf
                            nomeSegurado
                            emailSegurado
                            clausula
                            motivo
                            atendimentoId
                            (:id-cc-carro-extra cfg)
                            referenciaId
                            dataInicioBeneficio
                            dataFimBeneficio
                            nil
                            nil))
         [:ok limit-value] (res/ok {:valorLimiteBeneficio limit-value})

         [:invalid-data] (res/unprocessable-entity {})

         [:unkown-error] (res/internal-server-error
                          {:erro "Ocorreu um erro inesperado no servidor :("})))
is there a way to remove this code from the handler and put it inside something like a controller? i could easily create a function but id have to repeat all the parameters already destructured

schmee21:03:04

noisesmith maybe I’ve structured things the wrong way

noisesmith21:03:34

schmee does that mean that you call namespaces that are not in your require block? because I don’t see how else you could have that problem

noisesmith21:03:43

and it should be easy to fix that if that’s why

schmee21:03:58

hmm, what exactly do you mean with “top-level namespace”?

noisesmith21:03:45

schmee either the one with -main, or if you are using a shim, the one the shim loads

noisesmith21:03:23

there shouldn’t be any code path that can hit anything without filtering down from your starting point

noisesmith21:03:38

so requiring that file should make the rest come in too

noisesmith21:03:22

(unless you were using some dependency injection trickery with eg. multimethods, but even then best practice is to require all the implementing namespaces explicitly)

schmee21:03:33

well, my main file is core.clj, but that file doesn’t have any requires in it

schmee21:03:58

because that’s what I’m using tools namespace for atm 🙂

schmee21:03:25

so I was wondering if that is a bad idea and I should require all the namespaces explicitly instead

noisesmith21:03:37

my answer to that is yes

noisesmith21:03:50

it makes things much easier to read and understand

schmee21:03:38

yeah, I guess that’s true

noisesmith21:03:40

schmee I do in fact have a top level namespace for my app without require in the ns form - but this is in order to shim - that is, to have a class a java launcher can call without needing to aot compile any real code

noisesmith21:03:45

since aot just introduces bugs

noisesmith21:03:15

but all the top level ns does is require a single ns - the one with the real main that requires everything else

schmee21:03:46

great, appreciate the input 👍

schmee21:03:10

another question: does lein uberjar entail aot compilation?

hiredman21:03:06

it is complicated

hiredman21:03:17

if you are setup to aot compile, then lein will of course aot compile before jaring everything up

schmee21:03:52

I just realized I have no idea what the hell aot compilation even is

schmee21:03:00

off to wikipedia

spieden21:03:43

@schmee clojure code is usually compiled to bytecodes “just in time” as you load it with e.g. require. aot just does this beforehand and writes JVM class files

zylox21:03:59

"ahead of time" = aot

schmee21:03:47

that sounds like something I’d want

spieden21:03:06

@schmee usually not unless you have some special need

mobileink21:03:30

i thought they were the same wrt generating bytecode, the diff is that aot puts it on disk?

schmee21:03:10

when would I not want to use an uberjar?

schmee21:03:42

I’m guessing for libraries?

spieden22:03:20

@schmee yeah they’re generally used as a deployment artifact for an application

seancorfield22:03:51

@tjtolton FYI, java.jdbc 0.7.0-alpha3 is up on Maven Central now, if you want to try :dbtype “redshift” with that version.

josh.freckleton22:03:57

i have a list of fns and want to (lazily) return the first non-nil, i know there's a pattern but I'm spacing it... help?

tanzoniteblack22:03:42

Do you know the list of functions ahead of time? Or is it dynamic?

josh.freckleton22:03:51

i don't want things further down than a success to execute though

tanzoniteblack22:03:58

if you know them while writing the code, use or:

(or (fn1 some-val) (fn2 some-val) (fn3 some-val))

josh.freckleton22:03:08

ahhhh that's right!

josh.freckleton22:03:14

thank you thank you

josh.freckleton22:03:18

it's been a long day 🙂

ordnungswidrig23:03:08

@josh.freckleton you’re looking for some-fn

josh.freckleton23:03:31

oh that's awesome, didn't know it existed thanks! In my case, each fn is different so I don't think this would work, but I'm glad to add it to my tool belt 🙂

ordnungswidrig23:03:55

Oh, sorry, I misread it, then some-some-juxt is your friend:

ordnungswidrig23:03:51

(some identity ((juxt f1 f2 f3) some-val)))

tanzoniteblack23:03:36

@U054UD60U that's not lazy though, you'd evaluate every function and then throw away any after the first non-nil

ordnungswidrig23:03:48

I think it’s lazy but not short circuiting.

tanzoniteblack23:03:16

juxt isn't lazy

tanzoniteblack23:03:04

(or short circuiting)

tanzoniteblack23:03:46

or is a simple version that works if you have a small number of functions you're checking and they're static and known at code writing time. If they're dynamic, or or is just way too verbose for the number of functions you're using, you'd have to either do (first (map #(% some-val) list-of-fns)) and accept that because map evaluates in chunks, you might call a few extra functions, but not the whole list if it's long enough. Or you'll have to roll your own code to do that (simplest would probably be a loop/recur version that's not lazy, but at least is short circuiting)

ordnungswidrig23:03:08

(reduce (fn [_ f] (if-let [r (f some-val)] (reduced r))) nil [f1 f2 f3 f4]) should bail out quick

ordnungswidrig23:03:31

or even (some-> some-val f reduced)

ordnungswidrig23:03:23

@U236LQYB0 you’re right, juxt is so eager, I just killed my cider repl

tanzoniteblack23:03:39

(loop [fns fn-list]
  (when (seq fns)
    (let [result ((first fns) some-val)]
      (if (nil? result)
        (recur (rest fns))
        result))))
is probably how I'd write that if I didn't know the fns while writing the code (or if there were way too many of them)

tanzoniteblack23:03:44

not lazy, but short circuiting at least

ordnungswidrig23:03:02

how could this ever be lazy if you need to eval up to the first non-nil result and then stop?

ordnungswidrig23:03:27

lazy makes sense if theres a sequence produced but it’s a single result only.

tanzoniteblack23:03:50

(delay (loop [fns fn-list]
         (when (seq fns)
           (let [result ((first fns) some-val)]
             (if (nil? result)
               (recur (rest fns))
               result)))))
for some definition of the word lazy 😄

tanzoniteblack23:03:15

(i.e. you make a valid point, short circuiting is probably what's really important)

ordnungswidrig23:03:56

lazy makes sense if you do something like (some identity (map #(% some-val) [f1 f2 f3]))

ordnungswidrig23:03:14

but using loop/recur or reduces skips the generation of the seq of results.

noisesmith23:03:01

anyone in this thread mention some-fn yet?

noisesmith23:03:51

clojure.core/some-fn
([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps])
  Takes a set of predicates and returns a function f that returns the first logical true value
  returned by one of its composing predicates against any of its arguments, else it returns
  logical false. Note that f is short-circuiting in that it will stop execution on the first
  argument that triggers a logical true result against the original predicates.
nil

ordnungswidrig10:03:14

@noisesmith yes, but it’s not a match. The task is to have different functions and a constant value.

ordnungswidrig10:03:06

@noisesmith actually, some-fn is what to OP was looking for. I had proposed if before but I looks like we got too confused in this thread to realize. upside_down_parrot