Fork me on GitHub
#beginners
<
2021-10-07
>
hiredman00:10:43

don't

👍 1
hiredman00:10:50

slurp is for text

hiredman00:10:39

if you want to read binary data into memory the way to do that will depend on what the input is

hiredman00:10:17

if you have an inputstream you can create a ByteArrayOutputStream and then use http://clojure.java.io/copy to copy the input into the output, then get a byte array from the baos

Alex Miller (Clojure team)00:10:21

and what you want it read into, and what you plan to do with it after :)

vlad_poh00:10:19

was trying to quickly pulldown avatars. using service that generates avatars for a given name. was hoping the slurp options would allow something like that. just saw that the implementation uses stringwriter.

Alex Miller (Clojure team)01:10:44

yeah, slurp is for characters, not binary data

Robert Möstl08:10:03

Hello! What's the standard way of updating the CLI tools on Linux? https://clojure.org/guides/getting_started describes how to install them, but not how to upgrade. Should one simply run the installer again? Will the install script clean up outdated artifacts (if there are any)?

Lycheese09:10:44

Did you check whether your Distro's version of Clojure is new enough to have the CLI? If not you could use a second package manager like Nix to manage Clojure updates (nixpkgs has very current Clojure versions).

Robert Möstl09:10:29

Nope. I'm not using the Distro package.

dpsutton09:10:14

i always just reinstall them

1
practicalli-johnny09:10:19

Yes, each Clojure CLI install replaces the previous install. The only thing to delete is the install script itself. Homebrew is also available for Linux and can install Clojure CLI tools. However, I just run the Clojure CLI tools installer when I want to try a new feature. I also update my CI yaml file to match the version of Clojure CLI I installed once I am happy with it.

👍 1
Lycheese08:10:57

Is there a more elegant solution for looping over the keys of a map 2 levels deep than this?

user> (def test-map {:a {"a" {:x 1} "b" {:x 1 :y 2} "c" {:z 3}} :b {"d" {:x 1}}})

user> (for [key (keys test-map)]
        (for [inner-key (keys (key test-map))]
          (prn [key inner-key])))

[:a "a"]
[:a "b"]
[:a "c"]
[:b "d"]
;; => ((nil nil nil) (nil))

delaguardo09:10:39

You can put inner-key into the first for. (for [key ... inner-key (keys (key test-map))] ... )

delaguardo09:10:36

Also in clojure for is not for looping but for list comprehension.

Lycheese09:10:20

What should I use instead in this use case?

delaguardo09:10:43

It depends. What do you want to have at the end?

Lycheese09:10:04

I want to loop over a map and dispatch an update event for each unique combination of key and inner-key, if that makes sense.

Lycheese09:10:45

And there is one specific value for key that I need to handle differently.

Lycheese09:10:00

Should I just use doseq?

delaguardo09:10:24

I would use its combination: for to generate a list then get a new list with only unique items and then doseq to make side effects

(doseq [[key inner-key]
        (distinct (for [key (keys m)
                        inner-key (keys (m key))]
                    [key inner-key]))]
  (dispatch key inner-key))
but doseq can use the same form as for if you don’t need filter out duplicates:
(let [m {:x {:y 1 :z 2}
         :a {:b 3 :c 4}}]
  (doseq [key (keys m)
          inner-key (keys (m key))]
    (prn key inner-key))) 

Lycheese09:10:54

The second one is what I arrived at now as well, but I wouldn't have thought of using for inside doseq, thank you for that insight. Now I just have to figure out why that doesn't work in a reactive context.

Lycheese09:10:04

I surrounded the doseq calls with doall and now it works.

delaguardo09:10:59

doseq is not lazy, no need to wrap in doall

Lycheese09:10:13

I thought so as well

delaguardo09:10:24

could you share the code?

Lycheese09:10:08

ok now it works without weird

Lycheese09:10:19

Thank you for your help 🙂

delaguardo09:10:23

probably something wasn’t evaluated in the same repl context )

quan xing13:10:55

(def
 ^{:arglists '([& items])
   :doc "Creates a new list containing the items."
   :added "1.0"}
  list (. clojure.lang.PersistentList creator))
