clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
Alys Brooks 2021-06-23T02:21:51.339800Z

Thank you for all the responses!

jcompagni 2021-06-23T04:11:16.343700Z

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?

jcompagni 2021-06-23T04:12:33.343800Z

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

phronmophobic 2021-06-23T04:39:18.344400Z

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.

dpsutton 2021-06-23T04:58:56.345700Z

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

phronmophobic 2021-06-23T05:18:30.346Z

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

jcompagni 2021-06-23T06:49:27.346300Z

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.

jcompagni 2021-06-23T06:50:00.346600Z

Thanks for pointing me in the right direction.

Osman Cea 2021-06-23T12:38:47.349600Z

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 Cea 2021-06-23T12:39:56.349900Z

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 Cea 2021-06-23T12:40:52.351200Z

I’m really confused about this

2021-06-23T12:41:17.351700Z

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

2021-06-23T12:41:48.352200Z

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

2021-06-23T12:42:57.353300Z

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

2021-06-23T12:44:26.354100Z

instead of quoting you can use list function

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

Osman Cea 2021-06-23T12:45:35.354600Z

oh I see, thank you very much 🙂

hanDerPeder 2021-06-23T13:03:31.361300Z

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

Apple 2021-06-23T13:38:55.361700Z

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

Apple 2021-06-23T13:39:48.362Z

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

2021-06-24T16:26:08.398500Z

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

p-himik 2021-06-23T13:49:00.362100Z

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-himik 2021-06-23T13:49:57.362300Z

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

🙏 1
2021-06-23T14:06:12.362600Z

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

(def xyz 'xyz)

2021-06-23T14:13:04.363700Z

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

2021-06-23T14:14:53.363900Z

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

alexmiller 2021-06-23T14:17:35.365Z

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

Darin Douglass 2021-06-23T14:17:38.365200Z

🍿

alexmiller 2021-06-23T14:18:34.365600Z

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

👏 1
2021-06-23T14:25:55.366400Z

What parts of the API are being altered?

2021-06-23T14:49:23.370500Z

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.

Apple 2021-06-23T14:50:41.370600Z

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)

alexmiller 2021-06-23T15:09:33.371500Z

https://github.com/clojure/spec-alpha2/wiki/Schema-and-select

👍 1
stephenmhopper 2021-06-23T17:55:07.375800Z

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

Ed 2021-06-24T09:30:31.388100Z

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

zendevil 2021-06-23T17:56:33.376700Z

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”

stephenmhopper 2021-06-23T17:58:20.376800Z

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

stephenmhopper 2021-06-23T18:01:05.377Z

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

NoahTheDuke 2021-06-23T18:03:03.377200Z

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)

2021-06-23T18:04:14.377900Z

is spec-alpha2 the future of clojure.spec?

2021-06-23T18:05:18.378500Z

(misread the code)

stephenmhopper 2021-06-23T18:08:16.378800Z

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

NoahTheDuke 2021-06-23T18:08:34.379Z

oh! my apologies for misunderstanding the inputs

stephenmhopper 2021-06-23T18:08:42.379200Z

np

zendevil 2021-06-23T18:14:11.379400Z

Rich has conned me

p-himik 2021-06-23T18:18:51.379600Z

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.

👍 1
p-himik 2021-06-23T18:20:05.379800Z

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

dpsutton 2021-06-23T18:28:57.380700Z

Can you not call sequence on the same for expression?

stephenmhopper 2021-06-23T18:32:53.380900Z

I’m not sure that I follow your question

alexmiller 2021-06-23T18:47:18.381100Z

yes

🙌 1
dpsutton 2021-06-23T18:59:08.381500Z

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

👏 1
stephenmhopper 2021-06-23T19:22:00.381800Z

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

stephenmhopper 2021-06-23T19:22:03.382Z

Thank you

slipset 2021-06-23T20:45:45.383100Z

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?

seancorfield 2021-06-23T20:47:18.383300Z

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

slipset 2021-06-23T20:48:43.383500Z

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

seancorfield 2021-06-23T20:49:30.383700Z

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

seancorfield 2021-06-23T20:50:21.383900Z

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

slipset 2021-06-23T20:51:16.384100Z

Yup

seancorfield 2021-06-23T20:53:39.384300Z

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

seancorfield 2021-06-23T20:54:20.384500Z

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

vncz 2021-06-23T21:08:57.384700Z

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

vncz 2021-06-23T21:09:04.384900Z

@seancorfield

salam 2021-06-23T23:09:35.385200Z

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