This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-05-29
Channels
- # aleph (1)
- # announcements (10)
- # aws (1)
- # beginners (110)
- # calva (4)
- # cider (26)
- # clj-kondo (14)
- # cljdoc (24)
- # cljsrn (16)
- # clojure (76)
- # clojure-europe (3)
- # clojure-ireland (2)
- # clojure-italy (15)
- # clojure-nl (8)
- # clojure-spec (23)
- # clojure-sweden (4)
- # clojure-uk (92)
- # clojurescript (37)
- # cursive (19)
- # datomic (59)
- # duct (1)
- # emacs (4)
- # fulcro (7)
- # graalvm (7)
- # graphql (1)
- # hoplon (69)
- # jobs (4)
- # jobs-rus (1)
- # kaocha (2)
- # leiningen (5)
- # luminus (2)
- # pathom (8)
- # reagent (6)
- # reitit (11)
- # spacemacs (12)
- # sql (3)
- # tools-deps (9)
- # unrepl (1)
- # vim (57)
(it expands to what you showed, but makes the steps of processing clear)
one exception I'd make is (println "foo" "bar" (pr-str baz-data))
- that's perfectly clear with the nested call
it's a straightforward way to show a series of operations that use the result of the previous operation, which is legitimate, and clearly what you ware doing
you can also use a let block to bind intermediate data, but I'd prefer to see ->
or ->>
if each step only consumes data from the immediately preceding step
Right. To clarify, the idea of using the evaluation of one form as a parameter to another is not innately bad/crazy/sloppy. But there are a number of ways to make it more maintainable/easier to read: ->
, ->>
, let
, et al.
oh yes, agreed
@noisesmith the let approach is what I'm doing, fun-b
inside fun-a
in a let
but fun-b
side effects, was thinking of passing a fun-b
call as an arg to make fun-a
pure
but what you do above doesn't pass the call - it passes the result of the call (maybe this distinction doesn't matter here)
but you are on the right track - deal with side effects by pulling it up the abstraction stack to callers, rather than pushing it down the stack into callees
that way more of your code is pure
right
sometimes an OO mindset (or something similar) makes people want to hide IO at the bottom of a stack of abstractions, which just multiplies your problems by increasing the amount of side-effecting functions in the codebase
right, getting the value out of IO and passing it into the pure function is the right way to do this when possible
recently saw a video where side-effects are described with maps (returned by functions) and then a "system" takes the descriptions and executes all the side-effects
the author mentioned that is how re-frame does it, but sounded a bit overkill for small apps
yeah, this is an adaptation of a lib for JS where structured data defines updates to be done in a batch because it's a bad idea to do DOM updates directly
but it happens to accomplish this same thing I'm advocating - moving IO and state to the top of your stack of function calls, and pushing pure things to the bottom
well wait, I do a need a third function, can't just put something like (->> z (fun-b) (fun-a x y))
at a top-level
well, you could but it would be bad form
right - and a common gotcha for beginners is that even a (def foo ...)
will do side effects at file load or even just compilation if ...
has side effects
@noisesmith by compilation you mean if someone is doing AOT?
Right
It's not always practical to hoist all of your side-effects right up to the top tho' -- much depends on how write-heavy your app is -- but separating pure and impure is a worthy goal.
This is an experiment of mine in terms of trying to do that separation completely https://github.com/seancorfield/engine in a generic way. The resulting code was hard to read and certain convenient idioms were hard to express.
true, adding a third fn for every two fns to make one pure doesn't make sense, but adding one to make 10-20 pure seems worth it
hihi all, I'm looking at generating an oauth api token for a service I want to integrate with. I'm not using ring in my application so far, but I found this library: https://github.com/weavejester/ring-oauth2 -- has anyone used this in a non-ring context?
What Sean mentioned is usually enough. Use clj-http
client or equivalent to get access token based on the "authorization code" you receive when the user accepts your app as authorized on the OAuth provider's consent page.
@johnjelinek Are you trying to integrate with that service as an OAuth client? Or are you hoping to be an OAuth provide so the service can call you?
the former
@johnjelinek Then you should be able to get the token from the service somehow by authenticating with it.
@seancorfield: at the moment, I want to spin up a datomic ion (HTTP Direct) to receive the auth code from the external service. Then in my repl, I can initiate the oauth2 flow and the service will turn it into a token that I can play with for the duration of my repl session
it looks like this lib is no longer maintained, but it seems to work in a non-ring context so far (for the initiation of the oauth2 flow) https://github.com/DerGuteMoritz/clj-oauth2
I've never used a library for dealing with OAuth tokens as a client. Just simple HTTP calls has always been enough.
In which directory I should keep my my main.js
JavaScript file when using Pedestal to be loaded in index.html
?
In the body of function named index
which is served by interceptor I have put [:script {:src "resources/public/js/main/main.js"}]
.
Hi- A question about namespaces Suppose you have Two libraries: A-lib and B-lib, each with a module x.core. ;; In A-lib:
(ns x.core)
(defn foo [] (println "Greetings fromm A-lib"))
;; In B-lib:
(ns x.core)
(defn foo [] (println "Greetings fromm B-lib"))
Now you start an app myapp and have these dependencies:
...
[A-lib/x "0.1.0-SNAPSHOT"]
[B-lib/x "0.1.0-SNAPSHOT"]
The ambiguity seems to be resolved by arbitrarily picking one:
(ns myapp.core (:require [x.core]))
(x.core/foo)
You get:
"Greetings from A-lib"
Assuming you have no access to the source code of either A-lib or
B-lib, is there a way to retroactively disambiguate our 'x' module,
either in our project declaration or in the require clause?
Thanks.@eric.d.scott At the bottom, the source for dependencies are resolved from the classpath
Or, another way to put it: Clojure/Script provides no direct way to deal with this issue.
That's what I suspected. I was hoping there would be some provision for doing this. Thanks.
Coming from the pytest
python
world, I'm used to having parametrize
to run a test with multiple cases. What's the clojure
way of doing that. Run a simple function with input/output pairs so I don't have to write so many is
statements. (https://docs.pytest.org/en/latest/parametrize.html for reference)
I guess are
is pretty close to the same thing.
@UHUG06517 I’ve also seen ‘doseq’ used to achieve that. I don’t love that solution but it gets the job done
which framework recommend for a restapi?
@rafael.ramos compojure-api 🙂
@comparalf you could also try https://github.com/zalando-stups/swagger1st bit higher level, works directly from the API in a YAML file.
Luminus recommends Reitit with swagger - http://www.luminusweb.net/docs/services.html
I'll take a look at both, thanks!
I am trying to use the figwheel repl from nRepl. I am using this https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl as a guide but I keep getting Could not locate cljs/stacktrace__init.class or cljs/stacktrace.clj on classpath
@mario.cordova.862 what version of CLJS are you using?
To start the repl I use lein with-profile clj,dev repl :headless
and I have added it to the source-paths for both clj, and dev profiles
I found this issue when googling that error: https://github.com/binaryage/cljs-devtools/issues/7
It wasn't that I had old CLJS. It was that I didn't have CLJS listed at all in my dependencies for those profiles 😅
Finally getting around to reading straight through Joy of clojure. I found this remark very interesting > you generally shouldn’t assume seq has been called on your collection arguments, but instead call seq in the function itself and process based on its result. Using this approach fosters a more generic handling of collections, a topic that we explore in great detail in chapter 5. It seems i can't wait for chapter 5 🙂, does this advice suggest that you call seq on all collections arguments? I don't see this widely done, though maybe im not looking hard enough.
I mean, i'm not sure how it helps really. dont most functions that work on collections convert them to seqs?
I think most of the time when we work with things as seqs, we are using functions that already implictly call seq
so this would be advice for making new collection functions that aren't built on the existing ones?
How can I update all dependencies in project.clj? Is it generally a good idea to update them all?
at least the project owner diisapproves of that, but there's a plugin (lein-ancient) that helps find deps that have new versions and even automatically update your project file iirc
Struggling with time stamps. I have a luminus
h2
database with a timestamp
field. I have a test that posts a time using java.util.Date.
then I check to make sure it updated and I get a difference like:
- {:last_login #inst "2019-05-29T19:28:30.456-00:00"}
+ {:last_login #object[java.time.LocalDateTime 0x7c1b5b8f "2019-05-29T15:28:30.456"]}
Test looks like:(let [time (java.util.Date.)]
(is (= 1 (db/update-time!
t-conn
{:user_name "sam_smith"
:last_login time})))
(is (= {:user_name "sam_smith"
:last_login time}
(db/get-user t-conn {:user_name "sam_smith"}))))
Any advice on working with java datetimes like this?Sounds like something in Luminus has extended clojure.java.jdbc
's protocols for column reading to produce Java Time values.
Which is probably a good thing -- and might encourage you to also use Java Time instead of java.util.Date
?
(java.time.LocalDateTime/now)
is the modern equivalent to (java.util.Date.)
Ahhh...That makes more sense to me. Their tutorial had just used java.util.Date.
so I grabbed that one. Worked like a charm!
Yeah, a lot of tutorials still refer to java.util.Date.
because it's been around forever but since Java 8 came out that's a bit of an anachronism really... but the default behavior of clojure.java.jdbc
is to traffic in the older types (`java.sql.Date` and java.sql.Timestamp
as well as java.util.Date
) -- because that's what the JDBC drivers all do by default.
I’m trying to test with clojure. For some reason I am not able to include clojure.test into my code
(ns clojure.test)
(testing "Arithmetic"
(testing "with positive integers"
(is (= 4 (+ 2 2)))
(is (= 7 (+ 3 4))))
(testing "with negative integers"
(is (= -4 (+ -2 -2)))
(is (= -1 (+ 3 -4)))))
clojure blah-test.clj
Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: testing in this context, compiling:(/Users/test/blah-test.clj:2:1)
at clojure.lang.Compiler.analyze(Compiler.java:6792)
at clojure.lang.Compiler.analyze(Compiler.java:6729)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3813)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:7005)
at clojure.lang.Compiler.analyze(Compiler.java:6773)
at clojure.lang.Compiler.analyze(Compiler.java:6729)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6100)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5460)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:4022)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:7001)
at clojure.lang.Compiler.analyze(Compiler.java:6773)
at clojure.lang.Compiler.eval(Compiler.java:7059)
at clojure.lang.Compiler.load(Compiler.java:7514)
at clojure.lang.Compiler.loadFile(Compiler.java:7452)
at clojure.main$load_script.invokeStatic(main.clj:278)
at clojure.main$script_opt.invokeStatic(main.clj:338)
at clojure.main$script_opt.invoke(main.clj:333)
at clojure.main$main.invokeStatic(main.clj:424)
at clojure.main$main.doInvoke(main.clj:387)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:702)
at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Unable to resolve symbol: testing in this context
at clojure.lang.Util.runtimeException(Util.java:221)
at clojure.lang.Compiler.resolveIn(Compiler.java:7299)
at clojure.lang.Compiler.resolve(Compiler.java:7243)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:7204)
at clojure.lang.Compiler.analyze(Compiler.java:6752)
... 21 more
same with
(require '(clojure.test))
note that the example from the docs uses use
https://clojuredocs.org/clojure.test/testing#example-542692d1c026201cdc326f23
same error
which does the same thing :refer :all
does.
neither are recommended nowadays. to make yours work, you could make it something like:
(ns blah-test
(:require [clojure.test :refer :all]))
let me try the repl
note that (ns ...)
at the top of your file should not be clojure.test
(that’s the name of the testing library) but something matching your file hierarchy
your problem is you created a namespace named clojure.test in the repl with your first ns form, which isn't the clojure.test you want
That worked zirth
Thanks for the necessary step I was not adding @hiredman
if you restarted your repl and tried again with a different namespace name it would likely work
Hi there!
This is the first time that I've had to handle circular function calls in Clojure.
In the snippet below parse-expr
calls parse-oper-exprs
, and parse-oper-exprs
calls parse-expr
to parse sub-expressions.
What the is idiomatic way to avoid the "Unable to resolve symbol: parse-expr in this context" error caused by calling parse-expr
on line 3 of the code below? Is there a way to lazily refer to a function that will be defined "later"?
clojure
(defn parse-oper-exprs [oper exprs]
(->> exprs
(map parse-expr)
(map #(str "(" % ")"))
(string/join (str " " oper " "))))
(defn parse-expr [oper exprs]
(cond
(= oper "+")
(parse-oper-exprs "+" exprs)
;...
))
Great! Thanks, @U050CT4HR! I'm clearly still getting to know the core language.
other options include letfn
which allows circular references, and trampoline
which allows a work around for no tail call elimination, but here declare should be fine
Wow! Thanks, @noisesmith. That brings this issue up to 3xTIL for me 😜
declare is the straightforward one, and what you usually want