Thank you for all the responses!
I am trying to read in a HeapByteBuffer from an AWS lambda response. It works fine in the REPL. But once I build and run a JAR file I get the following error:
{:type java.lang.IllegalArgumentException, :message "Cannot open <#object[java.nio.HeapByteBuffer 0x1d6014a7 \"java.nio.HeapByteBuffer[pos=0 lim=542 cap=542]\"]> as an InputStream."
I've tried opening it with a reader and directly slurp
-ing it in. Both work fine in repl but fail when I run the JAR as a Java executable.
Sample code:
(defn invoke-lambda-fn [fn-name arg-map]
(let [client (build-client)
payload (json/write-str arg-map)
request (-> (new com.amazonaws.services.lambda.model.InvokeRequest)
(.withFunctionName fn-name)
(.withSdkClientExecutionTimeout (* 15 60 1000))
(.withSdkRequestTimeout (* 15 60 1000))
(.withPayload payload))
resp (.invoke client request)]
(with-open [r (io/reader (.getPayload resp))]
(json/read r :key-fn keyword))))
Curious if anyone has run into similar issues?Ultimately it does work if I cast the buffer to an array. I'm mostly just perplexed by the error.
io/reader
and slurp
use a protocol that can be extended. The implementation of the protocol for HeapByteBuffer might be loaded in dev, but not as a jar. I would check to see if there's a dev only dependency or if there's a namespace that's loaded only in dev.
You can open up a socket server on your jar and check from that repl. Not sure what your main dev repl environment is
You could also explicitly add something like the following to make sure support is included: https://github.com/Datomic/fressian/blob/master/test/org/fressian/api.clj#L138
Mmm makes sense. The jar I was running had a different entry point than my repl. So even though the dependencies were effectively the same. Whatever was extending ByteBuffer in my REPL environment was never getting loaded while executing the jar.
Thanks for pointing me in the right direction.
Hello, I have a little question about list quoting. So, I want to run a bunch of validations over a value, so I thought of using every?
and pass a collection of fns that will be applied.
This works:
(every? #(% 5) [number? int?]) ;; true
But this doesn’t
(every? #(% 5) '(number? int?)) ;; false
And this one throws
(every? #(% 5) '((fn [n] (int? n))))
With the following error
Execution error (ClassCastException) at user/eval2042$fn (REPL:1).
class clojure.lang.PersistentList cannot be cast to class clojure.lang.IFn (clojure.lang.PersistentList and clojure.lang.IFn are in unnamed module of loader 'bootstrap')
I’m really confused about this
quotation means “do not eval”. so you are passing a list of symbols as a second argument for every?
symbol itself can be used as a function to get a value from the map
that is why
(every? #(% 5) '(number? int?)) ;; false
this throws
(every? #(% 5) '((fn [n] (int? n))))
because it applies a list (fn [n] (int? n))
to argument 5
instead of quoting you can use list
function
(list (fn [n] (int? n))) ;; => (#function...)
oh I see, thank you very much 🙂
What does "strong names" mean in the context of clojure? Seen several talks where the term is used.
hmm, so '(xyz) is not always the same as (list xyz)
(every? #(% 5) (list number? int?)) => true (every? #(% 5) (list (fn [n] (int? n)))) => true
also, small note, using the list
function is rare outside weird macro definitions, almost always you'd want [number? int?]
instead - the result is handled the same way and it's easier to read
list
creates a list of objects. It's like vector
, but for lists.
'(...)
quotes all the forms inside it.
So (list int?)
ends up being a list with one function clojure.core/int?
.
And '(int?)
ends up being a list with one symbol int?
. Which has no relation to clojure.core/int?
, except for the name.
Note that there's also (int?)` form of quoting, which will add the namespace to the symbol:
user=> `(int?)
(clojure.core/int?)
user=> (type (first `(int?)))
clojure.lang.Symbol
user=>
it is always not the same ) unless you have a var xyz
with a value 'xyz
(def xyz 'xyz)
I see Spec has been in Alpha for a while... where does it feel incomplete, to people who use it frequently?
Or does it feel like it’s alpha in name only?
it's alpha in that we are going to alter some parts of the api in spec 2, but I'd actually consider spec 1 to be quite stable
🍿
and we expect to provide support for migration whenever spec 2 is available
What parts of the API are being altered?
I'm also very interested in knowing more details about the spec. I've seen Rich's talk, I believe it was in "Maybe not", where he talked about spec being more powerful than type systems, but he also said he made some of the mistakes (some coupling, don't remember from the top of my head now) that the type systems make and that the future version of spec will fix that. Now the talk is a few years old now, so I don't know, is spec.alpha already the new version that fixed these concerns? I was meaning to look more into spec, but the alpha tag sounded a bit scary.
quote yields the unevaluated form. when unevaluated form is the same as evaluated form then they can have the same affect, e.g. '(1 2 3) (list 1 2 3)
https://github.com/clojure/spec-alpha2/wiki/Differences-from-spec.alpha
https://github.com/clojure/spec-alpha2/wiki/Schema-and-select
I need to apply some function f
to every pairing of entries between two collections and return the result.
(for [x (range 10)
y (range 10 20)]
(f x y))
Is there a better way to do this / a way to do this with transducers? I had this, but it’s uglier and the performance is not as good as using for
:
(let [xs (range 10)
ys (range 10 20)]
(sequence
(mapcat
(fn [x]
(map (fn [y] (f x y))
ys)))
xs))
If you wanted for
as a transducer, Christophe Grand's xforms lib has that https://github.com/cgrand/xforms
i’m calling a memoized factorial function, and. I’m not seeing performance improvements in the successive calls when compared to successive calls in the unmemoized verison.
(defn fact-unmemo [i] (if (= 1 i) 1 (* i (fact-unmemo (dec i)))))
(time (fact-unmemo 19))
(time (fact-unmemo 18))
(time (fact-unmemo 17))
(def fact-memo (memoize (fn [i] (if (= 1 i) 1 (* i (fact-memo (dec i)))))))
(time (fact-memo 19))
(time (fact-memo 18))
(time (fact-memo 17))
“Elapsed time: 0.040611 msecs”
“Elapsed time: 0.036174 msecs”
“Elapsed time: 0.035519 msecs”
“Elapsed time: 0.03265 msecs”
“Elapsed time: 0.030827 msecs”
“Elapsed time: 0.03215 msecs”time
is good for getting a general idea for how long an expression might take to evaluate, but for actual benchmarking, I’d recommend using something like criterium
Also, for your last one you have (time (fact-unmemo 17))
but I’m guessing you wanted (time (fact-memo 17))
isn’t this just map
? map
is variadic and steps over each collection simultaneously and passes the next tuple of each sequence to the function:
user=> (map + (range 10) (range 10 20))
(10 12 14 16 18 20 22 24 26 28)
is spec-alpha2 the future of clojure.spec?
(misread the code)
Not quite. If I wanted to pair the nth entry of xs
with the nth entry of ys
then that would work. But I want to pair each entry in xs
with each entry in ys
oh! my apologies for misunderstanding the inputs
np
Rich has conned me
Apart from Criterium mentioned above, computing a factorial is a very simple procedure. For low numbers, a cache lookup will be slower than a direct computation. 19 is not a very high number.
And if it's a practical problem with factorials that you're trying to optimize, you would be better off using a LUT.
Can you not call sequence on the same for expression?
I’m not sure that I follow your question
yes
(let [f (fn [[x y]] (+ x y))
xs (range 10)
ys (range 10 20)]
(into []
(map f)
(for [x xs
y ys]
[x y])))
Yeah, that works too. If I really need to stick with transducers for some reason, that will work, but I’ll probably just stick with using for
and embedding the call to f
there
Thank you
It seems like http://4clojure.com is down since a couple of days https://clojureverse.org/t/4clojure-com-status/7761/3 Anyone here have access to any of the maintainers?
The site seems to be working fine for me @slipset -- what errors are you seeing?
Works for me in chrome, but not safari, for some reason?
As that ClojureVerse post says, it does not work in Safari.
The site isn't "down", it's just old and no longer compatible with Safari I guess? I haven't used Safari for ages on my Mac (I use Microsoft Edge).
Yup
I just tried it in Safari and it's not clear to me why Safari will not load it -- seems to think the connection is reset but I don't get much love from the developer tools on Safari (which is mostly why I no longer use that browser).
I wonder if Safari defaults to refusing to load http:// sites now?
That is the case sometimes. I have been freaking out 1-2 times where the website just would’t load and by adding the s
to http it would just work @sean.kuo.work
there's a GitHub issue submitted for this very problem: https://github.com/4clojure/4clojure/issues/319