Is https://github.com/dakrone/clj-http the preferred http client? Just for basic requests / polling / API exploration? New to Clojure I donβt know what the go to libraries are yet
Or would http-kit
be a better choice>
I'd say the "most common default" one is Jetty with Ring: https://github.com/ring-clojure/ring/tree/master/ring-jetty-adapter
Oh sorry, HTTP Client?
Hum, either or, if its just for basic requests / polling / API exploration I'd go with HTTP Kit client personally, because its got zero dependencies. clj-http brings a lot of dependencies.
Sounds good to me. Thanks! @didibus
The built in java http client is pretty good. I would recommend clj-http over http kit, especially for exploratory stuff to avoid having to decide how you are going deal with multiple threads
@hiredman What do you mean? This is all you need to do:
(require '[org.httpkit.client :as http-client])
@(http-client/get "<http://google.com>")
You are queuing up work to happen on another thread and then waiting for it, which is not the same as doing it on the same thread.
At the very least you have this global httpkit thread spinning doing work, which it will continue regardless of what happens to your thread
I don't really see the issue...
We mostly use clj-http at work but there are a couple of places where we need to be able to cancel HTTP requests after a fixed timeout period and we use http-kit's client for that since clj-http doesn't seem to have a way to do that (and we're using an old version of clj-http because recent version break some things in our tests).
I like the simplicity of http-kit's client, but hiredman's point is important.
http-kit's client request pool (default): https://github.com/http-kit/http-kit/blob/master/src/org/httpkit/client.clj#L86-L89
For exploration that default seems fine, and then if you need to become much more serious, it lets you specify your own.
Also, from peeking at the impl of http-kit, the client seems to multiplex NIO, so there's only one thread doing the request, the thread-pool is for your handlers.
Hi there. I've come across tap>
and am not sure when and where it should be used. From the Clojure release note, it's said that:
> tap is a shared, globally accessible system for distributing a series of informational or diagnostic values to a set of (presumably effectful) handler functions. It can be used as a better debug prn, or for facilities like logging etc.
But how is tap>
any different from, say, normal logging? Thanks in advance π
It isn't intended for logging but it is awesome for debugging.
Tools like REBL, Reveal, and Portal all "listen" for tap>
'd values and display them.
I've been using clj-http with great success, very easy to use.
(funnily enough, I just gave a talk to London Clojurians today that featured tap>
and I talked about it -- the recording should be up soon)
Looking forward to it. Thanks π
The great thing about tap>
is that you can leave it in your (production) code and the attach and detach various listeners (using add-tap
and remove-tap
).
Assuming there are no add-tap
calls that do bad things, right?
Right. I was assuming no tap listeners (except when debugging).
Ah I see. So unlike typical (println value)
, tap>
allows you to dynamically configure how value
will be handled based on which tap you're attaching, so, say, you may have a tap to print a full value in dev but a different tap to print only important bits in test. Am I getting close?
Not quite. All tap>
'd values go to all listeners, but the important part is that those listeners get data so they can choose to display it graphically, or in a table, or whatever.
But each tap listener can decide what to do with each value, based on its structure.
You can (add-tap println)
and get the same regular printed output, or (add-tap prn)
to get readable printed output, or (add-tap some-graphical-ui)
to display data in a GUI. Take a look at https://github.com/vlaaad/reveal/ to see the sort of things that you can do with tap>
output.
That's handy. Now I see how one would want to use it over normal println
. Thanks a lot for the explanation :D
to be clear, I am not saying don't use http kit, or that there is something wrong with http kit, it just would not be my first choice for fiddling around. if I wanted some with no dependencies I would use the http client that comes with java, if I wanted something to use without thinking too much about it I would use clj-http
how would you do fetch
in clojurescript? is https://github.com/r0man/cljs-http a de facto client? or would you just use the fetchAPI or axios?
There is also https://github.com/JulianBirch/cljs-ajax
A late good morning all
Maybe this is more of a beginner question?
first question of the day. If I want to ask a api several times to keep all the responses can I then do (let [answer] (repeat 3( slurp ........)))
?
I am running below code and getting unable to resolve jj , Does if-let not consider else?
(if-let [jj (false? false)]
(println "as")
(println jj))
it should but right now I cannot check it. I see a message on the last line that jj is not known
it's only known in the true line:
(if-letΒ [jjΒ (true?Β false)]
Β Β (printlnΒ jj)
Β Β (printlnΒ "as"))
(defmacro if-let
"bindings => binding-form test
If test is true, evaluates then with binding-form bound to the value of
test, if not, yields else"
....)
so no, it doesnβt bind in the else clause.but whatβs the point of binding it? You already know the answer. Itβs falsy.
This is just a sample code, In production code I am assigning values
If you need the value afterwards then bind it in a let
and check the value in a regular if
.
yeah, I tried that first .. but wanted to reduce code so done for if-let
is there a comfortable way of inspecting interim values inside threading macros?
i mean something better than (->> 2 (#(doto % tap> )) (* 3))
we're going to add one in 1.11 :) tap->
:)
thanks! that was fast! π
Cool! I normally just write a little debug function.
(defn debug [x](prn x) x)
(->> foo
(debug)
(bar))
you can vote for it here https://ask.clojure.org/index.php/8749/can-we-have-a-variant-of-tap-that-yields-the-passed-value
hmm,
Why is the healing-potion not updated right
(def warrior (ref {:hitpoint 15}))
(def healer (ref {:healing-potion 50}))
(defn heal [warrior healer]
(dosync
(alter warrior update-in [:hitpoint] (partial + 25))
(alter healer update-in [:healing-potion] (partial - 25))
(get-in [:hitpoint] @warrior))
(get-in [:healing-potion] @healer)
(println warrior)
(println healer))
(heal warrior healer)
outcome :
#ref[{:status :ready, :val {:hitpoint 40}} 0x14060ef1]
#ref[{:status :ready, :val {:healing-potion -25}} 0x2953a377]
nil
are you doing (- 25 50), so 25 - 50 = -25? when you want (- 50 25) 50-25 = 25?
maybe ?
so if you chang ethe (partial - 25)
to (partial - 13)
you will get result of -37
(partial - 25)
is returning another function, which the 50
is passed to, so its doing (- 25 50)
, I think.
Instead of using partial
, you might want something like (fn [cur] (- cur 25))
, or an abbreviated form that Clojure allows for functions: #(- % 25)
It doesnt matter for + as 5+6 = 6+5, but 5-6!=6-5
@andy.fingerhut does not make a difference
#ref[{:status :ready, :val {:hitpoint 40}} 0x278238d9]
#ref[{:status :ready, :val {:healing-potion -25}} 0x40bd1764]
nil
code :
(def warrior (ref {:hitpoint 15}))
(def healer (ref {:healing-potion 50}))
(defn heal [warrior healer]
(dosync
(alter warrior update-in [:hitpoint] (partial + 25))
(alter healer update-in [:healing-potion] #(- % 25)))
(get-in [:hitpoint] @warrior))
(get-in [:healing-potion] @healer)
(println @warrior)
(println @healer)
(heal warrior healer)
@andy.fingerhut solution works for me.
(defn heal [warrior healer]
(dosync
(alter warrior update-in [:hitpoint] (partial + 25))
(alter healer update-in [:healing-potion] #(- % 25))
(get-in [:hitpoint] @warrior))
(get-in [:healing-potion] @healer)
(println warrior)
(println healer))
=> #'stuartstein777.aoc/heal
(def warrior (ref {:hitpoint 15}))
=> #'stuartstein777.aoc/warrior
(def healer (ref {:healing-potion 50}))
=> #'stuartstein777.aoc/healer
(heal warrior healer)
#object[clojure.lang.Ref 0xce48ab9 {:status :ready, :val {:hitpoint 40}}]
#object[clojure.lang.Ref 0x641e467b {:status :ready, :val {:healing-potion 25}}]
Did you resend the function to the repl after changing it?
yep
maybe a parentheses wrong
Now it works
second question
how I can I now print the warrior and the healer instead of refs
For most kind of "mutable containers" in Clojure, including refs, atoms, and agents, you can use (deref x)
to get the value "inside".
deref it? (println (deref warrior))
The syntax @x
is a shorthand for (deref x)
yep, found that out
last part of the puzzle . healing points cannot be more then 40
and the potion cannot be less then zero
Inside of the dosync
, you can have conditional code like if
or cond
that checks whatever conditions you want, before it makes any calls to alter
maybe use let-if
??
do you mean that even though healing potion is 50, you only want to use 40 of those points?
Minor comment: In your code pasted above, the expression (get-in [:hitpoint] @warrior)
does get the new value from the warrior
ref, and I am pretty sure that value is returned from the dosync
expression, but there is nothing that can ever "see" or receive that return value, so it is redundant and unnecessary. The same applies to the following expression (get-in [:healing-potion] @healer)
The code will do the same thing, slightly faster, if those two expressions are removed from the function heal
I mention it not so much because of the performance issue, but for learning purposes it is good to know that such expressions are almost always useless - they are pure functions of their input with no side effects, and their return value is ignored.
also, the arguments appear to be backwards
Doh! I should have noticed that, too. I guess it is a good thing those expressions are redundant, then π
hmm, why here a nullpointer exception
(defn hitpoint-validator[{:keys [hitpoint]}]
(and (<= hitpoint 40)))
(defn potion-validator [{:keys [potion]}]
(and (>= potion 0)))
(def warrior (ref {:hitpoint 15}
:validator hitpoint-validator))
(def healer (ref {:healing-potion 50}
:validator potion-validator))
I get that when ttrying the healer
potion versus healing-potion
You're destructuring a different key in potion-validator
to what you have in healer
, :healing-potion
vs potion
thanks, it works
the only thing I do not like is that it chrashes on a illigal state
(defn hitpoint-validator [{:keys [hitpoint]}]
(<= hitpoint 40))
(defn potion-validator [{:keys [healing-potion]}]
(>= healing-potion 0))
(def warrior (ref {:hitpoint 15}
:validator hitpoint-validator))
(def healer (ref {:healing-potion 50}
:validator potion-validator))
(defn heal [warrior healer]
(dosync
(alter warrior update-in [:hitpoint] (partial + 25))
(alter healer update-in [:healing-potion] #(- % 25)))
(get-in [:hitpoint] @warrior))
(get-in [:healing-potion] @healer)
(println "warrior:" @warrior)
(println "healer: " @healer)
(heal warrior healer)
thanks, that was it
I'm trying to parse a json using clojure.data.json but it wasn't in my project dependencies when I started the repl
there is no way to include it on the fly?
i'm currently using leiningen and calva
I thought you can do this : `
(require '[clojure.data.json :as json])
@antbbnin the repl
I would like to understand destructing in clojure, Anyone bookmarked helpful website?
you need to restart the repl after adding it to your project dependencies
(there are ways to accomplish this but they depend on tooling and are beyond the scope of #beginners imo)
There is a good guide here: https://clojure.org/guides/destructuring
got-it
Thanks π
i still get this
=> clojure.data.json
Syntax error (ClassNotFoundException) compiling at (form-init18181492875778679100.clj:1:1629).
clojure.data.json
i put these in my :dependencies
:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/data.json "1.0.0"]]
clojure.data.json is the name of a namespace, it is not a name bound to a value, so it has no value evaluated at the repl
have you looked at https://github.com/clojure/data.json#usage ?
you're right, i also tired this
=> (clojure.data.json/read-str "{}")
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:471).
clojure.data.json
did you try the first example code block in the usage section?
oh yeah :man-facepalming: i did not require it
thanks for insisting π
(ns brave-book.chapter11
(:require [clojure.core.async
:as a
:refer [>! <! >!! <!! go chan buffer close! thread
alts! alts!! timeout]]))
error:
:as - failed: #{:only} at: [:only :op :quoted-spec :spec]
:as - failed: #{:rename} at: [:rename :op :quoted-spec :spec]
(quote :as) - failed: #{:exclude} at: [:exclude :op :spec]
(quote :as) - failed: #{:only} at: [:only :op :spec]
(quote :as) - failed: #{:rename} at: [:rename :op :spec]
works for me
/tmp β―β―β― clj -A:async
Clojure 1.10.1
(ns brave-book.chapter11
(:require [clojure.core.async
:as a
:refer [>! <! >!! <!! go chan buffer close! thread
alts! alts!! timeout]]))
nil
brave-book.chapter11=>
very wierd
with a ;lein project I do not seem to work
or there is somewhere else a problem
(ns brave-book.chapter11
(:require [clojure.core.async
:as a
:refer [>! <! >!! <!! go chan buffer close! thread
alts! alts!! timeout]]))
(defn hot-dog-machine
[]
(let [in (chan)
out (chan)]
(go (<! in)
(>! out "hot dog"))
[in out]))
(let [[in out] (hot-dog-machine)]
(>!! in "pocket lint")
(<!! out))
nope, only with the ns I see that problem
you should check the version of core.async you are using
/t/foobar β―β―β― lein repl
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
nREPL server started on port 51406 on host 127.0.0.1 - <nrepl://127.0.0.1:51406>
REPL-y 0.4.4, nREPL 0.7.0
Clojure 1.10.1
OpenJDK 64-Bit Server VM 13.0.2+8
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
foobar.core=> (ns brave-book.chapter11
#_=> (:require [clojure.core.async
#_=> :as a
#_=> :refer [>! <! >!! <!! go chan buffer close! thread
#_=> alts! alts!! timeout]]))
nil
brave-book.chapter11=>
and you haven't reported the full error
i suspect the file isn't saved and you are evaluating something else
just part of the spec failure
I have save it and the brave book uses these versions :
:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/core.async "0.1.346.0-17112a-alpha"]]
oke, with a newer version it seems to work
newer versions of clojure are stricter about what they accept in ns forms, and some older versions of core.async have wonky ns forms
the full error instead of just the excerpt would have had some indication of which ns form was causing the problem, which likely would have shown it to be something in the core.async library, not in your code
oke, I thought I had paste the full error
Hello, I am doing the Learn Reitit Course and working with next.jdbc
, after connecting my DB with heroku, when I am trying to run my first sql command I get this error
The jdbc/execute part
Here is the user.clj
file, I will provide more if needed
(ns user
(:require [integrant.repl :as ig-repl]
[integrant.core :as ig]
[integrant.repl.state :as state]
[cheffy.server]
[next.jdbc :as jdbc]))
(ig-repl/set-prep!
(fn [] (-> "resources/config.edn" slurp ig/read-string)))
(def go ig-repl/go)
(def halt ig-repl/halt)
(def reset ig-repl/reset)
(def reset-all ig-repl/reset-all)
(def app (-> state/system :cheffy/app))
(def db (-> state/system :db/postgres))
(comment
(app {:request-method :get
:uri "/swagger.json"})
(jdbc/execute! db ["SELECT * FROM recipe"])
(go)
(halt)
(reset))
Nevermind, I fixed it. But Donβt ask me how xD
@ovidiu.stoica1094 Looks like you may have evaluated that code before db
was initialized.
is there a way I do not have to explicit return nil :
(defn distance [strand1 strand2]
(if (= (count strand1) (count strand2))
(->> (map vector strand1 strand2)
(map (partial reduce not=))
(filter true?)
(count))
nil))
@roelof simply remove the else clause
by default (if p x) returns nill if p is not satisfied
Or use when
oke, but then I see a message that the else is missing
@hiredman that seems to work Thanks
That message isn't from clojure, that message is from some extra tool you are using
A linter or something
Yes @hiredman is correct.
I'd prefer if over when in this case because you aren't performing sequential logic and don't need to evaluate the body in an implicit do block.
if vs. when was the one topic that caused the last dev team I was on to errupt into flames
odd hill to die on
@hiredman what was the conclusion?
There are takes on this topic, and debates that go back to common lisp
There was no conclusion, only conflict
Interesting, I have never heard of this debate before...
I think it is interesting to hear the debate at most once π
Is the debate on the other side an argument that the implicit do block avoids accidental else clauses?
the version i've heard is that when
is only for side effects. and otherwise use if
even if it only has a single branch. I don't understand the logic of it
I believe one side of the debate argues that when
does (or should) imply that the expression is there for side effects, but if
does not imply that.
That seems to be my reasoning as welll...
Nothing in the language behavior itself requires or implies either side of the debate, that I know of. It is a matter of style that some developers feel very strongly about. Not miles away from a tabs vs. spaces debate.
But by that logic, fn forms should only be used for side effects, and cond forms should never have side effects
The when implies side effects camp originates, I believe in common lisp, where an influential comp.lang.lisp poster took that position a long time ago
to end this debate once and for all we should just have a when!
macro for side-effects
I am trying to remember the guys name to see if I can dig up the post
but it will have a 1/1000 chance of not executing body even when the test is true
within the macro, you can suffix every symbol with !
to signal side-effects and it will automatically work
I seem to recall technomancy being a very fierce advocate of if
instead of when
?
I think his last name started with an N
erik naggum?
That must be it
oh boy
No, no. Don't end the debate. Simply try to find a way that it wastes more times for your competitors/opponents than it does for you π
that'd be when?!?
lol
technomancy was a member of the team I mentioned
I seem to recall quite a heated discussion on IRC around that time (2012) π
To me "when" for side effect ONLY seem to not make any sense in a language that doesn't have void returns
I think rich at some point posted something to the Google group saying when is idiomatic for single branch conditionals, but some felt he was wrong or that his wording was ambiguous in someway (could have been, I don't really recall)
An annoying this is googling if and when is basically impossible
oops, sorry for my question
The debate was there before your question, and will remain after your question π
o, I thought this discussion was about if versus when and I started a question how to do things better without explicit return nil
I don't remember if Rich has said that or not, but I've said it and that's my opinion
The debate is over 20 years old, I think.
starting before Clojure existed.
but you know, whatever
oke
looks I started it again with my question
This is a mild reasonable one, though π
oke
Not sure to follow you guys. At the end both forms are executing properly ? So its only a style issue. Am I right ? The 1/ 1000 sentence of @dpsutton and other comments make me doubting
yes, it is a style issue
sorry. the 1/1000 randomness was just a joke π
No pb, my not so good english and clojure doubts are sometime an awful mix
I'll bite! I feel like you can't enforce semantics through conventions. So having when only for side effect is a "good intention", but in practice, it's not an enforceable semantic. So realistically you can't rely on it to guarantee you anything. Thus it seems futile to assume when is only for side effect, and a lost cause to nag everyone who "mistakenly" uses when for returning a useful nil instead of only for side effects.
well i'm glad you asked. doubt anyone ever minds being asked for clarification.
That means, even before debating the "usefulness and merits" of a construct that would "execute a side-effect if condition is true", I can assert that trying to make when
behave with those semantics by pure convention is an exercise in futility.
I always wondered what he would think about situations where you have "if some-condition then execute-side-effects else execute-other-side-effects"? Would he insist on "when some-condition execute-side-effects; when not some-condition execute-other-side-effects"?
when
just isn't that construct, when
returns the last result of expressions if cond, else nil. That's what it is, seems hopeless to pretend its something else by using it exclusively for a subset of what it can be used for. And I can see people trying to do that actually getting burned out trying, cause "Good Intentions" don't work to enforce things. They can reduce the occurrence of it, but never prevent it. So if you're not okay with anything but a full guarantee, you got to find a different approach. For example, you could make a new construct that always returns nil, but if cond it also runs some side-effect. Such a construct could only be used for side-effect (or as a sub for nil I guess). If you even wanted to prevent someone using it as a sub for nil, you could have it return an exception maybe, or a thing that when deref throws an execption: Not allowed to use return of ...., ..... is only to be used for side-effects. Something like that.
(although maybe he's really only railing against (when some-condition some-return-value)
and preferring (if some-condition some-return-value nil)
except with an implicit nil
? I find it a hard position to justify)
That's what I thought the idea was. I'm not sure if its when
only for side effect, and if
only for pure logic, or only the former.
I think the idea was that at a glance, if you see when
, you know some side effect is happening in that piece of code. (and if you use when for pure behavior, that messes up with this "at a glance" reading)
So in order to be able to trust your "at a glance" reading of the code, you need people to only use when
for side effects. Which, like I said, I think is an exercise in futility π
(defmacro maybe-do
[condition & forms]
`(do (when ~condition ~@forms)
(delay (throw (ex-info "Can't read from void return!" {:type :void-return-error})))))
Something like this would be better. Now I don't know if I'm convinced in how useful it is to use this to indicate "hey I'm doing side effect here, nothing else!!", but at least you can be sure that when someone uses that, its only doing side effect.Hiredman said that he thought Rick said: > when is idiomatic for single branch conditionals So I assume this is what Alex is referring too. So it be that when your condition has a single branch, use when, otherwise use if or cond.
Ah, that "it", not the other "it" π
(just that a lot of the earlier discussion focused on Phil Hagelberg's position which is the opposite of that)
I think the more common use in Clojure is:
* When you have 1 branch use when
* When you have 2 branch use if
* When you have 3 or more branch use cond
* When you want to choose between "one of many value" use case
* If you need to do more than one thing per branch wrap it in a do
unless you're using when
, then you don't have to cause when
is unambiguous so do
would be redundant.
* Side effect or not, it doesn't matter
correct - when
for single branch conditionals is my preference
Thank you! I checked the (community) Clojure Style Guide and it doesn't seem to have an opinion on this particular issue. Which surprised me a bit.