This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-01-17
Channels
- # babashka (4)
- # beginners (161)
- # calva (19)
- # cider (13)
- # circleci (16)
- # clj-kondo (7)
- # cljs-dev (3)
- # cljsrn (46)
- # clojure (105)
- # clojure-australia (2)
- # clojure-nl (15)
- # clojurescript (20)
- # conjure (14)
- # core-async (8)
- # cursive (3)
- # datomic (4)
- # figwheel (5)
- # fulcro (22)
- # graalvm (1)
- # hoplon (2)
- # kaocha (3)
- # leiningen (6)
- # malli (5)
- # off-topic (19)
- # re-frame (5)
- # reagent (1)
- # reitit (43)
- # releases (1)
- # reveal (14)
- # rewrite-clj (2)
- # rum (1)
- # shadow-cljs (31)
- # spacemacs (2)
- # sql (6)
- # xtdb (8)
interleave sounds very useful, but i seldom see it used
(def goof '(:a 1 đ 2 :c 3))
(:a goof)
dumb icon face
i might expect an error from (:a goof)
(get :a goof) => nil
(get goof :a) => nil
that's at the cider repl
... or nil if key not present ... technically correct
loose typing
@codeperfect Is that a question?
get
on a list (with parentheses) always returns nil, I believe. It is more useful when given a first arg that is a vector or a map, not a list.
@seancorfield i haven't compiled code with that syntax, and i wonder if it should compile without an error, i stretch the limits of all software i use, and get nervous when i discover nonsensical code that compiles, i mean we can't have walmart giving away free teslas or anything
Do you think it is "nonsensical code"?
This is true also if what you pass to get
is not associative, it considers that like the key isn't on the thing since the thing cannot even associate keys to values
it just bothers me that the code doesn't make sense, it accomplishes nothing because it is garbage code, i think it is, and it still gets evaluated without an error
It makes perfect sense once you understand Clojure's semantics.
(goof :a) is new to me
Because nil
-punning is core to Clojure's idioms. So returning nil
here is far more useful (and idiomatic) than throwing an exception.
Associative data structures also implement function semantics: they look up their argument in themselves. Keywords also implement function semantics: they look themselves up in their argument.
user=> (get [1 2 3 4] 2)
3
user=> (nth [1 2 3 4] 2)
3
user=> (get [1 2 3 4] 100)
nil
user=> (nth [1 2 3 4] 100)
Execution error (IndexOutOfBoundsException) at user/eval6035 (REPL:1).
null
We have both approaches for different contexts.
yes that is the gist of it, i think the keyword function should only work with maps, that's all i am concerned weith
user=> ([1 2 3 4] 2)
3
oh, that is new to me
You can create new data structures that implement ILookup
and you can pass those as "arguments" to a keyword and it will "do the right thing". Clojure is about abstractions.
user=> (def stuff (reify clojure.lang.ILookup (valAt [_ _] 42) (valAt [_ _ _] 13)))
#'user/stuff
user=> (:a stuff)
42
user=> (:b stuff :c)
13
(as a silly example)I like this example, I've never used reify before nor extended a clojure implementation, but this gives me at least the very basics about why/how to do it.
reify
is awesome for adjusting one data structure to match another's API, so you can have different views into something. Also when you need to fake some interaction with Java under the hood.
@codeperfect Does that example help illustrate the point I was trying to make?
Hey folks, I'm trying to interop with a Java library that leverages .class
a lot, like below:
Family family = Family.all(PositionComponent.class, VelocityComponent.class).get();
Notice the PositionComponent.class
I was hoping I could interop by doing the following:
(deftype MovementComponent [speed dir] Component) ; the lib requires that it extend Component
; ... later in the code when I wanna make a family ....
; This doesn't work, get "Cannot cast class java.lang.Class to class [Ljava.lang.Class;"
(def fam (Family/all MovementComponent) )
; Also doesn't work, same error
(def fam (Family/all (class MovementComponent)) )
So I'm worried I might have to make a new namespace for MovementComponent
and use gen-class
, is that true? Or is there something else I can do. Having to use gen-class
would be a real bummer...@trevor670 So the issue here is Java varargs methods, not the classes.
If you look at the Java docs for the Family/all
method, I'm going to bet that is says static all(Class...)
and what it is expecting here is an array of Component objects.
So I think what you want is (def fam (Family/all (into-array Class [MovementComponent])))
Thanks so much @seancorfield! This is super exciting! (Thanks for all your clojure contribs to!)
the jvm is really weird but [Ljava.lang.class
means an array of java.lang.class
. Bizarre shorthand but the error message is trying to tell you
@trevor670 What is this library BTW?
In gamedev there's a really nice pattern that's also cpu cache friendly called Entity-Component-Systems. Ashley is a java implementation that strikes a great balance between ergonomics and performance.
ECS systems make let you break up your game logic into systems
which apply functions to a set of entities
based on what components
they have. (Example: apply rendering logic to all entities containing a render component)
They're not actually to hard to implement naively, but getting them performant is really important cause it's essentially your core game loop
Which why this is so awesome! I get to use clojure where it matters and enjoy the performance of the Ashley ECS!
Yep, Chris Granger, who created LightTable and Aurora, talks about ECS.
Ah, here's Ashley: https://libgdx.badlogicgames.com/ci/ashley/docs/
public static final Family.Builder all(java.lang.Class<? extends Component>... componentTypes)
so yeah, there's the Class...
type for (into-array Class [...])
I have installed intellj community edition and added cursive plugin , But I am not able to sync my file after starting repl,
@popeyepwr Not sure what you're asking so maybe #cursive would be a good channel?
Is there an easier way to write maps like these in Clojure:
(defn createContact
[phone email street city postal-code state country country-code]
{
:uuid "to be implemented"
:phone phone
:email email
:street street
:city city
:postalCode postal-code
:state state
:country country
:countryCode country-code
}
)
You could use zipmap
(defn create-contact [vals]
(-> (zipmap keys vals)
(assoc :uuid "to be implemented"))
where keys is a vector of keywords that correspond 1-1 to the vals.
This is not necessarily a better solution though, as you have less control over what goes in the map.New question:
(def contacts (atom []))
(swap! contacts (create-contact "
I then have this code, but I cannot get the info from the contacts atom in the repl? Tried this:
namespaces.core> @contacts
nil
namespaces.core> contacts
#<Atom@136cd01a: nil>
namespaces.core> (str contacts)
"clojure.lang.Atom@136cd01a"
namespaces.core> (str @contacts)
""
namespaces.core>
yeah now that I look at it I believe youâre looking for reset!
since you donât seem to want to run anything ont he current value of the atom
i don't think your createContact function is doing any work. If you have 8 values, i don't see how a positional function helps you at all. just write the map there
remembering the arg order seems worse than just constructing the map literal
Ok, so basically I am building controllers for a REST-api. Right now I am just going to populate it with mockdata. The reason I am creating a function is because I will have to also have a controller that creates a contact. I am very much a newbie though The thought now is to make a function that both creates a contact and puts it into the atom. This will later be connected to a DB
yeah you can swap! it, but you have to specify how you wnt to update the atom so itâd be like :
(swap! contacts conj (create-contact "+47 935 35 312" "" "Mellony Lane 42" "Berlin" "46162" "Berlin" "Germany" "52"))
:uuid #uuid "7326bc03-d044-4b0f-bafc-da4daf91bff5", Gotten this value after using the Java.util.UUID lib. What does the #uuid mean in this context? Will it mess up my uses of the ID in someway going forward?
hmm, studying compujure but could not find one thing or Im overlooking it several times I want that if lets say the index page is hit, a method is executed and the end-result is send to the browser
How about the usage example in the GH itself?
(ns hello-world.core
(:require [compojure.core :refer :all]
[compojure.route :as route]))
(defroutes app
(GET "/" [] "<h1>Hello World</h1>")
(route/not-found "<h1>Page not found</h1>"))
Oke, I mean can I do things like this :
(defroutes app
(GET "/" [] (display_data)
(route/not-found "<h1>Page not found</h1>"))
@U0EGWJE3E Of course you can
btw, clojure names usually don't use underscores. Usually the use hyphen: display-data
still does not display anything on my browser
(ns paintings.core
(:require [cheshire.core :as json]
[clj-http.client :as client]
[compojure.core :refer :all]
[compojure.route :as route]))
(defn image-url-size [image]
(let [data (select-keys image [:width :height])
url (get-in image [:tiles 0 :url])]
(assoc data :url url)))
(defn take-image-data [image-data object-number]
(->> image-data
(sort-by :name)
(last)
(image-url-size)
(merge {:object-number object-number})))
(defn assoc-image [object-number]
(-> (client/get (str " " object-number "/tiles")
{:query-params {:key "14OGzuak"
:format "json"}})
(:body)
(json/parse-string true)
(:levels)
(take-image-data object-number)))
(defn take-data [api-data]
(->> api-data
(map :objectNumber)
(map assoc-image)))
(defn display-data []
(-> (client/get ""
{:query-params {:key "14OGzuak"
:format "json"
:type "schilderij"
:toppieces "True"}})
:body
(json/parse-string true)
:artObjects
(take-data)))
(defroutes app
(GET "/" [] (display-data)))
then verify that when your routes do something simpler they work. Try to rule out assumptions.
for example test that when your routes are defined as:
(defroutes app
(GET "/" [] "Hello World"))
You can imagine itâs hard to guess what part of a computer is broken when it wonât even turn onâŠ
(Is it the battery? the screen? the ram? is the power out? am I blind? is this actually not a computer? is it the GPU? maybe a flash chip? maybe something is shorting out? maybe this outlet doesn't work?)
see what I mean?I might also suggest you inspect your browser to see what html itâs rendering and also if it has any errors in the console.
Like I said itâs hard to help when thereâs so much I donât know about your app, or what tutorials you followed
I recommend you first try to follow something until you get âHello Worldâ or similar in your browser
see this if you haven't yet: https://skillsmatter.com/skillscasts/3445-functional-web
Clojurians, am i beeing too rude by only coming to this group when i have a problem? I was thinking about ways that i can generate value to the group itself, but i didn't found anyone. If someone have an ideia of how i can help all achieve your goals. I fell bad to only come here to extract.
politely asked questions that lead to discussions help thousands of silent readers who may be facing the problem or just learn more in general. seems like a win win for everyone
I'm doing an exercise from the brave and true which involves querying a list of search engines in parallel and returning the first result from each in a vector I came up with this
(defn search-online-all
[query engines]
(mapv (comp first deref)
(doall (map (fn [engine]
(future (engine query)))
engines))))
The point of the exercise is to use future/delays/promisesI was debating wether to use mapv
instead of (doall (map ..))
Or if there is a better pattern that could be used here
One argument in favour of doall
is that it makes it more explicit that you want to realize the entire sequence at this spot. Especially if you are working in a team it gives away the intention to other developers very clearly.
ah nice! i liked it too
I was also thinking if there is a nicer way to do this so that the first result is the one from the engine that returns first, the second from the second fastest etc..
You could put a vector in an atom to hold the results, and use swap! & update to conj each result as it comes in. A core.async chan would work too.
ah right!
thanks!
% only works in the #() macro
Thanks, I hope this #(reduce (fn [c _] (inc c)) 0 %)
is good clojure code to count a seq where you do not allowed to use count
Hey! Iâm going through âLiving clojureâ and have ran into an issue when I was asked to install Cheshire. I added it to dependencies like so (project generated with lein if that matters)
:dependencies [[org.clojure/clojure "1.10.0"]
[compojure "1.6.1"]
[ring/ring-defaults "0.3.2"]
[cheshire "5.10.0"]]
then in my handler I try to require it like so
(ns cheshire-cat.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[cheshire.core :as json]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
but when I run repl and try to use json/generate-string
I get an error Syntax error compiling atâŠ.No such namespace: json
how can I debug what could be going wrong here?It is, yes.
One thing that you need to understand is your REPL is not necessarily inside the cheshire-cat.handler namespace, and it is that namespace only where you have required cheshire as json
Ah, should it bee switched to the handler?
riiight
So in user namespace you have not required cheshire as json and therefore can't use it
That makes perfect sense.
Too bad it wasnât mentioned in the book. Wouldâve saved me some frustration đ.
Thank you!
This can sometimes be a bit "magic", because some IDEs, like Cider, when you do eval-last-sexpr, it'll automatically eval it in the context of the namespace of the file you are in. So it might work like that, but then if you go at the REPL prompt and try to call something it won't. And it confuses people, cause you might assume that the IDE command to eval is the same as typing in the REPL but not exactly
Right, got it. Thanks for the detailed explanation đ
I did restart the server so I assume cheshire was installed just fine.
hmm, why here a classException #(reduce (fn [i xs] (conj xs i)) %)
I try to reverse a seq but am not allowed to use reverse
or rseq
In such a situation I'd try to check what the values of i
and xs
are with which the anonymous function gets called (additionally to @U11BV7MTK's suggestion below; I'd expect such a possibility to be useful in general)
It helps to write it:
#(reduce
(fn [accumulator element]
(conj accumulator element))
%)
+ if you prefer pen-and-paper style, also recall the difference between (reduce f coll)
and (reduce f val coll)
"still" meaning when evaluating what code (and "same error" being what exactly)?
(reduce (fn [xs i] (conj xs i)) () (range 6))
always use an initial value. otherwise reduce uses the first value of the collection for the accumulator
Try it out and tell us if it was that.. Learning to debug is arguably the most important skill to pick up.
Open a repl and try it there with your own sample data, do a couple extra println just to see how the data changes.
Your arguments to conj are backwards as are your arguments to the reducing function.
take some time and think about the arguments to your reducing function acc item
. and take some time to think about the arguments to conj collection item
and make sure they line up.
Hi, I am learning reitit and this is an example copied from a book: https://paste.ofcode.org/WkTRZKPgrKZSJbSPBRXSpA when I try curl -X POST
I get 404 instead of 405 though. It seems only the 404 default handler is considered :thinking_face: