Fork me on GitHub
#beginners
<
2017-11-06
>
pablore00:11:57

Hello! :spock-hand: I'm a lisp enthusiast learning Clojure to find real life solutions. While learning I'm migrating a small Nodejs codebase to Clj. Any help you guys can give me will be highly appreciated

eggsyntax01:11:50

Hi @, welcome! I've never done much with Node, but as far as I know, you'll want ClojureScript for that rather than straight-up Clojure. You might already be aware of that, just wanted to make sure you weren't going down a blind alley.

eggsyntax02:11:45

You may find Lumo interesting; it's a standalone Node-based REPL: https://github.com/anmonteiro/lumo

eggsyntax02:11:22

Also you should be aware that ClojureScript has recently acquired integration with NPM modules: https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules

pablore03:11:34

Thanks! Clojurescript is not needed since I'm migrating a backend-only codebase

pablore03:11:33

It is a REST service, therefore I will be only using Ring

aconanlai17:11:48

i'm also coming from a JS/node backend and learning Clojure!

aconanlai18:11:37

what kind of help/ questions did you have

aconanlai18:11:41

i'll see if i can answer

pablore18:11:34

I've been strugling deciding which reducing function to use. Be vanilla reduce, r/reduce or r/fold

pablore18:11:48

I dont know the differences clearly

aconanlai18:11:23

what's the task exactly?

pablore19:11:32

uff lots of tasks really. The software I'm writing is a simulator for a queue management system. It should get a collection of "tickets" and handle all of them, updating the state for each.

pablore19:11:41

simplified it should look like this:

(defn handle
  [state ticket]
  (do-something-with-state-and-return-it))

pablore19:11:16

then I can reduce this function over a collection of tickets

eggsyntax19:11:55

My suggestion would be to start with regular old clojure.core/reduce, and only move to one of the others if there's good reason to later (eg performance). There are exceptions, I'm sure, but I think for most people it's rare to reach for reducers right away.

pablore20:11:33

k. After I get this project done I will measure the performance with each reducer function

cdimara04:11:30

The author says the function is an alternative to pulling in stencil but won't (require '[stencil.core]) do just that?

noisesmith04:11:10

it means if you don't call that function, then you don't need stencil in your deps

noisesmith04:11:55

so you can decide, as a user of that code, get a stencil dep and call that fn, or ignore it and not - otherwise you'd get an error from loading the namespace, if the require was in the usual place

amarjeet06:11:41

I am trying to use vase. 1) Here is what I want to do: I need to call a 3rd party api (I should be able to do that using clj-http i think) and save data in my db (say Datomic here). Now, I am not able to figure out where should I make this 3rd party api call (in a function definition) - should it be in service.clj? If yes, then how can I use that function inside the edn file? And, question 2) Are routes defined i in the service.clj file being overridden by the ones defined in the edn file?

alexbay12:11:38

Is there any way in Clojure to write function with lazy arguments? Something like defnlazy

alexbay12:11:21

I want arguments to be lazily evaluated.

manutter5113:11:58

In Clojure that would more likely be a macro

manutter5113:11:12

Or a lazy seq

manutter5113:11:30

depends on what you’re after when you say “lazy”

alexbay13:11:48

I want analogue of Scala by-name parameters

alexbay13:11:12

The argument is not evaluated until it’s accessed first time.

manutter5113:11:52

Ok, that’s more like a macro then. Can you give an example of where you’d want to use one?

sundarj13:11:51

@alexbay in Clojure function arguments are always strictly evaluated. it is macros that have the ability to defer/avoid evaluation (e.g. when)

alexbay13:11:51

Yep. Is there any library that has this kind of macros defnlazy, so the function could be written like (defnlazy f [a b] a)?

manutter5113:11:24

It’s not a library, you’d just use defmacro

manutter5113:11:29

(defmacro when
  "Evaluates test. If logical true, evaluates body in an implicit do."
  {:added "1.0"}
  [test & body]
  (list 'if test (cons 'do body)))

manutter5113:11:42

The body arg(s) will not be evaluated unless the test arg evaluates to true.

manutter5113:11:24

That’s probably not a great intro to macros, though, since that’s from the source code for clojure.core.

alexbay13:11:37

Ok, I see. Why I’m asking is because this ability is sort of standard for FP languages like Haskell, Scala.

manutter5113:11:32

Yes, but I’m tempted to say that’s because they don’t have macros per se, so they need some other mechanism to serve a similar purpose.

manutter5113:11:20

Macros are more powerful (and trickier to master)

alexbay13:11:08

Sounds interesting. Thanks.

jgreen18:11:44

