I’m trying to create a hyphenated namespace. I’m sure others have done it, why does it give an error that my namespace is invalid?
if the namespace is hyphenated, the file name should use _
might want to post the error if that doesn't sound like the problem
For some reason it says my namespace is written wrong. What the hell? I have everything correct.
It's the garden/garden
that's wrong, no namespaced symbols
I think you want garden.core :as garden
If you scroll that long error message, it should tell you more of what it didn't like and what part of the code it didn't like.
Ah man, that was so stupid.
I didn’t want to scroll though all the clojure spec errors.
The editor put a warning wiggly line under garden/garden
I tried that ns
form in a plain REPL and it's much more obvious:
seanc@DESKTOP-30ICA76:~/clojure$ clj
Clojure 1.10.2
user=> (ns wildwestrom.tailwind-garden
(:gen-class)
(:require [clj-css.core :as parser]
[garden/garden :as garden]))
Syntax error macroexpanding clojure.core/ns at (REPL:1:1).
garden/garden - failed: simple-symbol? at: [:ns-clauses :require :body :libspec :lib+opts :lib] spec: :clojure.core.specs.alpha/libspec
[garden/garden :as garden] - failed: simple-symbol? at: [:ns-clauses :require :body :libspec :lib] spec: :clojure.core.specs.alpha/libspec
garden/garden - failed: simple-symbol? at: [:ns-clauses :require :body :prefix-list :prefix] spec: :clojure.core.specs.alpha/prefix-list
[garden/garden :as garden] - failed: #{:verbose :reload :reload-all} at: [:ns-clauses :require :body :flag] spec: :clojure.core.specs.alpha/ns-require
:require - failed: #{:refer-clojure} at: [:ns-clauses :refer-clojure :clause] spec: :clojure.core.specs.alpha/ns-refer-clojure
:require - failed: #{:import} at: [:ns-clauses :import :clause] spec: :clojure.core.specs.alpha/ns-import
:require - failed: #{:use} at: [:ns-clauses :use :clause] spec: :clojure.core.specs.alpha/ns-use
:require - failed: #{:refer} at: [:ns-clauses :refer :clause] spec: :clojure.core.specs.alpha/ns-refer
:require - failed: #{:load} at: [:ns-clauses :load :clause] spec: :clojure.core.specs.alpha/ns-load
:require - failed: #{:gen-class} at: [:ns-clauses :gen-class :clause] spec: :clojure.core.specs.alpha/ns-gen-class
user=>
And you can see that garden/garden
failed simple-symbol?
_wonders why cider doesn't use the <https://clojure.org/reference/repl_and_main#_at_repl|available tools> in clojure.main to print the triaged error message rather than the explain data_
Maybe it just hasn't caught up with that yet? Or maybe it tries to do something that is portable across older versions of Clojure?
¯\(ツ)/¯
I talked to the cider folks about this 2 years ago
(I'm salty about complaints about error messages when tools don't display the results of work 2 years old)
the whole point of that work was to avoid showing everything that cider is showing
Hi @alexmiller, could you be more specific ? Is it possible to enjoy those improvements ?
If you use the default clojure repl, you'll get the new error messages, if you use a specific tool/ide, you'll have to refer to them. About CIDER specifically, I think @alexmiller is referring to this (unresolved) issue: https://github.com/clojure-emacs/cider/issues/2443
@caumond The plain Clojure REPL has all these improvements. Any tooling that has decided to take advantage of the additional "triage" functionality and the extra data that has been attached to all the exceptions will have all these improvements. CIDER has not incorporated that yet.
I have an atom object as below
#object[clojure.lang.Atom 0x432fca40 {:key :true,
:val {a "a",
:b "b"}}]
How can I remove :b
from atom?
(swap! my-atom dissoc :b)
@popeyepwr (swap! the-atom dissoc :b)
this has :val key inside we have 2 more keys :a and :b
@borkdude @lennart.buit
oh, (swap! the-atom update :val dissoc :b)
its is not removing
Sure enough:
(swap! (atom {:val {:a 1 :b 2}}) update :val dissoc :b)
{:val {:a 1}}
I notice your a
key is not a keyword but a symbol thoughhow to remove if it is a symbol?
in my code I have symbol
replace :b
with 'b
which library would you use to access apache kafka?
You might want to look at Ketu (https://github.com/AppsFlyer/ketu). I haven’t used it yet, but it’s intriguing. My current project is using Jackdaw (https://github.com/FundingCircle/jackdaw) which works just fine.
Nice! Thank you very much 🙂 I will look into both.
Why would you consider ketu instead of jackdaw?
From the video posted recently, it’s a pure Clojure solution. https://www.youtube.com/watch?v=zAlvM33UpGA
But again, I have no experience with it so can’t attest to its readiness.
ok. thanks again!
Any tips on how to avoid huge let bindings? Also nested lets
I'll test ketu and see how it goes 🙂
Smaller functions ? Are you sure you cant breakdown the function ?
In other words for me it is a smell for a too big functions
and once u break it in functions u can use threading macro -> or ->>
hi folks! 👋
brand new to clojure and attempting to put together a demo app for consuming an OAuth server that I maintain. I feel like I'm rather close, but am not quite understanding how to close the loop.
I'm using https://github.com/weavejester/ring-oauth2 and don't quite understand the part about accessing the access_token
in order to request a user's profile. There's also an error in my logs that im not quite sure what to make of, but i think it might be related to favicon request?
here's what I've got so far - https://github.com/enterprise-oss/osso-clojure-example/blob/main/src/clojure_osso_demo/web.clj
just hoping one of you kind folks might point me in the right direction to get this over the finish line
Can you post the error from your logs? Which Oauth Provider are you connection against, what implementation is there? Aah I see, Osso
here's the logs:
2021-02-04 10:24:33.108:WARN:oejs.HttpChannel:qtp871565652-27: /favicon.ico
java.lang.IllegalArgumentException: contains? not supported on type: compojure.core$routes$fn__4160
at clojure.lang.RT.contains(RT.java:849)
at clojure.core$contains_QMARK_.invokeStatic(core.clj:1492)
at clojure.core$contains_QMARK_.invoke(core.clj:1484)
at ring.middleware.flash$flash_response.invokeStatic(flash.clj:21)
at ring.middleware.flash$flash_response.invoke(flash.clj:14)
at ring.middleware.flash$wrap_flash$fn__5653.invoke(flash.clj:39)
at ring.middleware.session$wrap_session$fn__5630.invoke(session.clj:108)
at ring.middleware.keyword_params$wrap_keyword_params$fn__4383.invoke(keyword_params.clj:36)
at ring.middleware.nested_params$wrap_nested_params$fn__4441.invoke(nested_params.clj:89)
at ring.middleware.multipart_params$wrap_multipart_params$fn__4523.invoke(multipart_params.clj:173)
at ring.middleware.params$wrap_params$fn__4343.invoke(params.clj:67)
at ring.middleware.cookies$wrap_cookies$fn__5501.invoke(cookies.clj:175)
at ring.middleware.absolute_redirects$wrap_absolute_redirects$fn__6245.invoke(absolute_redirects.clj:47)
at ring.middleware.resource$wrap_resource$fn__6125.invoke(resource.clj:37)
at ring.middleware.content_type$wrap_content_type$fn__6193.invoke(content_type.clj:34)
at ring.middleware.default_charset$wrap_default_charset$fn__6217.invoke(default_charset.clj:31)
at ring.middleware.not_modified$wrap_not_modified$fn__6174.invoke(not_modified.clj:53)
at ring.middleware.x_headers$wrap_x_header$fn__5927.invoke(x_headers.clj:22)
at ring.middleware.x_headers$wrap_x_header$fn__5927.invoke(x_headers.clj:22)
at ring.middleware.x_headers$wrap_x_header$fn__5927.invoke(x_headers.clj:22)
at ring.adapter.jetty$proxy_handler$fn__5858.invoke(jetty.clj:27)
at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle(Unknown Source)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:501)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:375)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
at java.base/java.lang.Thread.run(Thread.java:832)
and the Oauth service is my OSS app Osso, we have a demo instance at https://demo.ossoapp.com that im using here (the Demo Production OAuth client)
im able to get sent to my OAuth server and am sent back to my application, and I see a request to the token endpoint on my oauth server
I’m not sure if the error is related to OAuth, as I don’t see the ring-oauth middleware in the stacktrace
ok, that sounds good!
so that lib allows me to redirect to a url, where I suppose I would then write something to use the access token to make a request to my oauth server's /oauth/me
endpoint
they say > the way you'd access the token would be as follows: > (-> request :oauth2/access-tokens :osso) and im not really sure what to make of that?
I used this in an app for Google Login (I can’t share the code), let me try and remember. The auth process in your app should be started, as soon as the user accesses /auth/osso, right? The user then gets redirected to the Oauth Provider, to log in
After login is done, they are redirected to /auth/osso/callback, a URL you need to provide in your application
You will then get a request parameter from that call, that contains a session with the token information that is sent too you by your OAuth Provider
The key should be something like :oauth2/access-tokens
. This will get you a map with the key :osso, and the tokens provided
I think the error lies in your Compojure and middleware setup, that’s not correct
You need to set up the routes, and wrap them with your middleware, in your code you have added wrap-oauth2 to the routes
call of Compojure.
i am using web sockets to receive events from an api and write parsed ones to s3 but i want to decouple receiving and writing to s3
i am doing (async/put!...
in on-receive
handler
and i created this fn to do the s3 bit
(defn loader [in]
(async/go
(while true
(let [msg (async/<! in)]
(store-in-s3 msg)))))
If i understood correctly the loader
will take messages as they come from the channel and do the 'writing'
and on-receive
can put to the channel as fast as possible.
I am just looking for confirmation is this correct or i misunderstood how async/go operates?smaller functions and fewer named things; huge let blocks are a symptom of thinking procedurally
I think it takes some getting used to, relaxing the requirement to give each intermediate step a name; you might get something out of this presentation https://www.infoq.com/presentations/Macros-Monads/
that looks like it will basically work; however one thing to beware of is that store-in-s3
is likely a function which blocks the thread
core.async uses a thread pool under the hood (a fixed size pool onto which ready go-blocks are scheduled)
if you block all of those threads calling store-in-s3
then no other go-block gets to run; this is not necessarily a show-stopper problem for what you're doing
but it is important to understand that you could theoretically get into a kind of deadlock situation doing things like this
I cannot run that code right now (at the wrong machine), but copy/pasted from your GitHub example, this is the direction you might want to take
check out https://clojuredocs.org/clojure.core.async/pipeline-blocking
if all you want to do is store-in-s3
for each message on a channel, AFAP, this ^ is a good way to do that
ok yup that helped get me pointed in the right direction for addressing that error, it gone! thanks so much!
now I need to figure out how to read a request parameter, and then use that token to make a request, which seems figure-out-able
An alternative to using pipeline-blocking is to wrap store-in-s3
with async/thread
so that it is executed in another thread pool separate from the one core.async uses to schedule it's go-blocks
(defn loader [in]
(async/go
(while true
(let [msg (async/<! in)]
(async/<! (async/thread (store-in-s3 msg)))))))
thank you for the answers but i am not sure how to use the pipeline or pipeline blocking in my case could u walk me through the process how to use this and think about this? I found https://gist.github.com/raspasov/7c9d8f2872d6065b2145 but it's not obvious what i should do
@blak3mill3r @hiredman u must've not seen question above that's why i am tagging. Could u tell me how to use pipline as it's not obvious to me or where could i learn about it and how it's used in detail and practical examples?
@lepistane this code calls long-blocking-op
in parallel with 18 threads, passing each of values
to it (and thus takes just barely more than 100ms)
(def c-in (a/chan 10))
(def c-out (a/chan 10))
(defn long-blocking-op [v] (Thread/sleep 100) [:result v])
(a/pipeline-blocking 18 c-out (map long-blocking-op) c-in)
(time
(let [values ["bang" "whiz" "pop" "Pow" "zow" "biff" "zing"]]
(a/onto-chan c-in values)
;; read the same number of outputs blocking this thread on each one
(doseq [v values] (println (a/<!! c-out)))))
a/onto-chan
is just like doing this: (doseq [v values] (a/put! c-in v))
the arguments to a/pipeline-blocking
are: 1) number of threads concurrently doing the blocking operation 2) the "to" channel 3) a transducer 4) the "from" channel
in this case it is a very simple transducer which, for each step, calls the blocking function passing that value as its one argument, and its return value will be put onto the "to" channel
Does that help?
the solution @chrisblom suggested might be better
it's a small change to the code you pasted
@blak3mill3r
> it's a small change to the code you pasted
That's true but this is good opportunity to learn and use core.async 🙂
So if i understand correctly "to" channel will contain either the [:result v] in this case or exception in case long-blocking-op
doesn't go as planned?
In my case the ln context of writing to s3. It will either have success or error response which then i can handle by having listening to that "to" channel?
No thread pool there, though, right? This code creates a thread for each message.
no
it uses a cached thread pool
So it reuses threads if possible
That is an unbounded thread pool btw
So it creates a new thread if none is available
ok cool! got it working, printing out the json to the client! naturally I'm sure a lot of this can get cleaned up, and i still have some nice-to-haves i'll try and figure out at some point, but cool! im a clojure dev now 😎
When beginners use put! they pretty much always leave out the callback argument, which is very bad
And many apis don't give you anything sensible to do using the callback
Using !!> will block the current thread to communicate back pressure without a callback
thanks much for your help Tim!!
unless you are using cljs, in which case you are screwed, because despite the necessity of callback based apis there, people keep writing them in a such a way as to not let you properly handle backpressure
pipeline-blocking lets you control the concurrency explicitly as well
s/lets you/forces you to/
Is clojure a frontend or backend language? Backend right? Clojurescript is frontend, but clojure is back given the fact that we can manage data/servers e etc in it, right?
Party in the front AND party in the back :)
if you think frontend as “running in the browser” then yes!
Happy to hear that! 🙂
is there such a value that compared to a number (with >, <, >=, etc.) always returns false?
can I create one ?
there might be some trick with reify, but I would guess you would run into issues with clojure's numeric optimization(?)
I don't see anything promising on the Number class that would allow that https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Number.html
@gr.evocatus I think ##NaN
might actually be what you want
(ins)user=> (< ##NaN 0)
false
(cmd)user=> (> ##NaN 0)
false
it might even exceed your needs, as it isn't even equal to itself
Also clojurescript can run on the backend as well.. If you really wanted to for some reason.
it's not a number, watcha gonna do? ¯\(ツ)/¯
That's amazing! I can't think of when I'd ever use this.. But it's amazing!
@noisesmith thanks! But I already did the bigger task in a different way
I'm writing my own binary heap implementation, just for fun and to learn Clojure deeper
Hey, technically not a clojure question but maybe someone is able to help: I use emacs/cider and have a clojurescript project with shadow cljs. I connected to the nrepl server but im not able to send s-expressions to the repl with C-c C-e
like I do with clojure. Anyone know how to resolve this?
@lukas.block If no one can answer here, maybe #cider and/or #shadow-cljs channels can help...
Thank you! I give it a try.
people do
I mean there is really great support for using npm packages from clojurescript now, so if you for some reason wanted to access stuff on that platform, it might make sense to run clojurescript on the server
Also, people have used Clojure in desktop applications as well, perhaps that is "front-end"
If you need a total order of elements ##NaN is not what you want, since it isn't involved in any total order on the floating point numbers. It is an oddball value that has all of its own weird properites.