what's means with ^{:arglists ...

andy.fingerhut13:10:55

When you use defn to define a function, it adds metadata to the Var for you, e.g.:

user=> (defn foo [a b] (+ a b))
#'user/foo
user=> (meta #'foo)
{:arglists ([a b]), :line 1, :column 1, :file "NO_SOURCE_PATH", :name foo, :ns #object[clojure.lang.Namespace 0x6b580b88 "user"]}
user=> (doc foo)
-------------------------
user/foo
([a b])
nil

andy.fingerhut13:10:06

That code you are showing above looks like it comes from core.clj in Clojure's implementation. In that particular case, they are using def to define the Var for the function list. Since they aren't using defn, it won't have some of the function-specific metadata created for it automatically, so instead they are supplying it manually.

dgb2313:10:22

There is also a good reason for not using defn there, it’s defined later in that file.

Robert Elliot14:10:04

This is probably a really dumb question… for reasons of integration with another system / language which would be tedious to go into in depth, it would be very convenient to declare records in the same namespace with a name containing periods, as so:

(ns whatever)

(defrecord foo.Foo [value])
(defrecord bar.Foo [value])
I wasn’t really expecting it to work, thought I would get a syntax error, but actually I got the following: java.lang.IllegalStateException: Foo already refers to: class whatever.foo.Foo in namespace: whatever, compiling:(whatever.clj:4:1) which suggests it’s sort of half working! But somehow the names still clash. Is there a way around this? (I will fully understand a vomit emoji here…)

delaguardo14:10:05

defrecord is a macro and during expansion it adds import like that. So after it processed symbol Foo refer to the symbol from “another” package.

delaguardo14:10:55

you can unmap this symbol from current namespace like this (ns-unmap *ns* 'Foo) but that is slippy road with a lot of hidden bumps

delaguardo14:10:07

(ns whatever)

(defrecord foo.Foo [value])
(ns-unmap *ns* 'Foo)
(defrecord bar.Foo [value])
this code should work

Robert Elliot14:10:55

I see - so I end up with two imports of Foo. Got you, thanks!

Alex Miller (Clojure team)14:10:28

what you're doing here is not supported and behavior is undefined, so don't do that

🆗 1
thanks2 1
DenisMc15:10:51

Hi, I’m trying to figure out how to rename some keys in a map that looks like this : {:top-key “blah” :nested-keys [{:nested-key-1 “blah”][:nested-key-1 “blah”}] I have a function to appropriately rename the keys in the nested maps (datomic->json), and I apply that function to the list using (map #(datomic-json [%] [{:nested-key-1 “blah”][:nested-key-1 “blah”}] This seems to work fine for me when running it in the repl - the map function returns my json with the successfully renamed keywords - but when I run it in my functional tests, instead of getting the json I am getting a response that looks like this: #object[clojure.core$map$fn__5862 0x2c514038 clojure.core$map$fn__5862@2c514038] It looks to me as if my function is not being evaluated for some reason that is beyond my newbie brain at this point. Any pointers would be most welcome, and apologies in advance if my explanation of my problem is difficult to understand.

respatialized15:10:02

`map` produces a lazy sequence, so the object you see is data processing that hasn't happened yet. printing forces the sequence to be realized, which is why it works in the REPL. to actually call the function you're mapping over the sequence, you can either call (into [] (map some-fn some-data) or (mapv some-fn some-data). mapv is eager - using it will most resemble what you expect when you're prototyping in the REPL, and will return a vector.

noisesmith17:10:00

this is incorrect, his result was not lazy

DenisMc15:10:15

Yep, that was it. mapv is doing the trick. Thank you.

noisesmith16:10:22

@denis.mccarthy.kerry when you get object[clojure.core$map$fn__5862 0x2c514038 clojure.core$map$fn__5862@2c514038] that means you called map with only one argument, which instead of processing a list, creates a transducer.

DenisMc17:10:52

Yes that was a problem. I changed it to mapv and figured out that my brackets weren’t indented properly while doing so and when I got them right the thing worked. Must go back again and see if it still works without using mapv…