clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
2020-11-02T02:41:57.018600Z

Hey guys, I got two questions first would be, what would be a better way of writing this?? (into {} (map (fn [x] (hash-map x (hash-map "booked?" (random-boolean) "nameOfEvent" "nothingBookedYet"))) (get-next-4-weeks-dates))) it would get assigned to a def and returns something like {2020-11-07 {nameOfEvent nothingBookedYet, booked? true} 2020-12-07 {nameOfEvent nothingBookedYet, booked? false} ... } (get-next-4-weeks-dates) returns vector of dates as strings ex ["2020-11-01" ...] second, is how could I filter all trues so that it returns all trues with date aswell 11/01/20 {nameOfEvent nothingBookedYet booked? true}

dominicm 2020-11-02T12:25:11.023200Z

I'd reach for zipmap:

(zipmap (get-next...) (repeatedly (fn [] {:booked ...})))
(On mobile, so abbreviated)

2020-11-02T16:57:45.035500Z

Ill try zipmap aswell, thank you

2020-11-02T22:51:31.052500Z

Macro? Oh you mean ->>?

2020-11-02T22:52:09.052700Z

With the reduce way, you can even just skip doing the assoc when random-boolean isn't true, so it can filter and create the map on one go.

2020-11-02T23:10:41.052900Z

Is ->> not a macro? Eventually a user will select a date and flip booked to opposite boolean. I appreciate the different approach though.

2020-11-03T03:00:44.057700Z

It is, but, you've definitly been using macros without realizing, things like if, or, and, defn and more are all macros as well

2020-11-03T03:01:17.057900Z

You might just not have been defining your own macros yet

2020-11-03T15:52:12.067800Z

I just haven't really looked into it. Last time I did the syntax and how it worked looked advanced so I backed off.

2020-11-03T17:39:44.068800Z

Ya fair enough, it is a little more advanced, I remember I took a bit of time before learning to use it as well when I started

👍 1
phronmophobic 2020-11-02T03:01:03.018800Z

maybe something like:

(defn get-next-4-weeks-dates []
  ["2020-11-01" "2020-11-07"  "2020-11-14" "2020-11-21" ])

(def date->event
  (into {}
        (map (fn [dt]
               {dt {"booked?" (rand-nth [true false])
                   "nameOfEvent" "nothingBookedYet"}}))
        (get-next-4-weeks-dates)))

(def booked-events
  (filter (fn [[dt {:strs [booked?]}]]
            booked?)
          date->event))

alexmiller 2020-11-02T03:01:31.019Z

served off of github so ... ¯\(ツ)

2020-11-02T03:02:38.019300Z

Thank you, ill give that a shot

2020-11-02T05:23:20.020100Z

You can use reduce instead:

(reduce
  (fn[acc e]
    (assoc acc e
               {:booked? (random-boolean)
                :name-of-event :nothing-booked-yet}))
    {}
  (get-next-4-weeks-dates))

2020-11-02T05:27:53.020300Z

Or just using map literals instead of hash-map already reads a lot better:

(->> (get-next-4-weeks-dates)
     (map
       (fn[x]
         {x {:booked? true
             :name-of-event :nothing-booked-yet}}))
     (into {}))

2020-11-02T07:30:37.020500Z

I havent uaed a macro before, ill check it out.

valerauko 2020-11-02T09:15:52.021600Z

Could someone please point me to where Clojure's memory model is implemented? The part where differences are branched off

suren 2020-11-02T10:25:27.022400Z

I am trying to deploy a package in clojars . I am getting following error

java.lang.IllegalArgumentException: Must provide valid :files to deploy-artifacts
Can anyone help me with this?

dharrigan 2020-11-02T10:26:57.022900Z

@suren try asking in the #clojars channel. Someone may be able to help there. 🙂

suren 2020-11-02T10:28:25.023100Z

@dharrigan thanks buddy

2020-11-02T13:37:17.024900Z

Do you mean where path copying is implemented for collections that you are updating, so that they return a new collection instead of modifying the one they are given?

2020-11-02T13:37:34.025700Z

If you mean something else, it is not clear from your question

alexmiller 2020-11-02T14:17:04.026Z

Clojure's memory model is Java's memory model since it runs on the jvm

valerauko 2020-11-02T14:50:44.026300Z

I mean the path copying as you say

alexmiller 2020-11-02T14:53:16.026500Z

look at the source for https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentHashMap.java then

alexmiller 2020-11-02T14:54:46.026800Z

based on Bagwell's HAMT http://infoscience.epfl.ch/record/64398/files/idealhashtrees.pdf (with some mods for performance)

mafcocinco 2020-11-02T15:29:12.029100Z

Is there currently a “best” Clojure SFTP client library? “Best” is kind of squishy but something that is relatively well maintained and provides good examples. I was thinking https://github.com/clj-commons/clj-ssh but its tests are currently failing and it is somewhat lacking in examples (was looking specifically for a put example from an in-memory file).

2020-11-02T15:42:19.031800Z

We’re suddenly having production issues with org.httpkit.client throwing java.lang.IllegalStateException: Client/Server mode has not yet been set whenever we try to connect to one of our other servers over https. The only thing that’s changed since last Friday when everything was fine is that Daylight Savings Time ended over the weekend. Java version is 1.8 (and not Java 11, which seems to have had a lot of issues with this). It’s a long shot, but has anyone else ever seen a problem like this?

borkdude 2020-11-02T15:51:04.032100Z

@mafcocinco We use this one: https://github.com/miner/clj-ftp

