Fork me on GitHub
#beginners
<
2022-04-05
>
Alen01:04:03

Are threading macros idiomatic in clojure? Stuff like (A)

(-> foo
    fn1
    first
    :bar
    .getName)
or are nested calls preferred? (B)
(.getName
  (:bar
    (first
      (fn1 foo))))

🅰️ 8
🅱️ 1
seancorfield01:04:39

I'd say they are definitely idiomatic but they can be overused and sometimes it can be clearer to name parts of an expression via let rather than either of those two forms. If (fn1 foo) returns a pair (or a sequence) and you're ignoring the second (or all subsequent) element(s), it might be clearer to call that out in a let for example:

(let [[data & _] (fn1 foo)]
  (.getName (:bar data)))
It's going to depend on context and what's important about the navigation through the data.

Alen01:04:15

interesting point about destructuring to avoid first 👍

icemanmelting14:04:29

I think that threading macros should be preferred over nested calls. Specially if each step/function called are well named and therefore you end up with a smal “story” of what is happening to the data like so:

(-> data
    extract-date
    addDay
    to-date)

icemanmelting14:04:21

That is the kind of code I try to build every single time I use Clojure 😉

manas_marthi01:04:01

Hi All, I am looking at Apache storm code that has clojure code within maven project. How to repl into a maven project?

Muhammad Hamza Chippa09:04:11

Hi guys I am having some problem in returning multi line string from the function. The code look something like this, how can I return it ?

(defn svg2pdf []
  (str "q")
  (str "1 0 0 1 29.5 30.5 cm")
  (str "q")
  (str "Q")
  (str "Q"))
It is returning only q how can I make the function returning something like this
q
1 0 0 1 29.5 30.5 cm
q
Q
Q 

Stuart09:04:59

your function will only return the last expression evaluated. Which in your case is (str "Q")

Stuart09:04:06

You need something like

(defn svg2pdf [svg-root-element target-box]
  (str "q\n"
       "1 0 0 1 29.5 30.5 cm\n"
       "q\n"
       "Q\n"
       "Q"))
Or however you want to return it in one expression / build your string.

Muhammad Hamza Chippa09:04:07

it is working fine in console log but when I am rendering it in [:p ] I am getting it in one line

Martin Půda09:04:51

(defn svg2pdf [svg-root-element target-box]
  (clojure.string/join "\n"
    ["q"
     "1 0 0 1 29.5 30.5 cm"
     "q"
     "Q"
     "Q"]))

☝️ 1
🙌 1
pavlosmelissinos10:04:13

@U02DQ45FQF9 Do you understand why your original solution didn't work?

Muhammad Hamza Chippa10:04:25

@UEQPKG7HQ yeah now it makes sense

👍 1
oddsor08:04:34

Clojure-strings can also be multi-line! But the other suggestions are better for preserve indentation:

(defn svg2pdf []
  (str "q
1 0 0 1 29.5 30.5 cm
q
Q
Q"))

theequalizer7313:04:56

Hi, Given a string "2022-03-31T21:35:35Z" which represents a date-time in UTC, I’d like to parse it as a local time given a zone-id like -06:00. The expected result should be "2022-03-31T15:35:35-06:00" I’ve tried with clojure.java-time but don’t know how to do it. Any thoughts? :thinking_face:

Martin Půda13:04:37

(OffsetDateTime/of
  (LocalDateTime/parse
    "2022-03-31T21:35:35Z"
    (DateTimeFormatter/ofPattern "yyyy-MM-dd'T'HH:mm:ssz"))
  (ZoneOffset/of "-06:00"))

1
R.A. Porter13:04:39

(let [in-df  (java.text.SimpleDateFormat. "yyyy-MM-dd'T'hh:mm:ss'Z'")
        out-df (java.text.SimpleDateFormat. "yyyy-MM-dd'T'hh:mm:ssZ")]
    (->> "2022-03-31T21:35:35Z"
         (.parse in-df)
         (.format out-df)))
That'll come up in your local tz.

1
theequalizer7313:04:45

Thank you my friends!

theequalizer7314:04:10

Im not sure if that’s what I needed. Because the result is always showing the same hour 21 and it should be 15

R.A. Porter14:04:19

If you don't just want your local time and need to specify zone, then using my approach, you'd need to set the TZ on the out formatter. You'd be best served by using an official name for the TZ to create it, but this hard-coded -6 hours works:

(let [in-df  (doto (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ss'Z'")
                 (.setTimeZone (java.util.TimeZone/getTimeZone "UTC")))
        out-df (doto (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ssZ")
                 (.setTimeZone (java.util.TimeZone/getTimeZone (java.time.ZoneOffset/ofHours -6))))]
    (->> "2022-03-31T21:35:35Z"
         (.parse in-df)
         (.format out-df)))
(N.B. that I fixed my formatter strings to use the correct 24-hour values instead of lower-case 'h')

1
theequalizer7315:04:23

If I use (java.time.ZoneOffset/of zone-id) where zone-id is a string “-06:00” I’m getting the expected result.

dharrigan13:04:17

Is this #^bytes b still okay to use as a byte array type hint, or is a different approach recommended thesedays?

dharrigan13:04:26

(for Clojure 1.10.3 and above)

ghadi13:04:59

#^ is the old syntax for typehints. Use ^bytes

Alex Miller (Clojure team)13:04:42

don't place it on vars (will be evaluated), put it on the arglist. no changes in this area.

dharrigan13:04:56

(for context, I'm reviewing some old code)

dharrigan13:04:44

so, for an arglist, both [^bytes b] and [#^bytes b] are okay?

ghadi13:04:51

they're equivalent, but the former is the way to do it these days

dharrigan14:04:01

thank you 🙂

ghadi14:04:02

you must be reviewing some super old code

ghadi14:04:11

haven't seen that syntax in a while

dharrigan14:04:26

That's what struck me as a bit odd, I'm used to seeing ^bytes etc.., never seen #^bytes before, so a bit of googling revealed an old article.