Fork me on GitHub

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

👍 3

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


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

👍 3

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:


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

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


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.


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.


That prints Incrementing: 1 upto Incrementing: 32


although I've only asked for 3 items.


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


I believe lazy seqs are chunked (in batches of 32) by default, see e.g.


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


don't count on chunking or the lack of chunking


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


although, 32 is not a magic number. There is a good article explaining why 32 -

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


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


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

Ben Sless11:08:19

> fixed-length contiguous block of, described by a single entry in the It is the smallest unit of data for memory management in a virtual memory

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


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++] =;
                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 []
    (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 []}


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


I use it in the same way, no issues on my end so far. You can try debugging it:

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.


What are you trying to do with the jar file?


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.


@U01V7GEU89J I don't know about lein but you can do it easily with deps.edn (see

Krishan V07:08:20

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

👍 4