This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-10
Channels
- # announcements (1)
- # babashka (44)
- # beginners (188)
- # calva (37)
- # chlorine-clover (28)
- # cider (12)
- # clj-kondo (40)
- # clojars (1)
- # clojure (323)
- # clojure-austin (7)
- # clojure-europe (20)
- # clojure-italy (4)
- # clojure-nl (16)
- # clojure-spec (7)
- # clojure-uk (37)
- # clojuredesign-podcast (1)
- # clojurescript (30)
- # cryogen (2)
- # cursive (30)
- # data-science (1)
- # datomic (26)
- # emacs (1)
- # events (1)
- # figwheel-main (13)
- # fulcro (89)
- # garden (1)
- # graalvm (20)
- # graphql (8)
- # jobs (1)
- # jobs-discuss (1)
- # joker (6)
- # kaocha (125)
- # lambdaisland (1)
- # meander (42)
- # off-topic (18)
- # pathom (3)
- # pedestal (6)
- # shadow-cljs (55)
- # spacemacs (21)
- # sql (18)
- # tools-deps (8)
- # uncomplicate (2)
- # vim (1)
- # yada (3)
Hello, may I have your opinions on my solution for accessing tabular data by indices?
I'm representing the tables as multi-dimension arrays
*Vectors
They're created once and only accessed then
They have various dimensions
`(defmacro lookup [table & idx]` `(conj (for [i idx] `(nth ~(dec i))) `~table '->))`
I've managed to get it to work, just wonder if it's become some aberration. How would you do this?
@UTQEPUEH4 if I understand your comment, you're also implying that vectors should be used, so that direct indexing can be used. Right?
the vectors already are used, and yes, i'm saying that there already is a built-in function doing more or less the same
get-in
sounds great. I figure I can just map dec on my indexes and apply get-in
@UTQEPUEH4 I somehow ended with a macro after trying to write every lookup manually using threading macros
I realized I was doing repetitive tasks and decided to just turn the basic structure into a macro.
Any thoughts on using nested vectors for index acessing? I've got like 20 tables, some 100 items each
Am I missing some trivial manner to transform this macro into a function?
well, your macro isn't very trivial to begin with (macros usually aren't), and get-in
is basically (`reduce nth table idxs)`
Something like (reduce nth table (map dec idx))
should do
Thank you for your suggestions
There were obviously better solutions I just wasn't seeing
Instead of (map dec idx)
, did you consider adding a dummy element at the beginning to each vector in your table?
You don't need a macro for that, can just do:
(defn lookup [table & idx]
(get-in table (mapv dec idx)))
If its just that you want a get-in that is var-arg instead of taking a vector, you can just do:
(defn lookup [table & idx]
(get-in table idx))
Otherwise like other have said, get-in already does that:
(get-in [[1 2 3] [4 5] [6]] [0 1])
;;=> 2
If you hit pain with your current hand-rolled tables, here are two libraries that might prove useful: https://github.com/redplanetlabs/specter (flexible handling of nested data) https://github.com/techascent/tech.ml.dataset (really fast ND-arrays)
@U0K064KQV It's the first case. I'm basically using your suggestion, thanks. @U3X7174KS They don't seem suitable for this but are definitely interesting, thank you.
If I have done an extend-type
or extend-protocol
is there a way to remove those again and go back to the standard definition?
Options:
1. Re-run the type definition (deftype/defprotocol)
2. Use something like clojure.tools.namespace.repl/refresh or integrant.repl/refresh
If you're using CIDER; there's M-x cider-ns-refresh
.
I'm not aware of a way to remove specifically the "registration" for the type you extended with.
Is there a function which wraps another function and can ammend it's arguments when called.
Not really, other than fnil
(which can replace nils in supplied arguments with default values). Trivial to write it yourself though, depending on what sort of amends you need to make.
some of arguments are guaranteed to be strings so I want to prefix then with astring
How about (defn f-wrapper [arg]
(f (str ammend arg)))
As I say, don't think there's a built in way to generalise this problem, although you could write one.
Hey. easiest way to interact with REST (well, Json over http) endpoints? Preferably without dependencies... β(rest...β didnβt work. Hopless term to search for. π
the easy way is https://github.com/dakrone/clj-http For a quick and dirty you can also use slurp: https://clojuredocs.org/clojure.core/slurp
Note that you will also need to pull in the optional Cheshire dependency if you want automatic JSON and Clojure map conversation, or you can do that outside the library.
Hum... Probably @UJRDALZA5's recommendation is best. But since you mentioned without dependencies, Java 11 includes a bundled HTTP Client: https://openjdk.java.net/groups/net/httpclient/intro.html
Good day! How can I pass "unrealized" function with some argument as argument of other function? Say
(def f [x f1] (* x (call f1))))
(def g [x y z] (+ x y z))
(def h [] (f 3 (g 1 2 3)))
I want (g 1 2 3) to be called EXACTLY when it's called in f as argument f1. Not when it was passed as parameter.You need a macro for that - ordinary function calls always evaluate their args before control flow is passed to the function
Example?
I though future/delay/promises will work somehow. But can't find out
There's three way to do it. Others already mentioned two of them. You can use macros. You can use thunks (aka higher order functions). And the last way is to use eval on quoted forms.
This is called a thunk, which is an anonymous function of zero-arity, which is used simply to delay evaluation and be passed around to something which is expected to evaluate it later.
You can also use a delay
to create thunks. They're slightly different to anonymous function thunks in that they'll cache the result, so you need to be sure you will not need to re-evaluate it more then once.
(defn f [x f1] (* x @f1))
(defn g [x y z] (+ x y z))
(defn h [] (f 3 (delay (g 1 2 3))))
Also, in Clojure code, you might see people using partial
to create anonymous function thunks. It results in the same thing as using #()
or (fn [] ...)
(defn f [x f1] (* x (f1)))
(defn g [x y z] (+ x y z))
(defn h [] (f 3 (partial g 1 2 3)))
Now let's see about using eval, I don't recommend it because eval has more edge cases, but here you go:
(defn f [x f1] (* x (eval f1)))
(defn g [x y z] (+ x y z))
(defn h [] (f 3 `(g 1 2 3)))
Finally, using a macro:
(defmacro f [x f1] `(* ~x ~f1))
(defn g [x y z] (+ x y z))
(defn h [] (f 3 (g 1 2 3)))
is this the correct way to read a bytearrayinputstream coming from a post body?
(let [_ (pp/pprint (slurp (:body request)))...
this works if you want to block until the stream is done, and the stream is text and not eg. a jpeg
I wouldn't expect pprint to do anything interesting to a stream that println wouldn't, and slurp always returns a string
oh yeah, that pprint is just a placeholder
what would be a nonblocking way? input-stream func?
just found the ring-json middleware, gonna try it
the most generic thing is to process the inputstream byte by byte, but really if you know the kind of data you expect you can get a better choice - for json, you can use slurp just fine
thanks
you probably want a json middleware eventually, but it seems like actually getting the data comes first
yeah the middleware worked great
Good afternoon!
Hi I am trying to redef a function using that function and that causes a stackoverflow, ie do something like
(with-redefs [f (fn [a b] (+ a (f b a)))]
...)
what would be the best way to get around this ?my request body is always coming empty, no matter the postman's request
Definitely a good article to keep handy when learning Clojure and reading code written by others. Regarding your question, I do not ever recall seeing the ^
character used in a symbol that named something in Clojure. Some people do use unsupported characters in symbols that name things, because the Clojure code reader allows some unsupported things without throwing errors, partly for backwards compatibility with code out in the wild that used them, and partly because of the efficiency of checking all of the rules at compile and/or run time.
(defn ^:private ^ServiceActor conn-service-actor
"Service actor from connection."
[{:keys [::app-id
::app-service-token]}]
(ServiceActor. app-id app-service-token))
Got it. I am so used to understanding what this use of ^
means that it did not even occur to me to think of the ^
character as part of the symbol. But I can imagine looking at it for the first time, and there it makes perfect sense that the ^
appears to be part of the symbol.
Fortunately, if you grok most or all of that 'weird and wonderful characters' article, and/or go back to it as needed, you should be pretty much done with understanding the syntax of Clojure.
so in this case does ^
signify anything to you (being a person who understands clojure more than i π)?
Right. And this section of that guide article has more examples and explanations, that are worth remembering exist in that article for if you forget: https://clojure.org/guides/weird_characters#_and_metadata
The main reason for such type hints in Clojure is to avoid slow calls to Java code. They can sometimes use the Java reflection API, if the Clojure compiler cannot determine at compile time which of several Java methods to use, instead determining on each call at run time which one to use.
Former you can give a full meta map, the middle is for a meta key with value true and the latter is for a :tag key with value to the type specified
I think the hint here is in the wrong place. To type hint return value, pretty sure the meta has to be on the arg vector
So the var tag should be AFunction, but Clojure doesn't need hinting for that so it's not useful. And the return hint should be on the args vector
The Clojure compiler does in some cases use a type hint on the var itself, too, which can be useful if the value of the var is not a function.
I don't have comprehensive cases to quote you off the top of my head, but you will often see type hints before the var for some functions, but before the arg vector for other functions, and I think it is typically recommended to put it on the arg vector for a function, since that technique also works for functions defined with multiple arities.
Take a look at the source for the clojure.string namespace in Clojure itself, for plenty of examples of functions defined like this: (defn ^String reverse ..)
. If that is wrong, then Stuart Halloway and Rich Hickey messed it up.
And here I thought I was going off into the weeds π
Hum... It might be that Clojure also somehow leverages the var type hint, but it feels wrong to me
It can certainly be confusing, because there are two places where "it does what you need it to", so the rules for writing it aren't as concise as one might like. That is probably the source of the wrong feeling.
I have found that in most cases where as an engineer you get the feeling that where a software system ended up in a place that makes no sense to you, it makes much more sense if you knew the history of how it got there. Such history of decisions is often difficult to find, though.
"makes much more sense" perhaps a loose translation for "seems less insane" in some cases π
I am not here to convince you that this state of affairs makes sense. I am trying to explain what is.
For example, a type hint of Fn
for a Var would be just about completely useless, yes? Very little, if any, Java interop calls would ever avoid reflection with such a type hint, because almost no Java methods care about class clojure.lang.Fn
, or any other clojure.lang.*
classes.
I suspect the decision might have been made because type hinting the return value of a Var that is a function is far more useful than saying "it is a function object".
Try experiments of passing the return value of reverse
to Java interop calls that can avoid reflection by knowing the return type is a String
, versus my-reverse
that does not have that type hint, and report back the results. I believe you will find that the type hint makes a difference in avoiding reflection in such cases.
The compiler might have special logic. But the official docs do not document type hints at that place
In particular this text: "`:tag` a symbol naming a class or a Class object that indicates the Java type of the object in the var, or its return value if the object is a fn."
It didn't here https://clojure.org/reference/java_interop
You can still use a let-bound symbol with a type tag in that case, I would think.
but I'm not so curious right now that I want to create code that would answer that question. let-bound symbols with type tags are a useful technique for avoiding reflection in some cases, though, if you can't easily find another way.
There are a few functions in Clojure source code that have type hint before the Var name and on the arg vector. The only ones I have seen (e.g. chunk-next) have the same type hint in both places. I don't know why that code does that, nor have I tried to give different types in the two places. That case is, I doubt, explained in the official docs anywhere, nor would I expect it ever to be (my personal guess -- I have no inside knowledge what the plans are for the official docs).
I would not be surprised if code like that might even date back to an early time in Clojure's implementation when type hints were supported in one place, but not yet the other, and support was being added for "the second place" in the compiler around that time. Just a wild guess, though. That code was written by the compiler writer, who knew exactly what it could/could not do.
My guess, is that if you pass the function around, you no longer have access to the var hint, but you maybe still have access to the args vector hint?
It is an area I delved into deeply once when writing some warning checkers in Eastwood, and wrote a section of its README explaining some of it, but not everything you are asking about, which I don't know the answer to all of them.
The compiler source code is there for the curious -- everywhere is walking place if you have the time π
Everywhere except a 100% certain answer to the question of "what was person X thinking when they wrote this?", which is unusual to find the answer to, unless they were doing insanely detailed literate programming, or you find the answer in some on-line discussion somewhere. I imagine it isn't exactly fun to answer such questions indefinitely to all askers.
Ya, I think people ask, because we like to know what is a wart versus what has a great reason behind it that we're just not seeing yet.
Like my curiosity would end, if someone was just like... Ya, this is a historic wart. But until then, I'm thinking, oh, are there times where one should be used over the other? Limitations to each, etc.
Java primitive type hints only work on arg vector, I am pretty sure.
if you want the implementation to take advantage of passing actual Java primitive long
or double
types as parameters or return values.
Except for that, it isn't clear to me that either is a historic wart.
I wouldn't really understand why they would have added the other if they started with that one, unless too many people kept making the mistake and they thought well... lets just support both
But my total guess out of thin air is that probably they started with the var one, and things evolved where they needed to support multi-arity, and other scenarios and maybe added the argvector one as well
On main Clojure channel, Alex brought up a good difference. Its what you just said, but it explains why. The var meta is evaluated, so typing ^long will resolve to the long function. Seems argvector is now preferred.
That is true, but I was trying to describe yet another difference: you can cause the Clojure compiler to create JVM byte code for a method that returns a primitive long
or double
type if you use the appropriate type hint on the arg vector. You cannot do that by putting any kind of type hint of any kind on the Var
At least, I am pretty sure that is true. It could be just one more reason to prefer type hints on the arg vector for functions.
Where can I check what's available to me when using the for
sequence comprehension form? More specifically, I'm referring to the :when
part:
(time (dorun (for [x (range 1000) y (range 10000) :when (> x y)] [x y])))
I've seen also :while
and :where
, but I'm not sure how to search the docs for that particular thing.
I only now noticed it on the bottom of the page paragraph that it specifies the modifiers.
:-) the examples may help also
Me too
I have them showing up in Cursive's docs as well and it's a very pleasant experience so far.
Is it a bad idea to dive into re-frame if I never did a webapp or cljs before?
no, i think itβs a great way to learn react
based on trying out react + other state management solutions that are much more bloated, re-frame is a lot easier to learn imo
I've been thinking the same thing. IMO it would be wise to have some idea as to what React is doing and what problems it helps alleviate.
But, you might have a harder time getting started. I view it the same as starting with React + Redux from the beginning. You don't really need Redux for the simpler stuff. It helps with being functional and pure and all that jazz, but it doesn't really help you understand React itself. In fact, I think it will be much more difficult.
Hi! I'm Connor. New to Clojure, really liking it, sometimes get caught in doc circles so time to start being more sociable. Is there an easy way to consistently get 'contracts' of anonymous function arguments? E.G. if I call doc on 'map-indexed' I get
clojure.core/map-indexed
([f] [f coll])
Returns a lazy sequence consisting of the result of applying f to 0
and the first item of coll, followed by applying f to 1 and the second
item in coll, etc, until coll is exhausted. Thus function f should
accept 2 arguments, index and item. Returns a stateful transducer when
no collection is provided.
For some reason have to read twice to parse out that the anonymous fn expects ([index item])
, whereas ([f] [f coll])
is immediately parsable.no, you're at the mercy of the author of the doc string sadly
Makes sense that would be hard especially once you get into the #() style anonymous functions but I had hopes.
Looking at the examples usually provides better insight on how you might use the function.
#() fns just expand
user=> '#(f % x)
(fn* [p1__2#] (f p1__2# x))
the real problem is that clojure has no type system keeping track of what functions expect or how they will be called beyond accepting invoke with a given arg or throwing an errorhonestly, I think this is more a convention problem. Even the type signature would still be a bit confusing. Like for reduce, I always forget if the accumulator is the first element or the second. I think Clojure could get pretty far just having a convention for documenting these HOF more clearly
the way I always remember it: you can pass conj
as the fn arg to reduce and it just works
or str
and the result is concatenated, not scrambled
...oof damn I had reduce arg order written down as [value accumulator]...that's why that function wasn't working at all. (Taking notes: doesn't work if you take the wrong notes, and I had it written with such confidence that there was a huge blind spot debugging that part. Thank you @U051SS2EU, for those particular examples π