Clojure 1.10.1
user=> (identical? Double/NaN Double/NaN)
false
user=> (identical? ##NaN ##NaN)
true
@andy.fingerhut so you’re saying that something like:
(=
(+ (+ 1.111 1.111) 1.111)
(+ 1.111 (+ 1.111 1.111)))
=> true… might return false, depending on the numbers involved?
I want to reuse some variadic keywords args that are destructured in one function - i.e. a map m
- when calling another function f
that also takes variadic keywords args. Is the idiomatic way to do this then
(apply f (mapcat identity m))
? Applying the map directly doesn’t work, so I have to flatten it somehow which I do using (mapcat identity m)
.yeah, this is an annoying problem that might be addressed in clojure 1.11 but over the years the community has moved towards an options map instead of keyword opts (at least, in my perception)
Count me as one of the community in this matter. Variadic keyword arg destructuring seem stunted, as demonstrated here.
^
gotcha
(will be addressed in 1.11 and there may be multiple reasons this pendulum will swing the other way)
jokes on you, I use both at the same time already
https://github.com/vlaaad/remote-repl/blob/master/src/vlaaad/remote_repl.clj#L11-L13
My Clojure goes to 11
Are there a functions in clojure core that would behave like and
and or
but not a macro, a function and I don’t need the short circuit logic?
I find myself often in need of (map and seq1 seq2)
and or
version of such
every? identity
for example
or some identity
for or
#(and %1 %2)
for that case?
I didn't realize that and
and or
aren't provided as fns along side their macro form
clojure doesn't have separate namespaces for fns and macros, a var is either a fn or a macro
can't be both at the same time
for instance something like:
(every? (fn [[x y]] (< x y)) [1 2 3] [3 4 5])
(modulo definline
stuff, but let's pretend that doesn't exist)
so I tried doing (map < [1 2 3] [3 4 5])
but then there’s no elegant way to roll those booleans up
reduce #(and %1 %2)
or use (reduced ...)
for short-circuiting
yeh… that’s why I asked if there’s a function for that, I know I acan use anon function and call and
in it
but this is similar to (every? identity ...)
that's only done for optimizations though
yeah, cljs has a completely different compilation model than clj
@borkdude not really, userspace code can do this freely afaict
I mean, they are used for optimizations in cljs
The occurrence of macros and functions for the same var
https://blog.fikesfarm.com/posts/2015-12-12-clojurescript-macro-functions.html
the cljs impl uses this mechanism for optimisations, sure, but it's completely open
thanks borkdude, I’ll guess I’ll use every?… but this same thing came up many many many times in various code, where and
or or
would be perfect as an argument to coll processing function and then I have to go #(and %1 %2)
yes, I was speaking about clojurescript macro-functions specifically
maybe the word "only" wasn't appropriate, sorry
make a proposal in an ask.clojure issue :)
not going to add this
tbh it should be only done for optimisations and limited to core.
I'm not a fan of this working for user code at all
to my mind macros are used for performance and the functions are provided to allow the semantics that roklenarcic is talking about (passing it into apply/map/etc.)
but then, as I mentioned, clojure technically does have the same capability via the impl details of definline
no, that's completely wrong
macros are used for changing evaluation semantics
it's incidental that in some cases controlling the evaluation semantics can lead to better performance hints to the compiler
ok lol
In general yes, but e.g. the +
macro is added for optimizations, while it's also a fn. this is what I was referring to
I wasn't making a strong claim of "macros are ONLY used for performance"
yes but that could be done (and imo, should be!) as an intrinsic to the compiler instead of as a macro
clojure has similar optimisations baked into the compiler
¯\(ツ)/¯
cljs.user=> (macroexpand '(+ 1 2 3))
(js* "(~{} + ~{})" (cljs.core/+ 1 2) 3)
cljs.user=> (macroexpand '(apply + [1 2 3]))
(apply + [1 2 3])
yeah I'm aware of how it's done in the cljs impl :)
@lilactown no but it's wrong to say for example that " and
as a macro is used for performance and then a fcuntion for semantics"
ah so that is called an "intrinsic", now I get what those compiler people were talking about
this can only be true for a very limited subset of "functions" that have function semantics
and doesn't have function semantics
anyway, I've used this to effect in some libraries where I wanted to provided a macro - for some performance reasons - and also a function to allow function application and other more dynamic uses. I would be sad to lose that capability
in Clojure we don't have this capability and I've never used it in CLJS
eeeh we kinda do :) it's just not very known
(I went to some compiler-related conference last weekend)
you mean (definline ...)
? ok, never used it
user=> (defn foo {:inline (fn [x] (+ x 1))} [x] (- x 1))
#'user/foo
user=> (foo 2)
3
user=> (apply foo [2])
1
close your eyes and forget you ever saw this
ah that one, yes I knew it, but I usually roll a macro and just don't allow myself to use it as a fn when I want this ;)
@lilactown the capability is sound, other lisps have similar things -- I just don't think having this macro+fn hack is the way to do it, but whatever
ok
I don't really understand the what/why of some of the things you're saying. I am trying to participate in the discussion to explain my experience using macro+fn, and you tell me very bluntly that I'm "wrong"
I was just referring to this statement to my mind _macros_ are used for performance
ok
let me amend
to my mind macros _are used sometimes for performance_
ish :) but I don't want to nitpick
I feel like I have spent a lot of energy very quickly here on an argument that we never needed to have
I'm sorry you felt we were having an argument, not my intention
Macros are always a sensitive topic. ;)
Like lisp-1, lisp-2, and why Clojure is not a true lisp-1, etc ;P
I have a bit of a gripe with some unnecessary "extensions" to the evaluation model of cljs compared to clj, this is part of it
So what other "extensions" are there?
shoulda said changes rather than extensions but off the top of my head: type hints having different semantics (regardless of the absence of classes in js), clj/cljs namespace renaming, metadata evaluation being different, different arglists quoting, overuse of js*
as an escape hatch in the impl
things that matter more from a lang impl/analysis tooling PoV than end-user experiene anyway
I had an issue once with a macro that used try/catch with some code from cljs.spec (which is also macro-rich) but ran into the issue that the catch or finally clause was analyzed before the body of try
and this wasn't considered an issue, so I had to come up with an ugly workaround
ugh.
the issue was that cljs.spec macros do side effects during macro-expansion
so the side effects happened at the "wrong" time
lol, yeah, I wish we could have the invariant that macros aren't side-effectful
but alas
t.a.jvm has to take a non insignificant performance hit to handle this
it's comparable to the ns
macro, or def
special form, it has the side effect of defining something in the runtime before the rest is analyzed
yeah there's a bunch of macros in the wild that do that
whatever's the name of that testing framework, also does it in clj
I remember slipset suggesting an optimization for this related to eastwood, right?
yeah it's the ns-safe-macro
check
clojure.test?
nah the ugly one :)
non core
midje?
there it is
we don't speak its name
you said ugly, that rang a bell ;P
haha
honestly I have no experience with this framework, so I don't want to say anything bad of it, I've only heard some people (e.g. circleci blog) complain about it
@alexmiller I seem to recall CLJ-2590 came up many years ago and the sticking point was a Windows limit on the length of a fully qualified class name
I think this is a fairly trivial thing to achieve, but I'm kind of lost how to do this without any state atm
I have a bunch of maps which I group with group-by and then I need to map over the map and add an id from a lazy seq of ids to each of the maps in the respective groupings
however when I do this with (repeatedly (rand-int 1000))
and (take (count grouped-maps) ids)
I have the issue that all records get ids from the same starting point
I mean, I could of course modify the id sequence, but I'd like to know how to do this idiomatically
So somewhat like this:
(->> stuff
(group-by :some-key)
(map (fn [[k v]]
[k
(map (fn [[m id]]
(assoc m :id id))
v ids)])))
and?
not sure what the question is
It can be exactly almost like this if you replace [[m id]]
with just [m id]
. map
can accept any number of collections to map over.
Do you need to group before adding :id
? It's much easier if you group afterwards:
(def ids (iterate inc 1))
(def things [{:a 1 :b 2} {:a 1 :b 3} {:a 2 :b 4}])
(group-by :a (map (fn [id thing] (assoc thing :id id)) ids things))
What OIDC client library should I be using in a Clojure project?
also consider mapcat seq
or apply concat
in place of mapcat identity
Does anybody have link to a good example repo for JWT authentication using Buddy that they can share? https://github.com/funcool/buddy I'm trying to follow along with the example code here: https://github.com/funcool/buddy-auth/blob/master/examples/jws/src/authexample/web.clj Although it isn't quite complete enough to see the whole process (authenticate with username and password, generate token, pass token back to web client, authenticate protected routes using token)
Can you have in general a defrecord/deftype or reify that implements two different interfaces / protocols with clashing method names?
or can you uniquely identify the interface / protocol by the method name?
no
no to which question?
CLJ-2590 is the question and I think the answer was, If we 'fix' it by composing internal class names from symbols instead of numbers then the resulting increase in class name length will cause some code that currently works in Windows to not work any more.
I think it was discussed on the Google group.
the second one
IIRC the JVM doesn't take into account in the interface in the method definition
What I mean is: can you construct a reify with two method names from different interfaces?
two identical names? no
two identical yes
they'll be the same impl for both interfaces
(assuming the args & return type are all the same, too)
what if the arities are different (not sure if Clojure supports types in the signature of those?)
you could REPL it
yeah, trying it
So I've got this:
user=> (definterface Foo (foo [_]))
user.Foo
user=> (definterface Bar (foo [_ _]))
user.Bar
user=> (def x (reify Foo (foo [_ _] :foo) Bar (foo [_ _ _] :bar)))
#'user/x
user=> (definterface One (foo [x]))
user.One
user=> (definterface Two (foo [x y]))
user.Two
user=> (def r (reify One (foo [_ x] :one) Two (foo [_ x y] :two)))
#'user/r
user=> (.foo r 42)
:one
user=> (.foo r 42 42)
:two
lol, are we twins? 🙂
user=> (.foo x 1)
:foo
user=> (.foo x 1 2)
:bar
Ok, that answers my question, thanks!Why JWT in particular - can't regular session IDs be used?
I've got to authenticate across multiple domains, and as I understand it JWT is the way to go when that's the case.
You mean, like SSO? So you login to example1 and you would be automatically logged into example2?
JWT might be needed when you have a stateless backend or a distributed backend where it's unfeasible to share the state between all the instances. In all (or perhaps almost all) other situations regular session IDs are not only sufficient but also better. They're as simple as it can get and yet can provide all the security you will need.
Here's a nice article on JWT: http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/