Fork me on GitHub
#clojure
<
2021-06-23
>
jcompagni04:06:16

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?

jcompagni04:06:33

Ultimately it does work if I cast the buffer to an array. I'm mostly just perplexed by the error.

phronmophobic04:06:18

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.

dpsutton04:06:56

You can open up a socket server on your jar and check from that repl. Not sure what your main dev repl environment is

phronmophobic05:06:30

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

jcompagni06:06:27

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.

jcompagni06:06:00

Thanks for pointing me in the right direction.

Osman Cea12:06:47

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

Osman Cea12:06:56

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')

Osman Cea12:06:52

I’m really confused about this

delaguardo12:06:17

quotation means “do not eval”. so you are passing a list of symbols as a second argument for every?

delaguardo12:06:48

symbol itself can be used as a function to get a value from the map

delaguardo12:06:57

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

delaguardo12:06:26

instead of quoting you can use list function

(list (fn [n] (int? n))) ;; => (#function...)

Osman Cea12:06:35

oh I see, thank you very much 🙂

hanDerPeder13:06:31

What does "strong names" mean in the context of clojure? Seen several talks where the term is used.

Apple13:06:55

hmm, so '(xyz) is not always the same as (list xyz)

delaguardo14:06:12

it is always not the same ) unless you have a var xyz with a value 'xyz

(def xyz 'xyz)

Apple14:06:41

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)

Apple13:06:48

(every? #(% 5) (list number? int?)) => true (every? #(% 5) (list (fn [n] (int? n)))) => true

p-himik13:06:00

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.

p-himik13:06:57

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=>

🙏 2
noisesmith16:06:08

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

Rob Haisfield14:06:04

I see Spec has been in Alpha for a while... where does it feel incomplete, to people who use it frequently?

Rob Haisfield14:06:53

Or does it feel like it’s alpha in name only?

Alex Miller (Clojure team)14:06:35

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

Alex Miller (Clojure team)14:06:34

and we expect to provide support for migration whenever spec 2 is available

👏 2
Rob Haisfield14:06:55

What parts of the API are being altered?

Jakub Šťastný14:06:23

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.

vncz14:06:46

If I recall correctly the coupling he was talking about was the aggregate definition and what is required; they should be decoupled because the requirements are context specifics, and should not be in the schema per se

👍 2
stephenmhopper17:06:07

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))

Noah Bogart18:06:03

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)

stephenmhopper18:06:16

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

Noah Bogart18:06:34

oh! my apologies for misunderstanding the inputs

dpsutton18:06:57

Can you not call sequence on the same for expression?

stephenmhopper18:06:53

I’m not sure that I follow your question

dpsutton18:06:08

(let [f  (fn [[x y]] (+ x y))
      xs (range 10)
      ys (range 10 20)]
  (into []
        (map f)
        (for [x xs
              y ys]
          [x y])))

👏 2
stephenmhopper19:06:00

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

Ed09:06:31

If you wanted for as a transducer, Christophe Grand's xforms lib has that https://github.com/cgrand/xforms

zendevil.eth17:06:33

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”

stephenmhopper17:06:20

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

stephenmhopper18:06:05

Also, for your last one you have (time (fact-unmemo 17)) but I’m guessing you wanted (time (fact-memo 17))

hiredman18:06:18

(misread the code)

zendevil.eth18:06:11

Rich has conned me

p-himik18:06:51

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.

👍 2
p-himik18:06:05

And if it's a practical problem with factorials that you're trying to optimize, you would be better off using a LUT.

jasonjckn18:06:14

is spec-alpha2 the future of clojure.spec?

slipset20:06:45

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?

seancorfield20:06:18

The site seems to be working fine for me @U04V5VAUN -- what errors are you seeing?

slipset20:06:43

Works for me in chrome, but not safari, for some reason?

seancorfield20:06:30

As that ClojureVerse post says, it does not work in Safari.

seancorfield20:06:21

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).

seancorfield20:06:39

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).

seancorfield20:06:20

I wonder if Safari defaults to refusing to load http:// sites now?

vncz21:06:57

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 @U01S3FM9CV8

salam23:06:35

there's a GitHub issue submitted for this very problem: https://github.com/4clojure/4clojure/issues/319