Fork me on GitHub
#beginners
<
2018-05-28
>
johnj00:05:50

Is there a built-in function like every? that instead of returning false when the predicate fails returns the item in the collection ?

johnj00:05:07

I'll cook my own

johnj00:05:18

hmm, take-while my ease it

_rj_r_01:05:10

so I'm working through 4Clojure at the moment, and am starting to wonder which is the best way as far as readability vs performance vs <insert whatever else here>.... obviously there is a bunch of ways to do the same thing.... but I'm not sure which ways are overall better (used a bit loosely here)? For instance, on the duplicate a sequence problem.... My solution is #(reduce (fn [res el] (into res [el el])) [] %)

dorab01:05:38

@lockdown- You could try some but with the complement predicate.

_rj_r_01:05:51

but there are so many others like #(interleave % %) and (mapcat #(list % %))

noisesmith01:05:04

you can replace (fn [res el] (into res [el el])) with (fn [res el] (conj res el el))

_rj_r_01:05:36

I feel like I'm about to embark down a rabbit hole haha....

noisesmith01:05:38

the mapcat one doesn't work quite like that (that's an uncalled transducer) but is likely the most straightforward solution

sundarj01:05:45

i think using repeat instead of list conveys the intent better

_rj_r_02:05:45

@noisesmith I am assuming conj is better here because I am just adding to the end of the vector? ... would into be better if I was using a list or a map data structure?

noisesmith02:05:08

into is a reduce that calls conj

noisesmith02:05:17

so using conj directly is simpler

_rj_r_02:05:51

ah... gotcha... thx!

noisesmith02:05:23

and into is better if you are eagerly filling one collection from another (with optional transformation as you consume the items)

_rj_r_02:05:50

as in going from a list to a set for example?

noisesmith02:05:06

here's a version using into properly (won't work on 4clojure's clojure version) (into [] (mapcat (fn [e] [e e])) coll)

noisesmith02:05:50

or for combining two collections, or altering a collection as you use it to fill a specific collection type

noisesmith02:05:41

that mapcat doesn't get used on the collection, it's a transducer that into uses instead

_rj_r_02:05:47

I'll have to stare at that awhile lol

noisesmith02:05:08

+user=> (def m (mapcat (fn [e] [e e])))
#'user/m
+user=> (into [] m [1 2 3 4])
[1 1 2 2 3 3 4 4]

noisesmith02:05:15

when you don't give mapcat a collection, it returns a transducing function. when you provide an extra arg to into before the last arg, it uses it as a transducing function to transform its input

_rj_r_02:05:37

I'm getting how it is working.. I'm not getting how it is a correct use of into since I am guessing I am at a point where I am not sure what is correct when/where when it comes to Clojure

noisesmith02:05:13

I could rephrase that - it's a case where into is better than alternatives

noisesmith02:05:28

your usage of into inside reduce was just an obfuscated conj

noisesmith02:05:27

or more simply, don't create a collection just to pass it as the last arg to into, there's always a better alternative

_rj_r_02:05:17

ah.. I see what you're saying... I'll have to think that through a bit when I'm working through problems... but that makes sense

noisesmith02:05:49

the reasons to use into with a mapcat transducer instead of mapcat directly are in case you know you are using the data eagerly and want better performance, or if it clarifies / simplifies code to be able to describe the transducing function separately from the rest

johnj02:05:38

in clojure's speak is a map refer as a collection too?

noisesmith02:05:01

map the function and map the collection are two different things

noisesmith02:05:18

we can disambiguate by calling the collection a hashmap

johnj02:05:45

ok, was referring to map the data structure

noisesmith02:05:01

both describe something related to mapping from items of one domain from items to another, and for historical reasons they both get called "map"

_rj_r_02:05:06

and they both can be used as functions... so that's fun

noisesmith02:05:09

into is frequently used with hash-maps because the basic collection operations mostly return lazy-seqs, and into is an easy way to get a hash-map back

johnj02:05:15

for example, in Java, maps are not part of the collection interface, it has its own

noisesmith02:05:15

that's true in clojure as well

+user=> (instance? java.util.Collection (java.util.HashMap.))
false
+user=> (instance? java.util.Collection {})
false
+user=> (instance? java.util.Map {})
true

noisesmith02:05:17

but java "Collection" is overly specific, basic cs tells us that hash-maps and queues and trees are all collections

johnj02:05:15

got it, was wondering how it was used in clojure "speak" πŸ˜‰ cause of java

noisesmith02:05:41

+user=> (coll? {})
true

noisesmith02:05:23

coll? gets a little closer to our idea of what a "collection" is, but only for clojurey things sadly

noisesmith02:05:32

+user=> (coll? (java.util.HashMap.))
false

johnj02:05:52

nice, I need to look more at the cheatsheet

johnj02:05:44

re your into hash-maps, the same applies for vectors no?

noisesmith02:05:58

sure, or sets etc.

πŸ‘ 4
seancorfield02:05:03

And re: @sundarj’s comment about using repeat to clarify the intent:

(into [] (mapcat (partial repeat 2)) [1 2 3 4])

seancorfield02:05:53

or

(into [] (mapcat #(repeat 2 %)) [1 2 3 4])
if you prefer anonymous functions over partial.

seancorfield02:05:22

(and I agree that expresses the intent better than (fn [e] [e e]) in my opinion)

devn02:05:20

I like (fn [e] [e e]) more, but what do I know?

devn02:05:25

Eh, I like both for different reasons. logs off

πŸ™‚ 4
seancorfield02:05:15

I don't know which would be considered more idiomatic. My preference is entirely subject. Another option would be #(vector % %) which some people may prefer.

_rj_r_03:05:44

crazy how many ways there truly are to do something.. still trying to wrap my head around that.... I feel that Haskell had a more clear path to solutions (trying to at least compare functional languages here even though they really are way too different to compare)

ScArcher05:05:33

If I'm calling a function and would like to conj two values from the result of that function into a map, then return it, what's the best way to do that?

ScArcher05:05:58

should i use a let to reference the return value, then do two conj's ?

seancorfield05:05:34

@scott.archer If you're using clj-http you could have it parse the JSON response automatically, so you'd get back a hash map with keywords as keys -- that would make your code easier.

seancorfield05:05:51

As it above, you could add a new binding in the let:

body (parse-string (:body response))
and then you wouldn't be calling parse-string twice.

seancorfield05:05:54

Instead conj, I'd probably use assoc:

(assoc my-site-info :token  (body "access_token") :ttl (body "expires_in"))

seancorfield05:05:07

(assuming the additional let binding above)

ScArcher05:05:27

@seancorfield Thanks, I caught the two calls to parse-string. I am using clj-http, so I'll see about having it parse the JSON.

seancorfield05:05:42

I also find it's easier, with clj-http, to specify :throw-exceptions false and check the :status in the result rather than letting it throw.

πŸ‘ 4
ScArcher06:05:18

Thanks again, i'm new and muddling my way through it. I'm decent at getting stuff working, but I want to learn the right way to do things.

seancorfield06:05:31

Learning all the idioms takes the longest time. I've been doing Clojure in production for seven years now and I'm learning new stuff all the time!

KAY_YAK07:05:03

Hi, I am getting null pointer exception. Can anybody explain why?

(loop [a 0]
  ((println "*** Sales Menu ***")
  (println "------------------")
  (inc a))
  (if (= a 0)
    (recur a)))

delaguardo07:05:19

First println returns nil and you are trying to use that nil as a function.

KAY_YAK07:05:48

How do I avoid that? using a do ?

delaguardo07:05:59

Unwrapping println and Inc expressions should help you. But be aware of immutable nature of clojure. (inc a) doesn't change the value of a

delaguardo07:05:06

loop body executed with implicit do already. No need to add extra do

KAY_YAK07:05:50

but if I put inc a inside recur does it get muted?

delaguardo07:05:34

No. inc returns new value and never change a var. If you the result from it try to use let.

delaguardo07:05:09

Describe what you want aa suggested in that channel and community will try to explain how to do that)

seancorfield07:05:07

@kushalkanungo1991 Also, you are evaluating (inc a) but essentially throwing the value away. Perhaps if you explain what you're trying to do, maybe we can help guide you to a functional solution?

KAY_YAK07:05:42

I am just trying to make an infinite loop and break it on a condition. I saw this example

(loop [accum []
       i     1]
  (if (= i 10)
    accum
    (recur (conj accum i)
           (inc i))))
;; β‡’ [1 2 3 4 5 6 7 8 9]
and was following it.

jumar07:05:10

There may be better ways how to do this but it seems you're just trying to learn how loop-recur works. As you see, in your snippet you're anot passing (inc a) to recur but just a which is incorrect. You should use (recur (inc a)) as you see in the snippet you've just posted. This way, the new incremented value of a (original a is unchanged!) is passed to the loop and symbol a is rebound to this value.

KAY_YAK07:05:10

I am just trying to make an infinite loop and break it on a condition. I saw this example

(loop [accum []
       i     1]
  (if (= i 10)
    accum
    (recur (conj accum i)
           (inc i))))
;; β‡’ [1 2 3 4 5 6 7 8 9]
and was following it.

Karol WΓ³jcik08:05:03

Hi is there a way to destruct the sequence in place sth like (hash-map (desctruct vec1) (destruct vec2))?

noisesmith14:05:09

what do you expect the input and output to look like here? I doubt that destructure is what you are looking for - it's a helper for making binding forms in macros

jherrlin10:05:57

Hey, I am in a project with Clojure and ClojureScript. I am running lein, Emacs, Cider and Weasel (Browser-connected ClojureScript REPL) on a GNU/Linux system. I am trying to wrap my head around how Cider is working in this environment and how to use the 2 REPLs. When i navigate to the project in Emacs and use M-x cider-jack-in-clojurescript it starts a new process on the system: clojure.main -m leiningen.core.main update-in :dependencies conj [org.clojure/tools.nrepl "0.2.13" :exclusions [org.clojure/clojure]] -- update-in :plugins conj [cider/cider-nrepl "0.17.0"] -- repl :headless :host :: and gives me 2 buffers that's connected to REPLs. But i dont know if on or the other is connected to a ClojureScript REPL or a Clojure REPL. How can i know? If I eval a sexp from a file buffer, how can i know to what REPL the sexp is sent?

grierson10:05:52

Are there any examples of component and compjure? I’m not sure how to structure my app with stateful components. In C# my IOC container would just inject everything automatically.

curlyfry11:05:59

@grierson Perhaps this section in the component readme helps? https://github.com/stuartsierra/component#web-applications should be pretty close to how it's done in compojure

grierson11:05:03

@curlyfry would the β€˜app’ be a map with keys for database, email, and other stateful components? Then just (:database component) inside my handler?

curlyfry11:05:51

I actually don't use Component (I prefer Integrant, which has pretty much the same use case but works a bit different) πŸ™‚ But the 'app' is called a 'system' in component, and is a map from keywords labeling the components to instances of components https://github.com/stuartsierra/component#systems

curlyfry11:05:09

My advice is to study the readme, it's quite extensive!

curlyfry11:05:59

I'm not entirely sure, better if someone who actually knows Component takes over!

curlyfry11:05:02

Or the readme πŸ˜‰

soulflyer11:05:25

@jherrlin Did you try doing cider-repl-set-ns from the file in question? You can see the prompt change so you will know which repl will do the work. As far as I can tell it's just a simple case of anything from a .cljs file goes to the clojurescript repl and anything from a clj file goes to the clojure repl. I don't know the full details, but in my limited experience it works like that.

jherrlin12:05:46

@soulflyer havent seen cider-repl-set-ns but will look into that! Thx! πŸ™‚

πŸ‘ 4
lepistane13:05:50

hi guys i am trying to simulate movement on google maps of multiple entities in parallel i do this by having this

(defn start-mockup
  "travel time has minimal of 30 sec and max of 151 per bus-stop
  1 sec = 1000"
  []
  (let [root (io/file "resources/routes")
        files (rest (file-seq root))
        _ (println "Num. files: "(count files))]
    (doseq [file files]
      (let [data (read-string (slurp file))]
        (future
          (doseq [c (:coords data)]
            (let [travel-time (int (* 100000 (+ 0.03 (rand 0.121))))
                  _ (println "travel-time:" (int (/ travel-time 1000)) " sec")]
              (println "name" (:name data) ", coords: " c)
              (Thread/sleep travel-time)
              (client/post  ""
                            {:body
                             (json/generate-string
                              {:bus-line (:name data)
                               :current-lat (:lat c)
                               :current-long (:long c)})}))))))))
right now once the route finishes (there are no more coordinates) future stops and there is no more entity i'd like to have circular behavior. Once bus goes from A-B (finishes it's route (no more coords)) to generate now one or start new future function i was playing little bit with (while true) with promise and delivery but i am not sure if that is right way of thinking?

