Fork me on GitHub
#beginners
<
2019-09-27
>
noisesmith00:09:03

oh, I wondered what that offered and it just calls the constructor

papachan01:09:46

Is there something like this to valid a lazy seq? (lazy-seq? (seq (range)))

dpsutton01:09:40

i don't believe so. what problem are you trying to solve? how does laziness impact you?

papachan02:09:52

chunk something?

papachan02:09:03

i dont remember where i saw it

papachan02:09:34

i will try to paste my code

papachan02:09:03

found something like this: user> (instance? clojure.lang.LazySeq (lazy-seq (map inc))) ;; => true

seancorfield02:09:35

@papachan There are a lot of lazy sequences that are different types...

clojure.lang.LongRange
user=> (type (range))
clojure.lang.Iterate
user=>
(but I haven't checked ancestors yet)

seancorfield02:09:23

Neither of those are LazySeq, for example:

user=> (instance? clojure.lang.LazySeq (range 10))
false
user=> (chunked-seq? (range 10))
true
user=> (instance? clojure.lang.LazySeq (range))
false
user=> (chunked-seq? (range))
false
user=>

alexmiller02:09:29

what problem are you trying to solve?

seancorfield02:09:21

(that was my next question 🙂 )

alexmiller02:09:45

sequences are inherently maybe lazy. asking whether it is implies that you care if it isn't, and that's usually a sign that you're doing something fragile or wrong

alexmiller02:09:30

realized? is another predicate in this area but it's fraught with similar perils and is also something I recommend not using

me124307:09:33

Hello! I'm looking for an interactive tutorial of clojure, like something that guides you through the basics. Does anyone know of such a thing? Thanks!

dharrigan07:09:49

Look at the section, Learning Paths

dharrigan07:09:00

Colours and Shapes is interactive

dharrigan07:09:18

as is Clojure Essentials

me124309:09:33

Thanks @dharrigan!

dharrigan09:09:09

You're most welcome! 🙂

dazld09:09:40

(when-let [{:keys [a b c]} {}]
  (prn :ruhroh a b c))

dazld09:09:46

😞 this is a bit of a shame

dazld09:09:15

i’d have hoped it would guard the destructured attributes all to have been non-nil

dazld09:09:36

a b c are all nil in this case

dazld09:09:45

but the prn is still evaluated

alexmiller09:09:21

The when condition is about the map

dazld09:09:48

the right hand side? ok

dazld09:09:43

(when-let [foo (:a {})]
  (prn :got foo))

alexmiller09:09:45

Well I’d say the left hand side, which is fundamentally about a map (and also about its structure)

dazld09:09:57

hah yes, it’s the source

dazld09:09:37

I was thinking about it as the bindings being nil

alexmiller09:09:37

Read it as “when there is a map to destructure, destructure it’s bindings and invoke the body”

dazld10:09:18

thank you that’s helpful

scot-brown10:09:07

If you want to guard against missing keys in a map m, you could do something like

(when-let [{:keys [a b c]} (and 
                                            (every? (fn [k] (some? (get m k)))[:a :b :c])
                                            m)]
  (prn a b c))
Or, if you want to allow explicit nil you could use (contains? m k) instead of (some? (get m k))

alexmiller10:09:47

Wouldn’t just (and a b c) be easier?

scot-brown11:09:23

Definitely an option, but it would be false for something like {:a false :b "foo" :c true}. You could still do (let [...] (when (every? some? [a b c]) ...)) (or (and (some? a) (some? b) (some? c))) so that the binding isn't so big.

scot-brown11:09:37

I always find it tricky to manage false-y vs. nil vs. missing

peterhull9012:09:42

Just been looking at http://chouser.n01se.net/apply-concat/ What would you recommend if you had a sequence of either maps or sequences of maps, and you wanted a sequence of maps?

peterhull9012:09:50

e.g. [{:a 1} [{:a 2} {:a 3}] {:a 4}] and we want ({:a 1} {:a 2} {:a 3} {:a 4}) Flatten seems to be the only correct one here, apply concat and friends all turn the un-nested maps into vectors, ([:a 1] {:a 2} {:a 3} [:a 4])

dpsutton12:09:29

Usually there’s a good way to ensure you’re only getting sequences of maps. Is that possible in your case?

danieleneal12:09:08

(defn splice-when
  [pred]
  (fn [rf]
    (fn
      ([] (rf))
      ([result] (rf result))
      ([result input]
       (if (pred input)
         (reduce rf result input)
         (rf result input))))))

(sequence (splice-when vector?) [{:a 1} [{:b 1} {:c 1}] {:d 1}])

danieleneal12:09:17

A funny way using a transducer

peterhull9012:09:35

I've got a bunch of functions that each return a thing (mostly) but sometimes multiple things and sometimes no things, and I want to collect those things.

danieleneal12:09:11

I think if you sometimes return multiple things, it would make most sense to always return multiple things even if it’s a sequence of one thing (or nil if theres no things)

peterhull9012:09:30

At the moment they return a map or vector of maps or nil. I suppose I could get them to always return a vector of maps (maybe empty) but the commonest case is one map so seems a bit wasteful

peterhull9012:09:57

@danieleneal yeah, you may be right

danieleneal12:09:01

It would make for a cleaner api imo

danieleneal12:09:57

then you can just (sequence cat xs) or (mapcat identity xs) away without a care in the world

peterhull9012:09:26

I'll look into it!

niclasnilsson13:09:08

Does a function like this have a name in functional programming? And does such a function exist in clojure.core and I just haven’t found it?

(defn apply-if
  "Returns a function that applies f if pred returns true for the specified value"
  [pred f]
  (fn [v]
    (if (pred v)
      (f v)
      v)))

jaihindhreddy15:09:14

Not exactly that but related. See cond-> and cond->>

jaihindhreddy15:09:21

In clojure.core

vachichng13:09:39

Hi guys, I have a question , so in OOP world , we have the repository pattern that is responsible to query and save the domain objects , it can be either single object or a graph of them, usually under a ORM to deal with the object relational mismatch or manual mapping. What is the approach in Clojure? I asume that there is nothing like the respository pattern, would then it be , for query load the tables and transform to domain model as clojure maps? and for persistence , transform the domain model map back to sql insert/update using some statement builder ? , that seems to be a lot of manual work.

dharrigan13:09:08

@vachichng I would look at next-jdbc (https://github.com/seancorfield/next-jdbc). In my code, I've just treat things like maps and get and store.

dharrigan13:09:25

It really is quite simple, if you just think of it as maps 🙂

dharrigan13:09:43

An in terms of "work" - I've found it to be refreshingly easier/simplier and more comprehensible than working with an ORM

dharrigan13:09:04

Even in my non-clojure work (Kotlin), I use jooq which is a very simple layer over sql

dharrigan13:09:18

I've abandoned things like hibernate

dharrigan13:09:37

next-jdbc + honeysql gives me all the power and flexibility I need 🙂

vachichng14:09:13

thanks, I will play a bit with next-jdbc + honeysql 🙂

dharrigan14:09:31

you're most welcome

seancorfield15:09:46

@vachichng if you want to dig deeper there are #sql and #honeysql channels

seancorfield15:09:09

But the Clojure way is to use plain data (hash maps) for domain objects / entities and simply read / write them from / to a database. You won't find much support for "relations" for example.

papachan17:09:57

is there a best way for this same result:

(apply str (remove #((set "[]") %) "[abc]"))

noisesmith17:09:21

for one thing, (set "[]") is idiomatically #{\[ \]} imho

noisesmith17:09:42

but using seq operations to go from one string to another is usually a bad idea

schmee17:09:10

(clojure.string/replace "[abc]" #"[\[\]]" "")

papachan17:09:57

yeah pretty nice. i was trying to get this out !

noisesmith17:09:14

also #(s %) for some set s, is just s

noisesmith17:09:22

for all #(f %) you should replace it with f, with the exception of enforcing only one arity being possible via runtime error (which...)

papachan17:09:21

thanks @noisesmith @schmee

csd18:09:31

i'm not sure why (HttpClient.) would need to be cached

csd18:09:49

because of the defonce

ghadi18:09:49

it's about not instantiating the client when the namespace loads

ghadi18:09:01

but rather, when something dereferences the delay

csd18:09:08

so, lazy loading

noisesmith18:09:04

@csd it's helpful to remember that all def forms are evaluated when clojure loads a file, there's no "compile only mode" available

noisesmith18:09:23

so a delay is a simple way to ensure you can load up the code without firing the missiles

noisesmith18:09:52

for example, without the delay, doing aot compilation while making a jar would create a new http client