Fork me on GitHub
#beginners
<
2022-02-13
>
quan xing11:02:15

how to understand function http://clojure.core.cat

teodorlu14:02:37

If you have a list of lists, cat can give you a list. It's a transducer, meaning you can use it with different sequence types using into. Lists, vectors, maps, sets.

teodorlu14:02:22

Perhaps the examples here make sense to you? https://clojuredocs.org/clojure.core/cat

teodorlu14:02:08

First example uses into to create a vector. Second example just creates a sequence.

teodorlu14:02:23

I haven't used it much in practice, perhaps others should chime in too. In case I'm missing / misunderstanding something.

Rodolfo Carvalho16:02:51

I'm trying to understand a little puzzle

user=> ([2 5 9] 4294967296)
2
user=> ([2 5 9] 4294967297)
5
user=> ([2 5 9] 4294967299)
Execution error (IndexOutOfBoundsException) at user/eval461 (REPL:1).
null
Looks like 2^32 triggers some funny behavior with vector indices, what's going on under the hoods?! Why does it sort of "rolls over" and ([2 5 9] 4294967296) behaves like ([2 5 9] 0)?

quoll16:02:44

When you use a vector like this, you’re calling the invoke method on clojure.lang.APersistentVector. This checks if the argument provided is an “integer”, which checks of the data type is one of Integer, Long, BigInt or BigInteger. Your number is a long, which gets boxed into a Long, so the answer is true. At this point, the value is cast to a java.lang.Number and .intValue() is called on it. This truncates to only the bottom 32 bits

💯 3
quoll16:02:04

The resulting int is passed to nth, which is what you’re seeing the result to

quoll16:02:01

You can see it in Java (using jshell):

jshell> ((Number)4294967297L).intValue()
$26 ==> 1

quoll16:02:08

It doesn’t matter what the top bits are, they will be truncated:

jshell> 0xFFFFFFFF00000001L
$32 ==> -4294967295

jshell> ((Number)(-4294967295L)).intValue()
$33 ==> 1

quoll16:02:44

So if I go back to the Clojure repl with that number:

user=> ([2 5 9] -4294967295)
5

Rodolfo Carvalho17:02:27

Wondering if this truncation could lead to bugs in practice, @U051N6TTC do you have any insight on to why truncate vs throw an exception in this case?

quoll17:02:09

This sort of thing shows up a bit since Clojure tries to use long values exclusively, but Java defaults to int in many places (such as array offsets). Clojure’s implementation is done in Java, which is where it shows up. There have been bugs, but they’re relatively rare

Rodolfo Carvalho17:02:56

Hmm that implementation decision also does mean that vectors are limited to a 32bit index space, right?

quoll17:02:25

Well… so are java arrays, so that seems reasonable?

quoll17:02:14

When Java was first released there really weren’t any 64 bit CPUs in use. When Java moved to 64 bit systems it was able to update to the new address space (meaning that individual processes could access more than 2GB) but the specification of Java didn’t change, and it continued to use 32 bit integers for things like arrays

Rodolfo Carvalho17:02:19

I'm not too familiar with Java, coming more recently from Go where arrays are 64bit on 64bit OS arch

Rodolfo Carvalho17:02:23

Today I learned quite a bit, thank you very much!

👍 1
quoll17:02:42

Yes, it’s a bit annoying. I’ve often worked with multi-gigabyte files that get memory mapped. To do this you need to create an array of maps. It works, but it’s a frustrating nuisance

andy.fingerhut18:02:04

I suspect the main reason for the silent truncation vs. exception is performance reasons. While it could cause bugs in some cases, note that it shouldn't cause bugs in at least one common case where you are traversing through consecutive indexes.

quoll19:02:02

In Clojure, traversal through consecutive indexes is likely to be performed via the seq api. Indexing is likely to be via nth. Generally, nth will be called when the code has identified which offset to request, else it runs the risk of IndexOutOfBoundsException. As for checking for the range of the input (as opposed to the bounds check), it is only required for some types, and it’s checking for an index where you are unlikely to ever exceed. Sure, there’s an argument against the consistency of behavior here, but it’s not likely to be a practical concern

Benjamin16:02:52

is there some blog post about what Date class to use? java.time.Instant vs java.util.Date ? My current use case is to say "UtcNow" and "UtcNow" 5 minutes ago in ms.

Benjamin16:02:17

:startTime
              (.toEpochMilli
               (.minusSeconds
                (java.time.Instant/now)
                (* 60 5)))
              :endTime
              (.toEpochMilli
               (java.time.Instant/now))

flowthing16:02:38

Never use java.util.Date if you can avoid it.

kappa 1
☝️ 1
Benjamin16:02:10

I saw a method called SetMonth

flowthing16:02:04

I'm not sure how that is related to your question. 🙂

Benjamin17:02:17

Just agreeing on your judgement - because it seems to be a mutable object and we know what Rich Hickey has to say about that it's just bad

flowthing17:02:04

Oh yes, I see what you mean now. Yes, although that's just one of the problems with java.util.Date (see e.g. https://stackoverflow.com/questions/1969442/whats-wrong-with-java-date-time-api).

👍 1
john2x03:02:26

the deprecation note for clj-time recommends using java.time as well

Benjamin19:02:25

question in thread

Benjamin19:02:30

cognitect.aws (:GetItem (aws/ops dynamodb)) =>

{:name "GetItem",
 ...
 :request
 {:TableName string,
  :Key [:map-of string shape/AttributeValue],
  ...}
 :refs
 #:shape{AttributeValue
         {:L [:seq-of shape/AttributeValue],
          :M [:map-of string shape/AttributeValue],
          :NS [:seq-of string],
          ...}}}
what is the nature of :refs ? just this : #:foo{'fa {}} ?

flowthing19:02:34

You can do (set! *print-namespace-maps* false) to print it the "regular" way (i.e. {:shape/AttributeValue ,,,}) if you prefer.

👍 1
Eric19:02:24

Workflow efficiency question for users of VSCode (& Calva): As I'm typing something like a function definition and my cursor is inside a set of brackets or quotes (the last one was inserted by paredit, I guess) is there a way to move to the next line, jumping out of the brackets/quotes at the same time? I'm trying to avoid having to hit Right Arrow + Enter every time.

Eric19:02:00

(defn foo
  "doc string"
  [n|])

Eric19:02:22

To illustrate, my cursor is the vertical bar after 'n'

Eric19:02:30

I want to end up where the vertical bar is here:

(defn foo
  "doc string"
  [n]
  |)

Eric19:02:27

Is there a key combo or setting that makes that easy?

flowthing20:02:50

The good folks over at #calva will probably be able to give you a better answer, but I think what you're looking for is the "Forward Up Sexp" ParEdit command (https://calva.io/paredit/) followed by a newline (that's kind of the other way around, though, but the end result is the same). I don't know whether you can configure a key binding to run more than one editor command at once in VS Code, though. Maybe there's a plugin for that?

Eric20:02:21

Ah, thank you 🙏:skin-tone-3: I will look into the key binding idea and see if I can map something like Shift+Enter to do it.

Eric20:02:01

You were right—"Forward Up Sexp" is what I wanted. I decided to just map Shift+Enter to that command since it is a useful one even when I don't want to insert a newline and it's easy to add another quick Enter tap.

👍 2
Leon20:02:52

Hey Guys, my Calva seems not to be working as expected, I am only getting the blue highlights. I am missing the gold ones. I have uninstalled and then installed but still