Russ Olsen14:05:57

So if I understand your question, you are trying to get the code inside of the future to run more or less forever?

Russ Olsen18:05:52

Ok then I see where you are going with the future but it's kind of an odd way of using a future, which mostly exists to compute a future value. Stylistically I'd put the the body of the future in a separate function, so that it's easier to see what is going in an out of the code. To answer your question, you could do the repeat with either a while or a loop/recur. I'd also think about getting rid of the future. Perhaps replace it with a plain old Thread if there aren't too many of them.

lepistane19:05:49

i couldnt make it work with while/loop but i will hack my way into it tnx for the feedback about the function there are about 150 futures soo 150 threads and since my laptop has 4 ... it's quite a lot in my mind

ScArcher14:05:51

Can anyone point me to a "production" example of using clj-http to consume a REST API?

ScArcher14:05:10

I've got mine working, but I'd like to see what robust error handling looks like in a real implementation.

ScArcher21:05:00

Thanks for the response! It looks like most of these check for a 200, then move on. Thanks again!

noisesmith16:05:48

on line 9 you put a vector in parens

johnj16:05:54

forgot the quote heh

noisesmith16:05:55

that means you are calling it

πŸ‘ 4
johnj16:05:02

facepalms

noisesmith16:05:22

you don't even need parens there, you can use []

