This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-18
Channels
- # announcements (17)
- # babashka (109)
- # beginners (212)
- # calva (1)
- # chlorine-clover (7)
- # cider (8)
- # clj-kondo (31)
- # cljsrn (2)
- # clojure (33)
- # clojure-dusseldorf (1)
- # clojure-finland (2)
- # clojure-france (22)
- # clojure-germany (1)
- # clojure-losangeles (1)
- # clojure-spec (6)
- # clojure-uk (19)
- # clojurescript (31)
- # conjure (41)
- # cryogen (1)
- # data-science (11)
- # datomic (6)
- # emacs (5)
- # exercism (8)
- # figwheel-main (2)
- # fulcro (57)
- # graalvm (15)
- # hoplon (15)
- # jobs-discuss (32)
- # kaocha (7)
- # off-topic (14)
- # pathom (2)
- # planck (9)
- # quil (1)
- # rum (5)
- # shadow-cljs (34)
- # spacemacs (33)
- # tools-deps (1)
- # xtdb (9)
I would recommend asking in the #data-science channel, as there might be a larger audience of people interested in that kind of thing in that channel.
Is anyone else constantly greeted with the error: Can't have 2 overloads with same arity
in code such as the following?
(defn call-with-rte "docstring"
([[] thunk] (thunk))
([[odd-man-out] thunk]
(throw (ex-info (format "odd number of values given as first argument of call-with-rte: %s"
odd-man-out)
{:type :invalid-call-to-call-with-rte})))
([[key value & others] thunk]
(let [*rte-known* (assoc *rte-known* key value )]
(call-with-rte others thunk))))
both of your argspecs here match odd number of values, so there's no way for clojure to differentiate between them
so built-in pattern matching doesn't do what you are trying to do anyway; if you need more, there's a chance that https://github.com/clojure/core.match/wiki/Overview can help
what is iirc ?
what is a comment thread? and how can I start one?
This place where we talking now is comment thread. it's not, as you can see, in the main channel
and How can I start one of these?
Oh come on 🙂 watch some tutorial on how to use slack? I don't even know what client you use. In web interface, it's in the popup icon bar when you mouseover some message
@U010VP3UY9X Instead of one function with multiple arities, you can also look up defmutli
and defmethod
.
core.match
, as suggested above, can also be a good solution. But that's an extra dependency.
There are some examples here: http://clojuredocs.org/clojure.core/defmulti
@UJRDALZA5, is defmulti
really a good solution, it sounds like a big hammer just to avoid one 3-clause cond.
well, in this particular example the matching thing is really only used to catch incorrect usage; I'd argue that spec
should be used for that instead
Regarding starting a thread, post one comment. Click on that posted comment, you should see option for starting a thread.
The problem with destructuring is, you can destructure extra values, and the non-matched value all become nil
. To Clojure, all overloads have arity 2.
with assert, I don't think I can control the exception which is created. right?
@hindon, yes I see, in my destructuring cases I'm implying an order.
@UTQEPUEH4, that's more or less what my cond-based solution does. Right?
This forces me to parse my own function arguments, which is not pretty:
(defn call-with-rte "docstring"
[bindings thunk]
(cond
(empty? bindings)
(thunk)
(empty? (rest bindings))
(throw (ex-info (format "odd number of values given as first argument of call-with-rte: %s"
(first bindings))
{:type :invalid-call-to-call-with-rte}))
:else
(let [[key value & others] bindings
*rte-known* (assoc *rte-known* key value)]
(call-with-rte others thunk))))
The exception will say data does not conform to spec. And you get a nice explanation which part of the data is out of shape.
I actually think that assert
's or spec exceptions are the right ones, and creating custom exceptions for that is counter-productive
I could simply use (apply assoc *rte-keys* bindings)
to give me the same semantics, except that the error on odd-number-of-arguments would be triggered in the call to assoc, rather than int he call to call-with-rte
The other curious thing about the code is that the dynamic rebinding doesn't seem to work.
why doesn't the let
rebind the dynamic variable?
also, the whole let / call thing is meaningless, of course; your thunk will not see let bindings
because let
creates new lexical bindings, if you want to call your thunk
with re-bound dynamics, you need binding
yes, i've discovered that. why not? How can I rebind a dynamic variable?
and if you have binding
, you just don't need your call-with-rte
at all ('cause it doesn't do anything except calling binding
anyway, afaics
ok, thanks. I saw the docs for binding
but it does not mention dynamic bindings. in CL we use (let ...)
for both and the compiler figures out which variables are dynamic and which are special.
@UTQEPUEH4, the recursive call is important as each call simply consumes 2 of the bindings.
I don't get it. why not just, I don't know, (binding [*rte* (apply assoc *rte* your-args)] (your-thunk))
?
why not actually require a map of those rte
s (whatever they are)? as in (defn call-with-rte [thunk rtes] (binding [*rte-known* (merge *rte-known* rtes)] (thunk)))
?
my original goal for avoiding multi-arg call to assoc, is because if an odd number of args are passed, then the user gets a confusing error about a call to assoc, rather than about a call to call-with-rte
about using a map directly, it's because call-with-rte
is the workhorse function of the macro with-rte
, and the syntax of with-rte
is like let
. You would not like to use let
if you had to give it a map, right?
to exploit assoc
is just too tempting. Here is what I ended up with.
(defn call-with-rte [bindings thunk]
(binding [*rte-known* (apply assoc *rte-known* bindings)]
(thunk)))
(defmacro with-rte [bindings & body]
`(call-with-rte '~bindings (fn [] ~@body)))
minus the docstrings
ah, no?
I prefer having a macro API and also a functional API for several reasons. it is easier to implement and test the functional API.
This forces me to parse my own function arguments, which is not pretty:
(defn call-with-rte "docstring"
[bindings thunk]
(cond
(empty? bindings)
(thunk)
(empty? (rest bindings))
(throw (ex-info (format "odd number of values given as first argument of call-with-rte: %s"
(first bindings))
{:type :invalid-call-to-call-with-rte}))
:else
(let [[key value & others] bindings
*rte-known* (assoc *rte-known* key value)]
(call-with-rte others thunk))))
is let
capable of binding dynamic variables in clojure? Or do I need some other special form for that?
or does let
only bind lexical variables?
It looks to me like the following behaves quite differently than I expect. If I have a dynamic variable named *foo*
then the following still apparently sees the global value, not the rebound value.
(defn bar [x]
(cond something *foo* ;; still old global value, doesn't see new *foo* binding
something-else (let [*foo* new-value] (bar (dec x)))))
I haven't tested for certain, but I believe let
is only for lexical bindings. If you want dynamic bindings, there is the similar-syntax binding
How can I make the recursive call see the new dynamic binding?
some errors are really hard to debug, what does Uncaught TypeError: Cannot read property 'cljs$core$IFn$_invoke$arity$1' of null
mean? In the line it says it is by source-map, it seems not to be a null
I can't even do hot-reload because it's inside react and react complains that it's an unmounted component, have to do manual refresh, despite using figwheel and everything
Seems like it might be you try to call something as a function, but that thing is nil
yeah, some props are not there, would be nice to know how to write specs for props so that I catch if one is nil
Hum, ya I don't know. Unfortunately don't have a lot of experience with react and surrounding libs
What are the semantics of memoize
with regard to recompilation?
(def f (memoize g))
When I re-evaluate this definition, has the old cache been removed/forgotten?matplotlib
equivalent in clj? vega/oz
would be enough? is there something else I should look on? I see some cluttered reddit threads but not much more, ty
I can get the ancestors of a class with ancestors
: (ancestors Long)
returns a set of classes, one of which is java.lang.Number
. However (descendants java.lang.number)
raises an exception.
Execution error (UnsupportedOperationException) at clojure-rte.core/eval18520 (form-init10469598600043035746.clj:682).
Can't get descendants of classes
Is there a way to find these descendants?There is no way to ask that question in Java
Without doing static analysis of “all” classes
Which is what ides like Cursive do
Cursive, the IDE?
perhaps there's a way to answer an easier questions. Given two classes, are they disjoint? I was planning to answer the question by finding whether they have a common descendant. my idea doesn't work.
I don't actually need to know what the common descendent is, just whether there is one.
If you’re talking concrete classes, then you only need to know whether one is an ancestor of the other
If interfaces, then what’s to stop someone from introducing a new interface at any point that implements both?
the question of whether a new class or introduced later doesn't bother me.
but no, I don't know they are both concrete classes. they may be abstract classes.
can I know from clojure whether a class is abstract or not? maybe that could be a workaround. If they are abstract (or interfaces) assume they might intersect, but if they are concrete, determine whether they are disjoint by looking at ancestors
Out of curiosity, why do you want to know if two classes A and B are disjoint? (I guess by that you mean that an object cannot be an instance of a subclass of both A and B?)
exactly. given an expression such as (and Integer String)
we know this is an empty type. We know this because Integer
and String
are disjoint. And we for the same reason we know that (and (not Integer) String)
is inhabited.
Integer and String are also final so they can’t be extended
How can I know whether a given class is final?
Should be one of the attributes/flags you see on a class using the Java reflection API.
is there some sort of show-me-the-attributes function in clojure?
The Java method is getModifiers, documented here: https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getModifiers--
There is a Clojure wrapper around that (or similar JVM calls) that gets you a Clojure data structure with the same data in it. Looking that up ...
Try this in a REPL:
(require '[clojure.reflect :as refl])
(print (refl/type-reflect java.lang.Integer))
there is a cider-inspect
function, but it doesn't seem to do anything useful.
I have no knowledge of Cider with which to suggest anything there.
interesting (refl/type-reflect java.lang.Integer)
returns a data structure with a key :flags
whose value is #{:public :final}
Is a clojure program free to require clojure.reflect ? or will that fail to work in some environments?
Question. given two classes, one of which is final and one not, then may I suppose they are disjoint whenever the non-final one does not have the other in its ancestors?
Java does not have multiple inheritance for classes
So yes. Similarly, (and (not (instance? (type a) b)) (not (instance? (type b) a)))
instance?
would be the idiomatic operator here
Bill, you are supposing I have an object of the type, right? or am I missing something?
I'm trying to do a predictive computation without having an instance. i.e., which will for for any instances of the two types.
ahh, you are correct. although I think Java’s Class
has a method to make the check you’re doing by scanning ancestors
@U010GL90FN0 l two classes are disjoint if they have no common inhabited descendent. And as the previous discussion lead me to know, in java you cannot ask for descendants of a class 😞
The work-around is that in the case of a final class, we know there are no descendants. thus we just need to check whether one is a supertype of the other, via ancestor check.
but remember: there’s no multiple inheritance
so if two classes are not ancestors of one another, they cannot have a common descendant
https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#isAssignableFrom-java.lang.Class- is the method i’m thinking of
if neither is assignable from the other, they are disjoint, and so are any subclasses
cool. I saw that function in the code for isa?
ahh, that looks like the tool you want. much easier
I don't understand the logic. Should I just take your word for it? Or should I try to convince myself that you are right?
if you like. you seem like someone who prefers to know things for sure. the key thing to know is that, for a given class A, it will have exactly one superclass. Object
is the root class
How can I call isAssignableFrom
? The isa?
code uses a syntax I don't understand. (. ^Class parent isAssignableFrom child)
OK, here is an example. java.lang.constant.Constable
and
both have no ancestors, but they are superclasses of both Integer
and also String
. The computation should determine that they are NOT disjoint.
it looks like isa?
works on class instances
Unfortunately, your specific example is not answerable
how so?
what does the isAssignableFrom
approach do in the case of Constable and Serializable ?
isa?
looks like a nice bit of sugar on top of isAssignableFrom
. So they will accomplish the same thing here
Let’s take (disjoint?
as an example
Box
is my class, I defined it
it doesn’t implement Serializable
Serializable
is an interface, though. Any subclass of Box
can implement it if they want
is Box final? I guess it isn't.
OK, so I understand how to compute disjoint-ness in the case one of the classes is final. The remaining question is what is the best I can do when they both fail to be final.
well, let’s choose something besides Serializable
if we choose something that is a class, not an interface, the question is easy to answer
Comparable ?
classes aren’t interfaces. they’re two distinct concepts in Java
if you want to refer to both, “type” would be the right word I think
it looks like the (refl/type-reflect java.lang.Comparable)
tells me whether the given class is an interface. thats good.
classes aren’t interfaces
no class is an interface
ok there are three cases, :final, :interface, and other.
so there are 6 cases for disjoint?
` right? some of which are answerable and some not.
So what can I know if one of the two classes is not an interface and also not final ?
i think there are only four cases: :interface :interface :interface :class :interface :final-class :class :class
btw, (type java.lang.Comparable)
returns java.lang.Class
so programmatically speaking it is a class.
(type Integer)
returns the same thing, as does (type Object)
so from the clojure perspective, they are all classes, even if at the java level they are not.
sure. but that is a detail of the reflection. in Java code, these things are declared by writing either public class MyClass { ... }
or public interface MyInterface { ... }
. Extending a class is done with extends
, extending an interface is done with implements
.
if you abide by this distinction, i can promise you that it will pay dividends in your communications with all who are fluent in Java.
and this is also why clojure’s decision to name the function to get an instance of Class
type
rather than class
was a good one. 🙂
(now that I think about it)
so there are three cases for a
and three cases for b
, :final, :interface, :else. That is 9 cases. if either is :final, we can use isa?. that leaves 4 cases. (other, interface), (other, other), (interface, interface), (interface other)
I think for (other,other) I can use isa? because of the promise of single inheritance. nothing can inherit from both unless one is already a subclass of the other.
anyway, to get back to the four categories:
* :interface :interface - These are never disjoint. Nothing prevents someone from creating a new class at runtime that implements both interfaces.
* :interface :class - Same as above. Nothing prevents someone from creating a new subclass that implements the interface.
:interface :final-class — Disjoint if (isa? interface final-class)
(edit: I mean (not (isa? interface final-class))
:class :class — Disjoint if (not (or (isa? a b) (isa? b a))
That leaves 3 (other,interface),(interface,other), and(interface,interface)
And if the right hand is an interface and the left hand is a class, swap them
I think it makes sense. I'll try to code it up tomorrow, and see what happens. its almost 20h00 now. time to quit for the day.
@U010GL90FN0 thanks for the insight. I'll site (blame) you in the comments of my function, and everyone will send you email if it breaks (grins).
how should I cite you?
hope i was of some help! i have NEVER explained Java’s notion of classes to someone who was introduced to OO elsewhere, or through clojure’s reflection first, so this is interesting. 🙂
Bill Phillips is fine. @jingibus on github
Java's concept of type of class is bizare to someone coming from lisp.
It is very, very restricted, by design. Classes are very concrete and inflexible. But it is helpful to understand them, because every instance in Java is built on that foundation
for me a type is a set of values. the type might or might not have a name, and might or might not be specifyable.
OK. gotta go. thanks again for the help.
made a mistake above, see edit
I have discovered 4 kinds of class flag sets. I don't understand the difference, as I don't know java. Maybe these make sense to a Java programmer???
clojure-rte.core> (:flags (refl/type-reflect String))
#{:public :final}
clojure-rte.core> (:flags (refl/type-reflect Object))
#{:public}
clojure-rte.core> (:flags (refl/type-reflect Number))
#{:public :abstract}
clojure-rte.core> (:flags (refl/type-reflect java.lang.CharSequence ))
#{:interface :public :abstract}
clojure-rte.core>
what is a public class which is neither abstract not final ?
are all interfaces also abstract?
Also two very different classes Object
and clojure.lang.PersistentList
are both marked as :public
but neither :final
nor :abstract
what does it mean to be non-abstract? and non-interface? does that mean it is possible to instantiate it?
I've moved this discussion to https://clojureverse.org/t/determining-whether-classes-are-disjoint/5811
in terms of code optimization this means that if we have already checked that an object is an Integer
and discovered that it is then we know a subsequent check for whether it is a String
can be omitted as it is guaranteed to evaluate to false
.
Is your goal to use such knowledge for code optimization?
exactly.
I am not certain, as I have not delved deeply into this kind of thing before, but the JVM has some fairly dynamic features, and I think it may be possible to reload a class later after it has been loaded once before, and if so, the answers might be different for a later loaded version of the class.
That might be beyond what you are hoping to handle, if it is true.
semantically it of course does not hurt to check (instance? String x)
discover that it is true and thereafter also check (instance? Integer x)
, but a static analysis should be able to determine that the latter will be false
how can I call the next most applicable method in a multimethod?
the code for multifns isn’t too bad. as alex said, you could ask for method of choice (using https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/MultiFn.java#L144) and remove it. alternatively, you could copy the https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/MultiFn.java#L161 and change it to return the second best method
Yes, but that only solves the problem the first time. If that second method then wants to call call-next-method, then I'd want it to work as well. In CLOS any method may call call-next-method
and it will work, provided there is a next method. There is a function next-method-p
if the method wants to know whether there is such a next method.
i.e., the one that would have been called if the current method didn't exist
You could remove the one it found and call it again :)
removing it and calling again would only work the first time, but it wouldn't work when that method wants to call call-next-method. 😞
CLOS is beautiful for the programmer, but a horror for the compiler implementor.
so what's the pattern using clojure multimethods to allow a method to contribute to the return value, or for a method based on runtime logic to decide whether it can compute the result, or delegate to next less specific method?
But really, there is no easy way to do that
(defn AAAAAAAA [strx] (try (djson/read-str (:body (client/get str) {:body-encoding "UTF-8" :accept :json }}))) (catch Exception e (prn e)) )) This piece of code fetches some data; however the exact data might not be there so it fails. For some reason the error handling does not catch the error. (meaning the e value) I sometimes get an error crash dump and the error JSON is reflected on the crash dump - I can read it and it provides the 404 code I modelled this from the clojuredocs and it does not work -why not? I assume the catch line will not require a djson/read-str as it is a header dump - I cannot find anything that makes sense of this. Using clj-http
Putting aside the reason for the error not being caught for a moment, there are a couple of things I can see wrong with that code. Firstly, if it's clj-http you're using, that options map needs to be the second arg to client/get
. Secondly, the first arg to client/get
is str
- that's a clojure function. I assume what you meant to use is strx
instead.
you are perhaps right however the client/get is a redacted statement and as is it works and I get answers. However, when the dta is set to fail I should get a 404 and the catch does not work (this is the focus of the question)
It is a (try (client /get function) (catch e) fundamentally. Yet the catch does not trigger on the 404 error. Am I supposed to use something else to catch the 404?
clojure.lang.ExceptionInfo: clj-http: status 404 {:cached nil, :request-time 1036, :repeatable? false, :protocol-version {:name "HTTP", :major 1, :minor 1}, :streaming? true, :http-client #object[org.apache.http.impl.client.InternalHttpClient 0x61213e02 "org.apache.http.impl.client.InternalHttpClient@61213e02"], :chunked? false, :type :clj-http.client/unexceptional-status, :reason-phrase "Not Found", :headers {"access-control-max-age" "3628800", "access-control-allow-headers" "origin,x-requested-with,accept,content-type,xxxxxx-api-key", "Content-Type" "application/problem+json", "access-control-allow-origin" "*", "Content-Length" "97", "Connection" "close", "access-control-allow-methods" "GET,OPTIONS", "Date" "Sat, 18 Apr 2020 20:26:42 GMT", "Content-Language" "en", "Correlation-Id" "2b10c2b7-8b61-4a60-9ee3-9f57f886c0fe"}, :orig-content-encoding nil, :status 404, :length 97, :body "{\"title\":\"No result found\",\"status\":404,........etc It seems that the e details not structured. If I want to chack the status (it being 404) am I to just parse the "string"?
I mean my objective is to manage 404 and other error sop the system can recover properly
As it's a ExceptionInfo
, ex-data
is your friend here. Use it to pull out that map of data from the ExceptionInfo
. Then you can interrogate that map using the usual clojure functions - e.g. you can read off the status code and handle it.
So you could then have a case
or cond
in your catch handler to deal with different status codes.
Another option is to change the clj-http
to not throw exceptions for non-success HTTP codes and then you don't have to deal with try
/`catch` and you just check the :status
field of the client/get
response.
:throw-exceptions false
Yes, that's certainly a simpler way of doing it and the one I'd use by default too. You then need to be careful that you're covering all "exceptional" status codes in your response handling code otherwise you could end up with some potentially cryptic errors.
Well after learning about it (I am not a Java prog) I have managed to extract the data. My catch code is now (catch clojure.lang.ExceptionInfo e (djson/read-str (str (:body (ex-data e))))))) It returns the map I want Thanks @UJF10JP8A and @U04V70XH6 Woking on the huge learning curve! 😁
I checked that ExceptionInfo
is a subclass of RuntimeException
which is a subclass of Exception
. Does anyone know why catching Exception
does not work?
Catching an ex-info
via Exception
works for me:
user=> (try
(throw (ex-info "test" {:a 1}))
(catch Exception e
(println "caught" (ex-message e) (ex-data e))))
caught test {:a 1}
nil
I mean my objective is to manage 404 and other error sop the system can recover properly
Hi! Does anyone know of any boards or w/e where people/beginners share sth they've recently written and more experienced people take a look at it for feedback or sth to that effect?
there’s the #code-reviews channel, but it’s usually slow. I haven’t tried it, but something like https://exercism.io/tracks/clojure may be of interest. you can ask in #exercism if you want a take from someone who actually has tried it
This is really great! Thanks @U7RJTCH6J