This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-09-03
Channels
- # announcements (3)
- # asami (4)
- # aws (1)
- # babashka (22)
- # beginners (111)
- # calva (3)
- # cider (1)
- # clj-kondo (55)
- # clj-on-windows (9)
- # cljsrn (1)
- # clojure (13)
- # clojure-europe (35)
- # clojure-losangeles (3)
- # clojure-nl (2)
- # clojure-norway (2)
- # clojure-spec (2)
- # clojure-uk (5)
- # clojurescript (51)
- # conjure (5)
- # cursive (5)
- # datascript (1)
- # datomic (27)
- # deps-new (8)
- # depstar (41)
- # emacs (4)
- # fulcro (24)
- # graphql (4)
- # gratitude (8)
- # helix (36)
- # jobs (2)
- # leiningen (2)
- # lsp (11)
- # off-topic (24)
- # pathom (23)
- # pedestal (2)
- # polylith (27)
- # re-frame (12)
- # reagent (7)
- # reitit (1)
- # releases (3)
- # remote-jobs (1)
- # rewrite-clj (4)
- # sci (1)
- # shadow-cljs (27)
- # spacemacs (12)
- # tools-deps (31)
- # web-security (2)
Hey channel, with rewrite-clj (or any other tool), is there a way to quickly parse a clojure source file into a plain-data presentation?, e.g. {:type :list :meta {:private true} :children [...]
.
IIUC with rewrite-clj I need to use it's nodes api and can't get this plain-data representation.
You might find the analysis output from clj-kondo more convenient: https://github.com/clj-kondo/clj-kondo/blob/master/analysis
okay, silly question time! If I'm in ClojureScript and I print out and get #object[test$engine$backend$services$messaging_test$test_on_message]
that means that we're having an object that's a JS-function rather than function in cljs, right?
(okay I admit, there's a follow up question to this too)
nevermind tho! got what I was pondering about 🙂
Hello! I'd like to fetch about 150 URLs and then combine the results. Is core.async a reasonable choice for that or are the simpler future
enough?
future
will allow you to parallelise the fetching of the urls pretty easily. I guess it depends on how you want to combine the results as to which is a better fit.
Ah, ok! I can wait for them all to finish before doing anything. Then I want them in a single vector or something so that I can further analyze the results.
something like this will create a load of futures and then deref them with a timeout into a vector
(let [urls ["" ""]]
(->> urls
(mapv (partial fetch-url))
(mapv #(deref % 1000 ::timeout))))
is that what you mean?yes ... there's a threadpool that all the futures run on. A future will start trying to generate a value as soon as it's created, and deref
will get the value of that future ... if you want more control over the threadpool, I would reach for the java executors framework
I say this frequently, but since this is a thread in #beginners I'll repeat myself: using core.async
for long running IO tasks is a bad idea - if you have complex synchronization needs with throttling / timeout / retry / etc. it can help but you'll need to use async/thread or else you'll block up the tiny go block thread pool
but in this case it doesn't sound like you have any complex coordination needs
so you can skip using core.async entirely
Good afternoon everyone! First of all let me wish a Happy Autumn to everyone! It's a wish were are sending around in my country! I have a question that might sound a bit stupid...from what I have understood up to now (while I'm trying learning Clojure by myself) the language does not evaluating a function's arguments lazily. This is something that has to do with the language design?
Correct. Clojure will eagerly evaluate the arguments to a function. So in the expression
(+ (* 2 3) (/ 16 4))
the (* 2 3)
will be evaluated first, then the (/16 4)
to produce (+ 6 4)
which will then be evaluated. The +
function doesn't get the chance to say "I'm not going to use the second argument, don't evaluate it". However, we do have lazy sequences which won't necessarily consume all their input, allowing you to write code that processes an infinite sequence. Macros however can control the evaluation of their arguments if they need to. That is how the language is designed. And a Happy Autumn to you.Hi @U0P0TMEFJ. Thank you so much for your reply! Oh, I see! It's because Clojure is working on lists!
Yes. Your code is a tree of expressions that are recursively evaluated. If you want to delay execution, you can wrap an expression in a function and call it later.
there are cases where function args are lazily evaluated - for example
(ins)user=> (defn foo [& args] (+ (first args) (second args)))
#'user/foo
(ins)user=> (apply foo (range))
1
(range)
would take a very long time to execute and finally error if that were not lazy
There are lazy functions and structures. More over, I suspect there is a trade off between compiler optimaztions and lazyness but I don't know enough to speak on the topic. Clojure was built to target java so there were probably practical limitations as to why not everything could be lazy. But I'm guessing :)
Hi @drewverlee. Thank you so much for your reply! I was thinking about how Scala is doing it...
and certain functions will return those lazy data structures (which makes it look lazy), such as map
, but the evaluation is “eager”
Is the logic that is used by satisfies?
different from what is used to actually dispatch calls to protocol fns? Or could something iffy be going in with a (Java framework provided) com.sun.proxy.$Proxy66
where this is not even supposed to work?
So there is an existing interface IInternal
, and I extend my Foo
protocol with some-fn
to it. Then I somehow get my mitts on an opaque object (the proxy) that implements IInternal
, yet calling some-fn
on it results in:
java.lang.IllegalArgumentException: No implementation of method: :some-fn of protocol: #'user/Foo found for class: com.sun.proxy.$Proxy66
maybe share some code
or you may have reloaded your protocol (which creates a new interface of the same name)
(definterface IInternal)
(defprotocol Foo
(somefn [this n]))
(extend-type IInternal
Foo
(somefn [this n] n))
(let [p (proxy [IInternal] [])]
(and (isa? (class p) IInternal)
(satisfies? Foo p)
(somefn p 7))
Am I misunderstanding how proxy-&-friends fit into the whole Interfaces-and-Objects hierarchy?
it works for me, if I pass the right number of arguments to somefn
(definterface IInternal)
(defprotocol Foo
(somefn [this n]))
(extend-type IInternal
Foo
(somefn [this n] n))
(let [p (proxy [IInternal] [])]
(vector (isa? (class p) IInternal)
(satisfies? Foo p)
(somefn p 1)))
;; => [true true 1]
Hmm, you are right. Then it must be something else. Off to the Java-mines with me it is!
the reloading thing I mentioned above can definitely trip you up here
It does (and has), but this time it’s something else as this happens as my opaque handle works with satisfies?
unless there is some way for my require’d protocol to be out of sync with its own methods, but I have no clue how that could happen
To answer my own question/misunderstanding: satisfies?
Only checks to see if you have extended a protocol to a certain thing, not whether there are actual implementations defined for each of the fns in the protocol. Also, contrary to defrecord/deftype , you can implement random fns in an extend-type
call, which in my case made me miss my typo in a protocol fn name:clown_face:
my guess is com.github.benjaminasdf.idlelib.compsearch depends on com.github.benjaminasdf.idlelib.compsearchdispatch, so when com.github.benjaminasdf.idlelib.compsearch is compiled com.github.benjaminasdf.idlelib.compsearchdispatch is also loaded and compiled, and then it is loaded and compiled again on its own, and that kind of double compiling does weird things
I am going to revise that, my guess is actually that like the exception says, you are missing the class gnu.trove.TObjectHashingStrategy
Indeed adding a dependency to gnu.trove.whatever fixed it. I just assumed that this intellij.open.api thing would take care of that. Usually a package would declare it's dependencies right?
the reason it doesn't error at the repl is gen-class is sort of a non-op at the repl, it only does anything when aot compiling
hey how do i convert a string to an int ?
(Integer/parseInt "123")
ok i will try that
ya this works !
thanks
but why doesnt (int userInput)
work ?
np. You should be aware that this will throw an exception if it can't parse, see https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt(java.lang.String)
int
is meant to be used with other numeric types
wait can i use the entire java APi ?
in clojure
yep 🙂 it's a good feature
ok nice
thanks again
Because coercision isn't parsing? how are they different ?
A good question. To me, parsing is extracting structured information out of unstructured data. Coercion is taking a piece of structured data and converting it to a different kind of structured data.
Also, it's worth noting that entering a 7
into a repl will get you a java.lang.Long
rather than an int
so you might want Long/parseLong
instead. Also it's worth noting that "7"
is also valid edn so you could:
(require '[clojure.edn :as edn])
(edn/read-string "7") ;; => 7
thanks
btw, given how frequently this question comes up, one thing I'm looking at right now is adding a function to the Clojure API for it (along with other similar things)
oh ya that would be helpful
i seem to be unable able to use (cast Number userInput)
& (int userInput)
cast
does only one thing: throw an error if its arg doesn't fulfill the required class, and return the object otherwise (with no conversion or alteration)
(its presence in your code does allow the compiler to do things it wouldn't otherwise attempt though...)
thanks
you have too many parens around (if (> randNo userIn) ...)
- that will lead to a null pointer exception
in clojure, () doesn't mean "sub expression" like in math, it means "execute this"
Ok thanks
hey is there something wrong with this code
(def randNo (rand-int 10))
(defn guess []
(let [userIn (read-line)]
(if (= randNo (Integer/parseInt userIn))
(println "Well Done !")
(
(if (> randNo userIn)
(println "Oops try smaller !!")
(println "Oops try bigger !!"))
(guess)
)
)
)
)
wait i figured it out !
i didnt use parseInt the 2nd time that i tried to use a numeric operator
is there any way that to use parseInt on the input at the same time of defining it ?
something like this
let [userIn (Integer/parseInt (readline))]
wait thats legal right
i am going to try this
looks right to me
yup sorry for spamming the chat
Something to keep in mind is parens are not blocks or grouping, they are function application
randNo
will always return the same number, whatever it’s first evaluated at compile time, but maybe that’s what you wanted
Hmm thanks, can you elaborate a bit I don't think I get it entirely @hiredman
(ins)user=> (println "OK")
OK
nil
(ins)user=> ((println "OK"))
OK
Execution error (NullPointerException) at user/eval147 (REPL:1).
null
(x ...)
means "resolve or evaluate x, and then call it", println returns nil, you can' t call nil@U02DGP08V5F does this example help?
in this code fragment:
(if (= randNo (Integer/parseInt userIn))
(println "Well Done !")
(
(if (> randNo userIn)
(println "Oops try smaller !!")
(println "Oops try bigger !!"))
(guess)
)
it looks like you want do
, which is a macro that takes all its args and evaluates them in order (like {}
would in eg. js)(if (= randNo (Integer/parseInt userIn))
(println "Well Done !")
(do
(if (> randNo userIn)
(println "Oops try smaller !!")
(println "Oops try bigger !!"))
(guess))
also, as a style thing, we don't leave )
on a line by itself (which is different from most languages)
Omg thanks for the elaborate explanation !
Thanks Yes I guess do Is what I needed
@tws oh really didn't notice that
Hi 😄
I have two vectors.
One is a vector of vectors... [[:x :b :q :r :z] [:c :d :n :i :p :z] [:e :f :g :h :o]]
Two is a vector of desired-number-of-items from the subvecs of vector 1 [5 2 1]
The output would be [[:x :b :q :r :z] [:c :d] [:e]]
(5 elements of the first subvec, 2 of the second, 1 of the last)
What's a good way to implement this?
A bit late to the party... but I love solving this kinda problems... also as a beginner it gives me practice... here is my solution...
(def v1 [[:x :b :q :r :z] [:c :d :n :i :p :z] [:e :f :g :h :o]])
(def v2 [5 2 1])
(map (fn [v num] (take num v)) v1 v2)
This gives
((:x :b :q :r :z) (:c :d) (:e))
(map (fn [v num] (subvec v 0 num)) [[:x :b :q :r :z] [:c :d :n :i :p :z] [:e :f :g :h :o]] [5 2 1])
You could just map over it and run subvecThat's really smart. I mostly get how it works... it surprises me that the arguments stay aligned pair-wise
RxJS has very helpful diagrams to visualise these higher order functions. It should have all the common ones For Zip pattern - http://reactivex.io/documentation/operators/zip.html#collapseRxJS
One thing to be aware I believe if the vectors are not the same length, map will only run to the shortest vector.
Ah that's a good caveat to keep in mind @chesslunatic