johnj16:05:53

is the result of another fn, a seq of vectors

noisesmith16:05:16

then call seq on it

noisesmith16:05:23

but reduce does that already

noisesmith16:05:50

I wish examples would stop using '(...) because it's pretty much always worse than using []

johnj16:05:57

ok, what I meant is that the coll passed to reduce is a seq of vectors from a function call

johnj16:05:10

but noted

noisesmith16:05:16

right, but if you need to emulate it being a seq, you can call seq on a vector

johnj16:05:23

seen results as seqs sometimes confuses me with lists

noisesmith16:05:38

but that is pretty much never needed (eg. reduce calls seq on its vector arg anyway)

noisesmith16:05:04

a list is a kind of seq, but clojure functions that take seqs can turn a lot of things into seqs

johnj16:05:27

so I think I'm getting a list but its a seq and run a test with a list with not quote πŸ˜‰

johnj16:05:39

yeah better to user more [] or call seq

noisesmith16:05:55

my point is, to test something that takes a sequential collection, use a vector literal

johnj16:05:46

but is there anything really wrong with '(1 2 3) ?

noisesmith16:05:44

it's error prone in a way that [1 2 3] is not

noisesmith16:05:01

you could forget the ', or try to put forms in that should be evaluated

noisesmith16:05:51

and the set of places where '(1 2 3) is right and [1 2 3] is wrong are very small, and fixable by a call to seq

