Fork me on GitHub
#beginners
<
2018-12-25
>
seancorfield00:12:24

@stardiviner You can add JAR files as dependencies in deps.edn using a coordinate of {:local/root "/path/to/the/file.jar"}

seancorfield00:12:20

for example (from our deps.edn file at work):

com.newrelic.metrics/publish
    {:local/root "/var/www/worldsingles/build/lib/metrics_publish-1.0.0.jar"}

seancorfield00:12:43

I also use that approach for my REBL set up

:rebl ; start REBL and a Socket REPL server
  {:extra-deps {ws/dev {:local/root "../dev"}
                org.clojure/core.async {}
                compliment {:mvn/version "RELEASE"}
                com.stuarthalloway/reflector
                {:git/url ""
                 :sha "58565dda87195478843d7cfdb71371ed29a573bd"}
                com.cognitect/rebl
                {:local/root "/Developer/REBL-0.9.109/REBL-0.9.109.jar"}}
   :main-opts ["-m" "ws.dev.repl"]}
(note: we use :override-deps as well to specify the version for several dependencies, hence the {} for core.async here)

seancorfield00:12:10

That's a nice mix of overridden deps, Maven deps (with "RELEASE" pulling in the latest stable available release -- only do this for dev-time tools, if at all, never for production deps!), Git deps, and local JAR files, and also a local subproject (`../dev`) which is where we keep our dev-only tooling in our subproject.

stardiviner01:12:54

There is one place I still blur. Use :override-deps {org.clojure/core.async {....}} for override specify version for dependency, right?

stardiviner01:12:32

If I use coordinate like {org.clojure/core.async {}} keep empty {} is like using Maven deps's "RELEASE", right?

seancorfield02:12:45

No. The empty {} must be specifically overridden. We have a :defaults alias that includes :override-deps to specify all of the "pinned" versions we want to use across all our subprojects.

seancorfield02:12:18

Even if a version was actually specified above in that :rebl alias, the version specified in our :override-deps will take precedence.

seancorfield02:12:18

We use this in some cases to test against a local, modified version of a project. For example, I'm working on expectations locally and when I want to test against that version instead of the regular published version we normally use, I can specify -A:exp-dev which is defined as

:exp-dev {:override-deps {expectations {:local/root "/Developer/workspace/expectations"}}}

seancorfield02:12:58

Normally, this dependency would be used

expectations {:mvn/version "2.2.0-rc3"
                              :exclusions [joda-time]}
(unless we run tests with :exp-dev added to the aliases).

seancorfield02:12:04

Does that help @stardiviner?

stardiviner02:12:12

I see. Thanks @seancorfield, Sorry for late response, my network for Slack is not stable.

simon22303:12:58

How do I write a function that works like, say, *, so that I can throw additional arguments at it like (* 2 3 4). > (defn multiply [a1 a2] (* a1 a2)) gives:

(multiply 2 3 4)
ArityException Wrong number of args (3) passed to: user/multiply  clojure.lang.AFn.throwArity (AFn.java:429)

simon22303:12:00

oh maybe i need something like [& args], having a play.

mfikes04:12:27

@simon223 If the operation admits it, one nice pattern is to have a variadic arity delegate to the 2-arity using reduce. See, for example, https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L2613-L2618

simon22304:12:38

ok learning some terms here 😄

simon22304:12:46

thanks looking

mfikes04:12:24

You need a "base" binary operation, so if implementing something like multiply and you had a binary *, you could do

(defn multiply
  ([] 1)
  ([x] x)
  ([x y] (* x y))
  ([x y & more] (reduce multiply (multiply x y) more)))

simon22304:12:47

(defn multiply
  ([] 1)
  ([x] x)
  ([x y] (* x y))
  ([& more] (reduce multiply more)))
you can't just do that i guess (ignoring basic syntax issues i assume are present)

mfikes04:12:06

Right, that defines two 1-arity versions.

mfikes04:12:43

A slightly more elaborate average example is in ClojureScript: Up and Running on p. 30. It is good in that the variadic arity isn't just a simple reduce with the 2-arity.

simon22304:12:24

Are = >= not= all just functions?

lilactown04:12:16

@simon223 in your last example you're missing an & in front of more

simon22304:12:39

ah yep gotcha

funyako.funyao15604:12:29

Is there any way to mark a function, so it doesn't get reloaded by cider-refresh or clojure.tools.namespace.repl/refresh ?

seancorfield05:12:45

@funyako.funyao156 You can mark a whole namespace to not be reloaded but not an individual function.

seancorfield05:12:16