mafcocinco 2020-11-02T15:52:34.032400Z

Thanks! The documentation implies that it is FTP only. Does it work with SFTP connection?

borkdude 2020-11-02T15:52:53.032600Z

yes, it does

mafcocinco 2020-11-02T15:53:09.032800Z

awesome, thanks!

borkdude 2020-11-02T15:53:11.033Z

I even made a little PR related to that, to that lib

dpsutton 2020-11-02T16:04:23.034100Z

take-while as a transducer "takes while" the input satisfies some predicate. easy enough to write but is there a transducer that "takes while" the accumulated value satisfies some predicate?

dpsutton 2020-11-02T16:05:21.034300Z

(defn foo [rf finish?]
  (fn
    ([] (rf))
    ([result] (rf result))
    ([result input] (let [result' (rf result input)]
                      (if (finish? result')
                        (reduced result')
                        result')))))

dpsutton 2020-11-02T16:06:16.034800Z

built-in or possibly in cgrande's lib?

borkdude 2020-11-02T16:13:03.034900Z

@mafcocinco You actually gave me an idea :) https://github.com/borkdude/babashka.curl/issues/27

mafcocinco 2020-11-02T16:13:29.035300Z

sweet!

2020-11-02T19:40:08.036100Z

it isn't really safe for transducers to make assumptions about result

dpsutton 2020-11-02T19:43:32.037200Z

do you know of a concrete example that can help clarify for me?

phronmophobic 2020-11-02T19:44:52.038800Z

@dpsutton, why not just use the built in take-while ?

(defn take-while
  "Returns a lazy sequence of successive items from coll while
  (pred item) returns logical true. pred must be free of side-effects.
  Returns a transducer when no collection is provided."
  {:added "1.0"
   :static true}
  ([pred]
     (fn [rf]
       (fn
         ([] (rf))
         ([result] (rf result))
         ([result input]
            (if (pred input)
              (rf result input)
              (reduced result))))))
  ([pred coll]
   (lazy-seq
    (when-let [s (seq coll)]
      (when (pred (first s))
        (cons (first s) (take-while pred (rest s))))))))

Jan K 2020-11-02T19:45:03.039100Z

I agree with hiredman, this is something out of scope for an individual transducer (imagine if it's attached to a channel, what's the accumulator value?). But I guess you could use clojure.core/reductions and wrap the reducing function manually with some transducers if needed, and then take-while the resulting sequence.

2020-11-02T19:45:08.039400Z

transduce calls (f) before applying the xform to f, so you cannot assume result is the value returned by your step fn's init arity

dpsutton 2020-11-02T19:45:58.040300Z

@smith.adriane because no inputs are bad. its when i've taken "enough" inputs that i can stop

dpsutton 2020-11-02T19:48:10.042500Z

something like (reduce (reduce-until + #(> % 100)) (range 300))

phronmophobic 2020-11-02T19:48:53.043300Z

the accumulator could be anything. it seems like you may want to write your own transducible process if you want to make assumptions about the accumulator value

dpsutton 2020-11-02T19:49:39.044100Z

i don't follow. using a reducing function assumes i know something about the accumulator shape.

dpsutton 2020-11-02T19:50:19.045Z

(fn [acc input] ...) if acc is completely opaque then i could never reduce anything

phronmophobic 2020-11-02T19:51:13.046200Z

the transducer (map f) can work when the accumulator is a core/async channel, a clojure sequence, a socket connection, standard out, outputstream, and many other accumulator types. not sure how your take-while would work with all those examples

2020-11-02T19:55:04.046700Z

(defn part [n]
  (fn [retf]
    (fn
      ([] {:value (retf)
           :part []})
      ([{:keys [value part]}]
       (if (seq part)
         (retf (retf value part))
         (retf value)))
      ([{:keys [value part]} item]
       (let [new-part (conj part item)]
         (if (= (count new-part) n)
           {:value (retf value new-part) :part []}
           {:value value :part new-part}))))))
#'user/part
user=>
user=> (let [f ((part 2) conj)] (f (reduce f (f) (range 10))))
[[0 1] [2 3] [4 5] [6 7] [8 9]]
user=> (transduce (part 2) conj (range 10))
([8 9] [6 7] [4 5] [2 3] (1 0))
user=> (into [] (part 2) (range 10))
Execution error (NullPointerException) at user/part$fn$fn (REPL:13).
Cannot invoke "clojure.lang.ITransientCollection.conj(Object)" because "coll" is null
user=>

2020-11-02T19:55:53.047400Z

part there is a kind of naive purely functional transducer that wraps the input result to keep a buffer, and unwraps it at the end

2020-11-02T19:57:04.048300Z

and if you sort of manually do the things when you use it with reduce, it works, but in a "real" usage with a function that takes a transducer it doesn't

2020-11-02T19:58:31.049100Z

it almost sort of works in that example with transduce, but will completely fall apart with different types and reducing functions

2020-11-02T20:00:59.049700Z

result is opaque, the only operation you can safely do on it is call rf

dpsutton 2020-11-02T20:01:09.050Z

thanks everyone

dpsutton 2020-11-02T20:01:19.050400Z

i see

2020-11-02T20:01:39.051Z

if you need to keep a count then you need to keep it in an atom closed over by your reducing function, similar to how the stateful transducers work

2020-11-02T20:08:13.052300Z

https://groups.google.com/g/clojure/c/HK9LkmlRyjY/m/StlzdHxaCwAJ might be the mailing list thread

j 2020-11-02T23:32:38.053100Z