is there a clean way to count the maps in both vectors? ie: {:foo [{:a “test”} {:b “test2"}] :bar [{:a “test”}]}

jgreen18:11:08

at the moment i have a function that looks like this: (+ (count (get coll :foo)) (count (get coll :bar)))

jgreen18:11:50

@jeff.engebretsen im not sure how i would use it in this case

sundarj18:11:09

(reduce + (map count ((juxt :foo :bar) {:foo [{} {}] :bar [{}]})))
3
is one way to do it

sundarj18:11:52

your original way is arguably simpler though

jgreen18:11:08

yeah, i did something like that before, but it seemed too complex for what i wanted

jeff.engebretsen18:11:36

I can't find a good way to use apply either.

jeff.engebretsen18:11:43

ignore the suggestion.

jgreen18:11:09

no worries, i appreciate the help. 😛

noisesmith18:11:53

(count (mapcat vals maps)) - if the val for every key is a vector, and you want to count all of them

sundarj18:11:16

@noisesmith i believe you mean val, not vals

noisesmith18:11:26

no I mean vals

jgreen18:11:59

yeah, vals didn’t work, but val did

noisesmith18:11:30

oh! input is a single map, I missed that

noisesmith18:11:03

so really it’s (count (mapcat val map))

jgreen18:11:20

no worries. this looks a lot better. thanks everyone!

alexkeyes19:11:04

quick q: what does the map-> syntax mean?

ghadi19:11:18

it's not special syntax, it's just the name of the function. When you make a defrecord Foo, in addition to the defrecord you get two functions for free, one positional ->Foo and one associative map->Foo

ghadi19:11:19

(defrecord Foo [a b c]) would give you a positional function (->Foo a b c) and a map/associative function (map->Foo {:a 1 :b 2 :c 3 :other 4})

ghadi19:11:14

you'll see -> in a lot of different contexts in clojure. like the threading macros -> ->> cond-> etc. or conversion functions in libraries: long->Date

alexkeyes19:11:27

@ghadi thanks for the explanation!

ignis20:11:21

hi! i'm trying to read a part of a file (up until certain line) -- and it appears not so easy from a first sight

ignis20:11:47

here is my attempt which fails with an exception

ignis20:11:52

returning one line in repl

ignis20:11:00

(with-open [r ( yaml-file)]
        (take-while #(not (re-matches #"Mappings:" %)) (line-seq r)))

ignis20:11:28

the exception is

ignis20:11:30

IOException Stream closed java.io.BufferedReader.ensureOpen

noisesmith20:11:47

take-while is lazy

ignis20:11:51

why is it closed exactly after one line outputted

noisesmith20:11:04

you don’t force inside the with-open, so you don’t try to read the file until it is closed by with-open

noisesmith20:11:13

don’t mix laziness and io

ignis20:11:22

so i need a doseq there?

ignis20:11:27

wrapping take-while

noisesmith20:11:30

doseq, or doall

noisesmith20:11:54

doseq would throw away all your data and return nil though

noisesmith20:11:04

which probably isn’t what you want

ignis20:11:08

is that a good way at all to read a part of the file?

ignis20:11:14

imean using that with-open

noisesmith20:11:37

sure, just make sure if anything inside with-open is potentially lazy, force the realization before leaving the with-open body

ignis20:11:59

ok understood, thank you @noisesmith

drewverlee21:11:43

is there a way to get a str version of the function?

(defn foo [x] x)
(??? foo)
;;=> "foo"

seancorfield21:11:44

@drewverlee Well, type or class would give you the class name of the compiled function... so .getName on that would yield a string.

seancorfield21:11:11

boot.user=> (defn foo [x] x)
#'boot.user/foo
boot.user=> (.getName (class foo))
"boot.user$foo"
Is that what you want?

seancorfield21:11:11

and then

boot.user=> (clojure.repl/demunge *1)
"boot.user/foo"
to get the more readable version.

rcustodio22:11:57

So I can understand core.async chan this (chan 10) would be like prefetch 10 from rabbitmq? meaning 10 execution in parallel?

smith.adriane22:11:14

10 would just be the buffer size

rcustodio22:11:28

I see, is there anyway to create a pool size with core.async?

smith.adriane22:11:20

there’s a couple options

smith.adriane22:11:46

but it won’t fit every use case

smith.adriane22:11:09

there’s also pipeline-async, pipeline-blocking

smith.adriane22:11:55

you can also do it manually, by creating multiple consumers from multiple thread or go blocks

rcustodio22:11:59

I see, thanks

smith.adriane22:11:09

you can see how pipeline does it

smith.adriane22:11:15

although it’s a little bit hard to follow

rcustodio22:11:29

Okey, I will check it

smith.adriane23:11:09

you can see them choosing between go blocks and thread

smith.adriane23:11:45

there’s probably some library on top of core async that provides a higher level abstraction

tkjone23:11:13

I am repeating something like the following several times in my code:

(-> highlight .-style .-width)
I wanted to see what it would look like to make the above into a function so the attr (`.-width`) could be dynamic. For example:
(defn get-attr
  [attr]
  (-> (.-style highlight) attr))
The end result being that I could use it like this:
(set! (get-attr .-width) 45)
I have tried a few variations of the above and can't seem to get this to work without crashing the compiler.

sundarj00:11:53

so, .-attr isn't a first-class value. it's a special form, like if, that is built into the clojure compiler, and can only be used statically

tkjone01:11:54

@ this being the case, does this mean that the way I was approaching it will not work, yes?

sundarj01:11:04

@ that is correct 🙂

tkjone01:11:29

Is there a way to do this though? I imagine it would be a macro?

tkjone01:11:46

At this point, it is a point of interest for me

sundarj01:11:10

yeah a macro would work (i think)

smith.adriane23:11:07

specifically the get and set functions in that library

smith.adriane23:11:31

eg. (goog.object/set (goog.object/get highlight "style") "width" 45)

smith.adriane23:11:36

with (:require [goog.object])

smith.adriane23:11:14

I don’t have a repl to test that, but I think that should work