πŸ‘ 4
johnj16:05:49

reduce hard lesson of the day, make sure the result of the first iteration can be used in subsequent iteraions πŸ˜‰

Alex Miller (Clojure team)17:05:55

It’s a good habit to just always supply the initial value

sova-soars-the-sora17:05:38

I want to read a string from the user, it has some numbers and some strings, I'd like to use edn reader, any pointers?

joshkh18:05:32

i need to pass a java File object to some constructor. everything works fine when i execute my uberjar locally: (io/file (io/resource "mykey.pem")) where the file is in /resources/mykey.pem, but when i deploy the uberjar to AWS ECS i get an exception saying mykey.pem is not a file or directory. i get closer if i use io/input-stream and can slurp the contents once deployed.. but is it possible to convert a buffered input steam to a File object?

sova-soars-the-sora18:05:01

@joshkh so you need to include an additional file when packing an uberjar? it has been a long time since i did this ... let me do some research

joshkh18:05:07

thanks, sova. the thing is the file is definitely in the jar. i've extracted it and looked. so it's more of a problem with getting a File handle on it.

sova-soars-the-sora18:05:56

do you need (io/file) ?

sova-soars-the-sora18:05:00

maybe you can use just io/resource

joshkh18:05:34

i definitely need a File object. (io/input-stream "mykey.pem") returns a valid BufferedInputStream

joshkh18:05:03

but the constructor of this java class expects a File. my lack of java skills are showing. πŸ˜‰

joshkh18:05:21

(io/resource) works as well. it returns a URL.

sova-soars-the-sora18:05:26

Well, i just read this: If you need to slurp a file from a JAR file, don't call io/file on the result of calling io/resource, or you will get an exception that says the resource is "not a file". Instead, call slurp directly on the result of io/resource.

joshkh18:05:02

yup! saw that too! but slurp reads it into a string.

sova-soars-the-sora18:05:55

Aha, there is also If you need to copy a binary file from a running JAR (or WAR), don't call slurp as it will try and decode the file. Instead, extract similarily to:

(with-open [in (io/input-stream (io/resource "file.dat"))] ;; resources/file.dat
    (io/copy in (io/file "/path/to/extract/file.dat"))))

joshkh18:05:44

oh, nice one! i'll give it a go.

joshkh19:05:37

@sova thanks. that did the trick!

4
errob3719:05:11

Hi everyone, Is somebody can help me here with instrumenting with deftype. All detail are here : https://stackoverflow.com/questions/50572207/clojure-how-to-instrument-another-protocol-in-implementation

seancorfield19:05:58

@sova Re: edn/read-string -- is the problem there you have a string like "42 \"hello\" \"world\" 13" and you want to read all those expressions, not just the first one?

seancorfield19:05:26

You could try (edn/read-string (str "[" user-string "]")) to get a vector of the expressions...

metal 4
kazesberger19:05:28

hi, I'm going to present clj(s) to my boss and colleagues this week and am currently thinking of the best way to demo how and why a REPL is a great tool to give fast feedback while building production ready code. any good ideas for code snippets?

kazesberger19:05:31

I'd stick to the usual notepad, but i thought mb you guys come up with something presentable in even less time

sveri19:05:34

@klaus.azesberger For me its always mind blowing how easy it is to implement a search field with re-frame. You could show a table and the have some input that you use to filter the table. Its just a few lines of code and can be live coded, if it is prepared well.

πŸ‘ 4
kazesberger19:05:09

thanks, that certainly fits my time slot πŸ™‚

kazesberger19:05:11

i could use some of our real ansible configuration data by parsing the yaml files

sveri19:05:58

I wish you good luck πŸ™‚

sova-soars-the-sora20:05:44

i want to remove entries from sets in a nested atom.

sova-soars-the-sora20:05:39

