This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-06
Channels
- # aws-lambda (6)
- # babashka (1)
- # beginners (204)
- # calva (10)
- # chlorine-clover (17)
- # cider (57)
- # cljs-dev (3)
- # cljsrn (3)
- # clojure (148)
- # clojure-bangladesh (1)
- # clojure-berlin (3)
- # clojure-europe (30)
- # clojure-france (1)
- # clojure-italy (4)
- # clojure-nl (5)
- # clojure-spec (4)
- # clojure-uk (14)
- # clojurescript (15)
- # code-reviews (8)
- # conjure (27)
- # data-science (9)
- # datomic (38)
- # duct (6)
- # figwheel-main (11)
- # fulcro (78)
- # helix (11)
- # jobs (1)
- # malli (18)
- # meander (22)
- # mount (4)
- # nrepl (3)
- # off-topic (93)
- # pathom (2)
- # pedestal (4)
- # re-frame (5)
- # reagent (6)
- # reitit (1)
- # ring-swagger (1)
- # sci (1)
- # shadow-cljs (19)
- # spacemacs (1)
- # sql (1)
- # tools-deps (76)
- # unrepl (1)
- # vim (5)
- # xtdb (8)
does that mean to not use :gen-class :implements
?
:gen-class
is a last resort.
oic ... I've been using it as a first resort
Do you have a doc link for the RequestHandler
interface?
I think in a decade of Clojure, I've used :gen-class
maybe twice?
• https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-core/src/main/java/com/amazonaws/services/lambda/runtime/RequestHandler.java • https://github.com/awsdocs/aws-lambda-developer-guide/blob/master/sample-apps/java-events/src/main/java/example/HandlerSNS.java
(reify RequestHandler
(handleRequest [this input context ...))
That will create an anonymous instance of a class that implements RequestHandler
.
so, handleRequest
is the entrypoint, so does the reify need to go in the defn
of handleRequest
?
No. That reify
call gives you back an object that implements the interface and has a single method, handleRequest
that can be called by whatever you pass that object to.
(ns handler.core
(:gen-class
:implements [com.amazonaws.services.lambda.runtime.RequestHandler])
(:import (com.amazonaws.services.lambda.runtime.events SNSEvent)))
(defn -handleRequest [event context]
(println event)
(println context))
this is what I have ... so, I need to maybe change the signature of handleRequest
and have it call something that does the reify?or can I call reify in the :implements [,,,]
?
You don't need any of that.
Wait... Explain how you're trying to use this?
How/where are you creating the instance of this?
this is supposed to generate a jar and the class exposes handleRequest
that gets called upstream by another process
That doesn't answer my question.
uhh ... maybe I'm not using the right words. So, if I don't reify, I can usually do this and it works, but then I'll have to parse the json payload:
(ns handler.without.reify
(:gen-class
:implements [com.amazonaws.services.lambda.runtime.RequestStreamHandler])
(:require [ :as io]))
(defn -handleRequest [this input-stream output-stream context]
(let [w (io/writer output-stream)]
(.write w "testing")
(.flush w)))
☝️ this works, but I wanted to use the event objects provided as wellso I make a jar out of that, hand it to AWS and they have a thing that calls it
Ah, so there's no Clojure code involved outside this?
correct
Ah, OK. Then, yes, you have to use :gen-class
here. Sorry. Your caller is Java -- it creates the instance -- so you can't use reify
here.
ok, thx for the clarification -- so, without reify, what am I to do to implement the interface with the generic?
Generics don't exist at runtime.
They are erased by the Java compiler.
ok, so, is it fine to tell it that it implements the interface, and then I can cast the event
in handleRequest
function?
No need to cast.
then how do I use event
as an SNSEvent
?
(defn -handleRequest [event context]
(println event)
(println context))
Just call methods on it.
To avoid reflection, you might want a type hint on the event
argument.
lemme lookup type hints
Just ^SNSEvent event
in the argument list
noice!
(defn -handleRequest [^SNSEvent event context]
(println event)
(println context))
ya, I think that's what I was after, thank you!
You've already imported the class so, yeah. That just avoids reflection in interop calls.
and I think it makes it more readable
Life is so much easier when your main entry point is Clojure 🙂
I'm getting this error now:
{
"errorMessage": "Class handler.core does not implement RequestHandler with concrete type parameters"
}
looks like even with the type hints, it still bombs out
Did it work without the type hint(s)?
(I assumed you already had something working before?)
the only thing I had working before was where I'm not implementing this interface and parsing the json from the input stream
this works, but it's implementing RequestStreamHandler
instead of RequestHandler
#aws-lambda may be a better place for you to find help -- since you're specifically dealing with issues caused by AWS Lambda, right?
correct
I can ask there, thanks!
note: with or without the type hints, it didn't work
I've no idea what that error message means -- so I assume it's specific to AWS.
I think that error indicates that the interface didn't fill in the generics
Generic types don't exist at runtime.
perhaps I can reify an implementation in another namespace and tell gen-class to implement that?
Static language doing a dance to be dynamic to resolve a static method implemented in a dynamic language
@ghadi: have you had success doing what I'm trying to do?
implement the interface with generics using genclass
bump, interface followed by java implementation
(and I believe you 🙂)
This
public class HandlerCloudFront implements RequestHandler<CloudFrontEvent, String>{
(or similar, right?)
(correct)
I never implement RequestHandler, I always implement RequestStreamHandler, then read the event as JSON
me too, that's what I usually do
but I wanted to see if this was possible
ok, I'll go back to that
Sometimes the best solution to a problem is to avoid the problem 🙂
https://github.com/Frosku/disultory Baby's first public release, tear it apart plz.
i started poking around with websockets using sente. i ripped off quite a bit of code from sente’s examples. i noticed there are a few methods like this in both clojure and clojurescript:
defmulti -event-msg-handler
"Multimethod to handle Sente `event-msg`s"
:id ; Dispatch on event-id
)
(defn event-msg-handler
"Wraps `-event-msg-handler` with logging, error catching, etc."
[{:as ev-msg :keys [id ?data event]}]
(-event-msg-handler ev-msg))
(defmethod -event-msg-handler
:default ; Default/fallback case (no other matching handler)
[{:as ev-msg :keys [event]}]
(ws-utils/->output! "Unhandled event: %s" event))
(defmethod -event-msg-handler :chsk/state
[{:as ev-msg :keys [?data]}]
(let [[old-state-map new-state-map] (have vector? ?data)]
(if (:first-open? new-state-map)
(ws-utils/->output! "Channel socket successfully established!: %s" new-state-map)
(ws-utils/->output! "Channel socket state change: %s" new-state-map))))
(defmethod -event-msg-handler :chsk/recv
[{:as ev-msg :keys [?data]}]
(ws-utils/->output! "Push event from server: %s" ?data))
i understand the destructuring going on here with {:as ev-msg :keys [blah blah blah]}
, but is there any reason you might want to keep {:as ev-msg}
in methods where it isn’t even being used (e.g., the :chsk/recv
one), as opposed to simply [{:keys blah blah}]
?
it doesn’t seem to matter in practice when i change it up. i’m assuming that it’s either a) keeping the signature of the function uniform due to defmulti out of convention, or b) the code isn’t as clean as it could be.
my linter is upset, so i’m inclined to remove it, but wanted to double-check that i’m not violating actually good code practice.it's useful to point you at the context of the overall map, not required
linter will prob be happier with _ev-msg
leading (or only) _ is often used as a convention to mean "not used"
only a convention, has no meaning to Clojure, but linters follow it
(repeatedly 3 (constantly true))
. I don't believe you can use the #(true)
syntax: (macroexpand
(repeatedly 3 #(true)))`
Got it, thanks. I actually need an infinite lazy seq as it’s part of a larger lazy structure
(doc repeat)
. i wish as a beginner i would have used doc
and apropos
more. they are truly fantastic
Hi, can anyone help me by referring a good article for using MSAL ( Azure AD B2C) with Clojure please.
for something like this, you need to use interop
if it works with java, you can use clojure with its java interop. if not, ther'es also cljs which can use the js interop
interop is a very small sublanguage https://clojure.org/reference/java_interop
Insidious problem: How can I get exception messages happening in threads to the console? As we're in the #beginners channel, here's a few more details as it's quite possible I'm asking the wrong question. Last night, I lost quite a few hours where a seemingly innocent six-line change completely stopped my software from behaving correctly – it didn't crash, it just acted like some function deep in the system was mysteriously no longer getting called. Thanks to git, I narrowed my way in on the problem. It was a stupid mistake on my part, I was trying to pass a date and had an extra set of parenthesis, so it was trying to execute the value... the kind of thing you'd get a "cannot convert to class clojure.lang.IFn" exception for. Except Clojure was showing me nothing. No exceptions. No errors. Nada. Deeper dive: I'm using websockets, specifically ztellman's aleph. When a socket makes a request, a callback handles it, constructs the response, and returns it to the socket. All this is working fine, and my trivial error was in one of the callback helper functions. In hind-sight, and I can only reason about the behavior, it acted like the thread crashed (silently) due to an exception. I just had no way of knowing that was the issue, much less where or why. What I was expecting was an exception message on the console, but I'm not quite clear what's truly happening. Perhaps aleph has background threads, maybe it's doing something with futures, maybe there's dark magic. I'd suspect if stdout/stderr was involved, it'd inherit those values from the main thread, but then again isn't exception reporting the role of the VM, so I'd think that shouldn't matter. Environmentally, I was running IntelliJ 2020.1 with Cursive 1.9.2-2020.1 as the REPL. I feel like I'm missing something pretty essential and basic. :thinking_face:
I've also been wondering if alepha is holding a thread open for each websocket connection, or whether it acts more like the good old select() system call that allows one thread to multiplex socket activities, similar to NodeJS.
This might help: https://stackoverflow.com/questions/19422366/java-uncaught-global-exception-handler
This certainly sounds like what's happening -- although it's aleph that's doing the magic at the time a socket connects to the web server, so I'm not exactly sure how I get this to happen at thread creation time. But this does give me something to research. Still accepting ideas and suggestions.
I was just looking at https://groups.google.com/forum/#!topic/aleph-lib/suDg8bbxnSo, which shows it's possible with Alpha, and just got back here to post the link when I saw your message @U1G5P6G0L. Can you point me at a resource on how to do that with Clojure? #beginners
Think I found it. Stop me if I'm wrong: https://stuartsierra.com/2015/05/27/clojure-uncaught-exceptions
(Thread/setDefaultUncaughtExceptionHandler (reify UncaughtExceptionHandler (uncaughtException [this thread ex] (println "Got Exception" ex "from thread" thread"))))
(status so far) -- the code from the article above, which closely matched the code fragment shown by @U1G5P6G0L, compiled fine but appeared to have no effect when I reintroduced the simple error. I did attempt throwing an Exception manually, and that was caught and appeared on the console ...but not by the exception hook I installed. :researching: (Want to make sure it isn't user error.) That said, this is the first time I'm seen a stack trace with an io.aleph.dirigiste.Executor$Worker$1.run and a manifold.executor/thread-factory/reify/f in it.
One of the issues I have with the concept of exceptions is that it leads people into thinking that errors are exceptions - if you are concurrently processing data - which presumably involves some I/O at some point - something will fail - it's not a matter of if - it's a matter of when. Best to build your code around it from the start. I would think unittests and spec are your friends. I have also been using this to turn my errors into values rather than to have exceptions jump around my code - https://github.com/fmnoise/flow
@USWSAE547 - preach! And while I'm "pickin' up what you're puttin' down," the code I'm working against does not use Exceptions to catch errors; in fact, that's why there is no try/catch going on anywhere. But in this case unittests and specs aren't gonna catch dumb coding mistakes like where I accidentally had an extra set of parenthesis around a value. Given that's caught at runtime, I want a hard crash to make me go resolve the problem. Unless I can get the Exception to surface on a thread, it'll silently just start working incorrectly. I'm facing a new problem that the global UncaughtExceptionHandler is not being triggered -- which makes me wonder if something in the library or about the invocation methodology is catching the error. : still investigating :
Fair - I found unittesting each component of processing pipeline - was critical to my success - I am also a fan of random errors - that you can throw in unittests and see how well your code copes when things randomly break - but yeah I have yet to find a remedy for mistakes - still looking though 🙂
In the JVM, every thread can have its own uncaught exception handler (set via the Thread api) and there is also a default uncaught exception handler, which should print exceptions to stderr.
so in the default setup, you should see thrown exceptions on background threads in your console
I'm not sure what aleph or other libs you might be using do though
This certainly sounds like what's happening -- although it's aleph that's doing the magic at the time a socket connects to the web server, so I'm not exactly sure how I get this to happen at thread creation time. But this does give me something to research. Still accepting ideas and suggestions.
the classic MO of async processing is to have a bug that doesn't send something along when it's supposed to and processing just stops - this can happen without an exception, just with faulty logic. this is kind of the classic tradeoff of splitting your effective stack trace across a bunch of independent async processes
I'm ready to start a new project in CLJS, after a couple of years away from Clojure. Back then, my tools of choice were leiningen and re-frame. Today, for a browser app, making heavy use of existing JS and React libraries, what's the recommended tooling? Still the same, or shadow-cljs + ???, or ....?
I usually go with shadow-cljs, reagent and re-frame.
Thanks.
If I'm reading the current re-frame-template
readme correctly, it looks like this is already built-in?
Yep, it’s already built in.
Hello ! I just read this post find on Twitter "How to check if a list contains a value in Clojure" https://www.mednikov.tech/how-to-check-if-a-list-contains-a-value-in-clojure/ Is there more idiomatic solutions ? I'm surprised, it seems a little bit complected to return true or nil/false if list contains or not an value.
the idiomatic solution is to use an indexed collection by the value you want to look up (eg. a set or a map with the items you want to check for as keys)
using some
is a fallback and doing it frequently is a sign you are using the wrong collection type
Also that author is being sloppy with terms that are important (especially important as a beginner) - methods and functions both exist, contains?
is a function, it's not a method. A function is an Object
implement IFn
, which includes an invoke
method, when clojure compiles (f x)
it looks for the invoke
method on f, and compiles code calling that method on x
this is important because methods do not exist as first class values (you can use reflection to get method handles, but those still are Objects standing for a method in a reflective context). you can pass a function as an argument, because it's an object, you can't pass a method as an argument, because it isn't, it has no standalone existence apart from the object it belongs to
Perfect @U051SS2EU for all this explanations, thx!
np - hope it wasn't too much of a brain dump
made this https://gist.github.com/gerritjvv/15c721c0e1eac18cad953120975d3968 to show different ways to look for values in a list.
Really weird one: for some reason in my test namespace, clj-http
isn't decoding JSON, but in my -core namespace, it is. This makes testing basically impossible.
Sounds strange. You're providing the same options in both calls?
Are you hitting the same service, or is the test code hitting a different endpoint? (maybe the test endpoint has the wrong content-type so clj-http
thinks it isn't JSON?) @U016JPB0Z27
If a function returns a future that no one uses, the computation inside the future still will take place, right? That is, a future can be a way of saying “I want these things to happen on some other thread” and I can choose to deref the future if I want the result (or not deref it)?
@fappy Yes, future
can be used for "fire-and-forget" tasks.
It's worth thinking about exceptions -- an exception in a future will be "lost" unless you either dereference it or have a try
/ catch
inside the future
(and log the failure or do something else with it)
Hi everyone! I'm just starting out in Clojure. I already have a question that I'm too curious about to wait until I run into an answer. What's the Clojure substitute for duck typing? I'm trying to figure out how you delegate calculations. For example, what's the Clojure equivalent of this Python code?
class Circle:
def __init__(self, length):
self.length = length
def area(self):
return (self.length / 2) ** 2 * 3.14 # close enough
class Square:
def __init__(self, length):
self.length = length
def area(self):
return self.length ** 2
total_area = sum([shape.area() for shape in [Circle(4), Square(4)]])
print(total_area)
lots of ways to do polymorphism in clojure. One example would be
(defmulti area :shape)
(defmethod area :circle [{:keys [radius]}] (* Math/PI radius radius))
(defmethod area :square [{:keys [length]}] (* length length))
(area {:shape :circle :radius 3})
@U017ANLQXBJ, this is also possible with protocols:
(defprotocol IArea
(area [this]))
(defrecord Circle [radius]
IArea
(area [this]
(* Math/PI radius radius)))
(defrecord Square [length]
IArea
(area [this]
(* length length)))
(area (->Circle 2)) ;; 12.566370614359172
(area (->Square 2)) ;; 4
Clojure has pretty flexible dispatch mechanisms. You may be interested in these articles that talk about the CS theory as well:
https://en.wikipedia.org/wiki/Dynamic_dispatch
https://en.wikipedia.org/wiki/Multiple_dispatchThank you both!
since clojure has an "a la carte" approach to OO and polymorphism, I unexpectedly learned a lot about OO from clojure even though clojure isn't primarly an OO language
noob reify question:
(defn firebase-save [path v]
(-> (FirebaseDatabase/getInstance)
(.getReference path)
(.setValueAsync
(stringify-keys v)
(reify DatabaseReference$CompletionListener
(onComplete [err _ref] (throw err)))))
Goal is to have firebase throw the actual error when saving value (rather then a java.util.concurrent.Exception)
I am trying to reify DatabaseRefrence$CompletionListener
, but am getting the error;
Can't define method not in interfaces: onComplete
Am not sure why clj is telling me ^ -- onComplete does seem to exist on the interface > https://firebase.google.com/docs/reference/android/com/google/firebase/database/DatabaseReference.CompletionListener
(when i click into it from intellij, I see it exists too. How could I dig deeper?@stopachka from the reify
docstring:
> Note that the first parameter must be supplied to correspond to the target object ('this' in Java parlance) Thus
methods for interfaces will take one more argument than do the
interface declarations.
One more noob question:
(defn firebase-save [path v]
(future
(-> (FirebaseDatabase/getInstance)
(.getReference path)
(.setValue
(stringify-keys v)
(reify DatabaseReference$CompletionListener
(onComplete [_this err ref]
(if err
;; TODO future should throw?
(throw err)
;; TODO future should complete?
true)))))))
Goal: firebase gives me an onComplete
handler. If there's an error, I want to throw the original error to the future, otherwise I want to complete it
Here I would guess the future would complete without waiting for onComplete
How could I do above?you could create a promise
, then put a deliver
to that promise inside the onComplete method
that's cheap, and gives you an object that will block on deref (and return false for realized?) until that onComplete runs
after which it will return the value delivered in the onComplete on deref
if you want the future not to complete until the onComplete returns, you could put a deref of the promise as the last thing in the future
(defn firebase-save [path v]
(future
(let [p (promise)
_work (-> (FirebaseDatabase/getInstance)
(.getReference path)
(.setValue
(stringify-keys v)
(reify DatabaseReference$CompletionListener
(onComplete [_this err ref]
(deliver p [err ref])))))
[err ref] @p]
(if err (throw err)
ref))))
^ something like this?that looks right, yeah
note: reason I am wrapping with future, rather then just returning promise, is so I can get the semantics, that by dereferencing an error, it would throw
you could get the same thing, without "wasting" a thread, by reifying IDeref
(using a promise to implement, throwing on some condition)
foo=> (def d (reify clojure.lang.IDeref (deref [this] (if (> (rand) 0.5)
(throw (Exception. "you lose")) 2))))
#'foo/d
foo=> @d
Execution error at finops_admin.auth$reify__52601/deref (48914f44106185aac2a591f0a62c0
f52e50e2fdfe7863baaeea7e53dc016c825-init.clj:1).
you lose
foo=> @d
2
Okay a bit of a noob question: How would I merge this reify Idea, with promise? Maybe I can do something like: have a promise that accepts expects a delivery of [err res] in IDeref, if err we throw
you would deref the promise and do the conditional in your original, inside the deref method
(reify IDeref (deref [this] (let [[err ref] @p] (if err (throw err) ref)))
or something similar
since this is the beginners channel, I'll go into more detail - the deref
method is what gets called when you use @
, so here you are describing the behavior of this anonymous object if it is dereferenced
(defn throwable-promise [f]
(let [p (promise)
resolve #(deliver p [nil %])
reject #(deliver p [% nil])
throwable-p (reify IDeref
(deref [this]
(let [[err ref] @p]
(if err (throw err) ref)))]
(f resolve reject)
throwable-p))
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html
Hi guys I just wanted to run a simple shell command using clojure. I am using the clojure.java.shell
's sh
function.
When I run something like (sh "ls")
this prints out what I expect in the REPL. However, when I run (sh "lsof" "-nti:" (str port))
it doesn't print anything out. I can hit enter again and I get back the REPL prompt.
Does anybody know why this is?
Okay, I think it is because I've run another (sh ...)
previously which is hogging the *stdout*
. Once I killed that process... it seems to work.
what does it return? you can get the last return value with *1
should that be (sh "lsof" (str "nti:" port))
?
shell/sh should collect all stdout/stderr from the process as data
That might be it, I'll try that @alexmiller
That works. (I had to add the hyphen before the "nti" part)
I think the main problem was that I ran an (sh ...)
that started a server and that was hogging(?) all the *stdout*
stuff.
When I killed my server process, both the server's output and the "lsof" output were printed out in the REPL.
I think the previous call was simply blocking your repl, sh doesn't run in the background
it shouldn't be using `*stdout*` at all, it's redirected to a string
If it was blocking my repl, I shouldn't be able to run another command right? Or does a repl command get dispatched to a new thread?
if it's blocking your repl, the repl doesn't read again until it returns
you can still type in, and that will get echod back
you just won't cause any evaluation
also, the ProcessBuilder
and Process
classes that sh
is built on are not especially hard to use, and offer a lot of flexibility
Would they be the right way to start some long running process? I guess since process is in the name... 😛
sh is not built on those
it's built on the older and much less good Runtime stuff
oh, my mistake
I've been using ProcessBuilder via interop lately and they are much better :)
yes - was actually amazed by how easy Process / ProcessBuilder were to use, easier than the most popular wrapper on them even
(defn exec
[command-args]
(let [proc-builder (doto (ProcessBuilder. ^List command-args)
(.redirectOutput ProcessBuilder$Redirect/INHERIT)
(.redirectError ProcessBuilder$Redirect/INHERIT))
proc (.start proc-builder)]
(.waitFor proc)))
is a pretty good start for a lot of stuff (but doesn't handle swiping a "result" from the process, really just for forking out
in a terminal this runs an editor, then you get your repl back after it exits
(-> ["vim"]
(ProcessBuilder.)
(.inheritIO)
(.start)
(.waitFor))
Woaaah this is awesome
if you remove the waitFor
call, every other character you type goes to the repl or the editor on my machine
What is another way of saying:
(when (rand-nth [true false])
"Some code")
I want to set the probability with a bit more precision. Say, have the code executed about 65% of the time.how about (when (< (rand) 0.65) ...)