Fork me on GitHub
#clojure
<
2021-08-08
>
seancorfield02:08:27

Yes, you can. The local-sym :some-key pair is just another key/value pair in the overall destructuring.

👍 3
seancorfield02:08:49

Funnily enough, I just did exactly this in the next-gen version of clj-new I'm writing...

seancorfield02:08:43

(because I want a :name command-line arg but don't want to shadow name in clojure.core)

👍 3
seancorfield02:08:50

Nested destructuring is always a bit 👀

R.A. Porter03:08:46

Of late, whenever I'm trying to go deeper (literally and metaphorically) with my destructing, I'm glad to have this link handy: https://danielgregoire.dev/posts/2021-06-13-code-observation-clojure-destructuring/

deleted03:08:30

ahhh yes that was in the first edition of clojure morsels 😄

😂 3
R.A. Porter03:08:28

I knew one of you great folks had posted a link to it originally. 👍

partywombat 3
amalantony05:08:51

Do lazy sequences evaluate more items than you ask them to? For example:

(defn print-inc [num]
    (println "Incrementing:" num)
      (inc num))
  
(take 3 (map print-inc (range 1 10000)))

didibus08:08:00

Yes they implement "chunking" which means it does batch, for performance reasons. That's why people suggest not to rely on lazy-seq for implementing lazy side effect behavior, because it can be tricky to know exactly when a side-effect will run, since many functions might realize a few more elements in the sequence then you might expect.

didibus08:08:14

There is chunking, which has it realize 32 at a time, but there are other functions that if you use them over a sequence sometimes are not as lazy as you'd hope, and end up realizing a bit more than just the next element.

amalantony05:08:12

That prints Incrementing: 1 upto Incrementing: 32

amalantony05:08:19

although I've only asked for 3 items.

amalantony05:08:30

I'm curious if there is any batching involved by default.

lassemaatta05:08:27

I believe lazy seqs are chunked (in batches of 32) by default, see e.g. http://clojure-doc.org/articles/language/laziness.html

6
noisesmith15:08:09

only some lazy types are chunked, but if the difference between realizing one item and realizing 32 items matters to you, don't use laziness

noisesmith15:08:23

don't count on chunking or the lack of chunking

dgb2310:08:21

Another magic number is 21 which is the maximum amount of function arguments I think.

delaguardo10:08:45

although, 32 is not a magic number. There is a good article explaining why 32 - https://hypirion.com/musings/understanding-persistent-vector-pt-1

Ben Sless10:08:56

This doesn't really explain why 32 and not 64, for example

Ben Sless10:08:27

powers of 2 make sense, they make caches and cpus happy

Ben Sless10:08:33

CPUs like arrays

p-himik10:08:08

But now you're explaining it, and not the article. :)

p-himik10:08:16

Although I'm still not sold on that explanation. I know of contiguous things being good and batching being good. But just as with CPUs having an odd number of cores, I'm not sure if any batch has to have a size that's a power of 2.

Ben Sless10:08:26

Now you're getting into things like how caches work, how CPUs load memory from RAM and move it between caches and cores, etc.

Ben Sless10:08:23

This is a very deep subject, so before a deep dive, I'll spoil the conclusion that small arrays might as well be in powers of two

Ben Sless11:08:17

First, memory is loaded in pages. Different operating systems have different page sizes, in my linux PC:

getconf PAGESIZE
4096

Ben Sless11:08:19

> fixed-length contiguous block of https://en.wikipedia.org/wiki/Virtual_memory, described by a single entry in the https://en.wikipedia.org/wiki/Page_table. It is the smallest unit of data for memory management in a virtual memory https://en.wikipedia.org/wiki/Operating_system

Ben Sless11:08:25

The smallest unit of data transfer between caches is a cache line

Ben Sless11:08:11

L1 cache is usually never shared by cores

Ben Sless11:08:58

L2 cache can be shared, sometimes between adjacent cores, depending on architecture and implementation, L3 cache is usually global

Ben Sless11:08:44

So memory is loaded from the RAM in pages of 4096 Bytes

Ben Sless11:08:30

All of this is before getting into the Java memory model

p-himik11:08:03

Just as a guess - a block size of 32 makes sense because it should take 64 bytes on x64?

Ben Sless11:08:52

Haven't found yet how the JVM actually allocates arrays

Ben Sless11:08:14

The array itself is an object and has a header, but then you have the backing array in memory

Ben Sless11:08:03

Since these are dynamically allocated arrays, let's just pretend they're allocated with malloc

Ben Sless11:08:45

so you malloc them, then get back a pointer to the array, when the CPU issues a load op to get the array, you get an entire page

Ben Sless11:08:20

So if the array is aligned in cache and a load will probably return the entire array, you're a happy clam

Ben Sless11:08:30

Here you can see backing by array to create a lazy seq:

private static final int CHUNK_SIZE = 32;
public static ISeq chunkIteratorSeq(final Iterator iter){
    if(iter.hasNext()) {
        return new LazySeq(new AFn() {
            public Object invoke() {
                Object[] arr = new Object[CHUNK_SIZE];
                int n = 0;
                while(iter.hasNext() && n < CHUNK_SIZE)
                    arr[n++] = iter.next();
                return new ChunkedCons(new ArrayChunk(arr, 0, n), chunkIteratorSeq(iter));
            }
        });
    }
    return null;
}

Ben Sless11:08:40

Why do this? It prevents pointer chasing

Ben Sless11:08:58

Each time you load a pointer, it's a potential page load which invalidates your cache

Ben Sless11:08:03

it's terrible for performance

Ben Sless11:08:21

Not to mention these are all objects anyway, so references

Ben Sless11:08:38

That way you at least load the references to memory 32 at a time

Ben Sless11:08:04

And please someone from the core team or who knows Java/CPUs well correct me if I said nonsense

Edward Ciafardini12:08:08

Having trouble sending multiple parameters in the body of a clj-http request. Is this the wrong syntax?

(defn text []
  (try
    (client/post ""
          {:basic-auth ["#######" "######"]
  :multipart [{:name "To" :content "+#######"}
           {:name "From" :content "+########"}
           {:name "Body" :content "test text"}]})
    (catch Exception e {:error e} (println e))))
Gives me the following error:
<TwilioResponse><RestException><Code>21211</Code><Message>The 'To' number +####### is not a valid phone number.</Message><MoreInfo></MoreInfo><Status>400</Status></RestException></TwilioResponse>, :trace-redirects []}

p-himik12:08:15

Seems like it has nothing to do with multipart and instead has everything to do with the phone number itself.

Edward Ciafardini12:08:02

Right - but it works in CURL,

Edward Ciafardini12:08:20

Thought maybe it was an issue with the map

p-himik12:08:00

I use it in the same way, no issues on my end so far. You can try debugging it: https://github.com/dakrone/clj-http#debugging

Edward Ciafardini12:08:48

Looks like a twilio issue - Thanks for confirming correct syntax 🙂

Edward Ciafardini12:08:22

CURL requests are now failing, maybe sent too many reqs while testing

Krishan V18:08:53

Hey everyone, how do I go about with interopt with a jar file? This isn't a java file, so I am not sure how to go about using the java classpaths in that jar.

potetm18:08:57

What are you trying to do with the jar file?

potetm18:08:41

Are you trying to use it as a library for other code, or are you trying to run something from the command line?

Drew Verlee19:08:09

Are you trying to call the java classes from clojure?

Drew Verlee19:08:59

I haven't tried to do that, would putting it on the local repo make it accessable?

Krishan V04:08:59

I am using it as a library but it would be available locally. Not pulled off clojars. Would I have to do something in my project.clj ?@U07S8JGF7

Krishan V04:08:20

@U0DJ4T5U1 Yep! That is what I am trying to do. Thing is I am unsure on where the jar should be located. src ? I am not getting namespace autocompletion either with Cursive so I suspect I am missing out a step here.

wcalderipe06:08:00

@U01V7GEU89J I don't know about lein but you can do it easily with deps.edn (see https://clojure.org/guides/deps_and_cli#local_jar)

Krishan V07:08:20

@UHD67JRL4 Thanks! I was contemplating using polylith over lein for this project. This should work fine then.

👍 4