(swap! lookup-rc update-in [:tags (keyword tag)] (remove entry-id) is not doing the trick.

noisesmith20:05:41

for one thing remove doesn't return a set, but also calling remove like that will fail

sova-soars-the-sora20:05:22

Hmm, I thought it was like filter

noisesmith20:05:29

if they are sets, (swap! lookup-rc update-in [:tags (keyword tag)] disj entry-id)

noisesmith20:05:39

filter also wouldn't work in that context

noisesmith20:05:22

update-in passes the object as the first arg, (remove entry-id) doesn't return something that can operate on a set

noisesmith20:05:01

it returns a transducer which can't do much without a transducing context (update-in doesn't provide one of those)

sova-soars-the-sora20:05:36

okay, very cool. beginning to grok.

noisesmith20:05:07

also, if entry-id is the actual id, that's not how filter and remove work, if it's a function that returns true for that id, it's weirdly named and it won't work with disj

sova-soars-the-sora20:05:13

what if i want to remove a keyworded map from an atom completely? can I do something like (swap! lookup-ab update [:entry-ids] disj entry-id) ? in an effort to remove something like the Set associated with 12 from :entry-ids { 12 #{1 2 3 4 5}, 13 #{1 2 3 4 5 6} }

noisesmith20:05:50

that calls for dissoc, but otherwise yes

noisesmith20:05:58

disj is for sets, dissoc for hash-maps

sova-soars-the-sora20:05:16

aha. thank you. Where does remove come into play? disj did not show up in my elementary searching

noisesmith20:05:47

remove is when you have a function that returns truthy for items that should be removed, and want a lazy-seq back

noisesmith20:05:30

for now you can treat (remove f) as an error that doesn't complain (later you might care about transducers and learn about it)

noisesmith20:05:40

+user=> (remove even? (range 10))
(1 3 5 7 9)

noisesmith20:05:23

what you did:

+user=> (remove even?)
#object[clojure.core$filter$fn__5610 0x48e92c5c "clojure.core$filter$fn__5610@48e92c5c"]
+user=> ((remove even?) (range 10))
#object[clojure.core$filter$fn__5610$fn__5611 0x3d1848cc "clojure.core$filter$fn__5610$fn__5611@3d1848cc"]

noisesmith20:05:45

it returns another transducer (one that would blow up if you ever tried to use it correctly as a transducer)

sova-soars-the-sora20:05:45

filter / fn is cool and groovy but filter / fn / fn is not.

noisesmith20:05:01

that's not what is happening here

noisesmith20:05:16

you called remove with one arg, which returns a transducer

sova-soars-the-sora20:05:41

oh, because it doesn't know what dataset to apply this to?

noisesmith20:05:44

calling a transducer with one arg (in this case your set) returns a broken transducer that doesn't blow up until you try to use it

noisesmith20:05:08

it creates an invalid transducer, it's just nonsense but nonsense that clojure doesn't proactively check for

noisesmith20:05:05

I should clarify - you can call a transducer with one arg - that is part of how they are used in transducing contexts, but that's not what's happening correctly here

noisesmith20:05:47

but you don't need to know any of that- just treat (remove f) as a garbage in garbage out error until you know you need it

sova-soars-the-sora20:05:21

okay, thanks πŸ˜ƒ

sova-soars-the-sora21:05:40

@seancorfield how would i access independent elements of a vector by index when I don't know how many there may be in total?

sova-soars-the-sora21:05:09

because when a user inputs tags, there may be many or few. i'm wondering if there is an idiom-esque way for how to iterate over strings in a vector of variable length

sova-soars-the-sora21:05:15

Ah, maybe just (doseq [x (rest (rest data))] ...) will be just fine πŸ˜ƒ

sova-soars-the-sora22:05:32

i'm catching some errors and printing out to the console when they happen, but i always also end up println'ing a nil

seancorfield22:05:04

@sova once you have your vector, count will tell you how many elements are in it.

seancorfield22:05:16

(a vector is always a finite number of elements and count is O(1) on it because vectors are Counted collections, as I recall)