(you can't unload/reload a namespace and preserve any elements of it)

seancorfield05:12:05

See https://github.com/clojure/tools.namespace#disabling-refresh-in-a-namespace if you want to mark a whole namespace as not unloadable/not reloadable.

funyako.funyao15605:12:52

@seancorfield Thank you!

vincent.cantin11:12:58

Is there a portable way (cljs/clj) to get an stream out of a string?

vincent.cantin11:12:01

I found with-in-str but I am looking for an alternative that does not bind to *1*.

vincent.cantin11:12:15

in other words, is there a portable clj/cljs function equivalent to the java function java.io.StringReader?

sova18:12:51

I'm trying to selectively render my page and I want to chain a bunch of if statements

sova18:12:09

but doing (if (condition) (do (if ) (if (if )) (if ))) does not play.

sova18:12:27

and do-if kinda doesn't even make sense. but i'm not sure how to group many ifs

mfikes18:12:17

Also, if you have something that looks like

(if test
  (do
    statement1
    statement2))
that could be converted to
(when test
  statement1
  statement2)

seancorfield19:12:29

@sova Are you trying to conditionally put together a data structure or string? Consider that (do (expr1) (expr2)) will only return the value of (expr2) -- the value of (expr1) will be thrown away.

seancorfield19:12:12

If you're building a string, you'll need to call str inside each "block" of values you want to append

(if (condition)
  (str (if ) (if (str (if ))) (if )))
sort of thing

seancorfield19:12:11

If you're build a data structure, then cond-> and into (for vectors) or merge (for maps) will work better (but, again, every expression result needs to be merged in or conditionally conj'd in (with into).

seancorfield19:12:38

Note that for merge, you can have nil values so it's often easier to write

(merge {:base "stuff"}
        (when cond-1
          {:some "more"})
        (if cond-2
          {:and "more"}
          {:else "teh end"}))

tobias.vetter20:12:21

Just upgraded Leiningen on macOS 10.14.2 and now it is broken:

✝  ~  lein repl
Warning: implicit middleware found: cider-nrepl.plugin/middleware
Please declare all middleware in :middleware as implicit loading is deprecated.
Error loading cider.piggieback: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter, compiling:(cljs/util.cljc:1:1)
Exception in thread "Thread-1" java.lang.RuntimeException: Unable to resolve var: cider.piggieback/wrap-cljs-repl in this context, compiling:(NO_SOURCE_PATH:0:0)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6875)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.analyze(Compiler.java:6625)
	at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3834)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6870)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.analyze(Compiler.java:6625)
	at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3834)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6870)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.access$300(Compiler.java:38)
	at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6269)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6868)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.analyze(Compiler.java:6625)
	at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6001)
	at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5380)
	at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3972)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6866)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.eval(Compiler.java:6924)
	at clojure.lang.Compiler.eval(Compiler.java:6917)
	at clojure.lang.Compiler.eval(Compiler.java:6917)
	at clojure.lang.Compiler.eval(Compiler.java:6890)
	at clojure.core$eval.invokeStatic(core.clj:3105)
	at clojure.core$eval.invoke(core.clj:3101)
	at leiningen.core.eval$fn__4201.invokeStatic(eval.clj:343)
	at leiningen.core.eval$fn__4201.invoke(eval.clj:333)
	at clojure.lang.MultiFn.invoke(MultiFn.java:233)
	at leiningen.core.eval$eval_in_project.invokeStatic(eval.clj:367)
	at leiningen.core.eval$eval_in_project.invoke(eval.clj:357)
	at leiningen.repl$server$fn__5963.invoke(repl.clj:278)
	at clojure.lang.AFn.applyToHelper(AFn.java:152)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invokeStatic(core.clj:646)
	at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1881)
	at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1881)
	at clojure.lang.RestFn.invoke(RestFn.java:425)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at clojure.core$apply.invokeStatic(core.clj:650)
	at clojure.core$bound_fn_STAR_$fn__4671.doInvoke(core.clj:1911)
	at clojure.lang.RestFn.invoke(RestFn.java:397)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: Unable to resolve var: cider.piggieback/wrap-cljs-repl in this context
	at clojure.lang.Util.runtimeException(Util.java:221)
	at clojure.lang.Compiler$TheVarExpr$Parser.parse(Compiler.java:710)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6868)
	... 44 more

tobias.vetter20:12:03

✘ ✝  ~  lein --version
Leiningen 2.8.3 on Java 11.0.1 OpenJDK 64-Bit Server VM

tobias.vetter20:12:27

✝  ~  java --version
openjdk 11.0.1 2018-10-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.1+13)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.1+13, mixed mode)

vincent.cantin20:12:14

@sova What you want is a routing function. I recommend you to take a look at one of those libraries: - https://github.com/juxt/bidi - https://github.com/weavejester/ataraxy - https://github.com/metosin/reitit

tobias.vetter20:12:40

Already removed everything from ~/.m2 and a new lein repl installed many of them back, but lein repl still is broken.

tobias.vetter20:12:48

Has anybody a clue how to fix that?

rahul08032720:12:09

@tobias.vetter you seem to have some outdated middleware in your either in ~/.lein/profiles.clj or your project.clj. Try removing them

tobias.vetter20:12:48

Ah yes, it is not the local project.clj, but the global one.

tobias.vetter20:12:05

Can I just delete it and Leinigen and/ or Clojure will generate me a new one?

seancorfield20:12:25

You can just delete it. No new one will be created.

seancorfield20:12:33

(it is optional)

tobias.vetter20:12:19

@ @seancorfield Thanks a lot. It works now!

tobias.vetter20:12:45

Christmas Functional Coding can begin!

seancorfield20:12:53

Outdated stuff in ~/.lein/profiles.clj is the number one most common cause of problems with Leiningen.

sova23:12:43

@seancorfield i'm building a string, maybe merge is the way for that. it's conditional renders for when a user is logged in.