Fork me on GitHub
#beginners
<
2019-01-14
>
fmn05:01:24

Are there any open source clojure projects that built using cats ?

Audrius09:01:06

how to repeat some function call n times?

pavlosmelissinos09:01:24

repeatedly if function has no args: https://clojuredocs.org/clojure.core/repeatedly iterate if function has args (and is without side-effects): https://clojuredocs.org/clojure.core/iterate

temco13:01:08

if you want to call a function which always returns the same value for n times, like (Thread/sleep 10000), repeatedly is OK; otherwise you should use iterate, for it re-use the return-value of the previous calling as the argument of the next calling

pavlosmelissinos14:01:36

Ι don't think that's correct, repeatedly takes a function with side effects as argument, so it shouldn't have to return the same value

temco14:01:48

yes, your statement is more correct

mfikes14:01:52

If you are just doing it for side effects and don’t care about the return values, you can also do (dotimes [_ n] (f))

borkdude17:01:43

Since we’re talking side effects, run! is also suited for side-effecting functions, if you want to run it over some reducible collection:

(run! (fn [i] (println i)) (range 10))

JoshLemer20:01:04

Wondering if Clojure has taken advantage of the new CHAMP (Compressed Hash Array-mapped Prefix Tree) data structure for their default HashMap/HashSet implementations?

JoshLemer20:01:46

in the upcoming Scala release (2.13) the existing HAMT structures were replaced with CHAMP ones

Lennart Buit20:01:53

the hashmap impl has certainly not changed. That said, you can implement the correct protocols for whatever hashmap impl you want and it will play nice

Lennart Buit20:01:10

I think the only thing you won’t get is its literal {}

noisesmith20:01:40

you can get it to pr as a {} (even java.util.HashMap gets that behavior already), but yeah, you shouldn't even try to override the reader for {}

Lennart Buit20:01:00

now I got curious…

JoshLemer20:01:06

Do you know if a change to CHAMP structure has been considered and rejected, or nobody has proposed it yet?

Lennart Buit20:01:16

I think that a change as fundamental as what algorithm to use for a hashmap has to have an incredibly high payoff.

Lennart Buit20:01:52

Especially because it is often not “this impl is flat better”, but more “this impl can better deal with these situations, but worse with these”

noisesmith20:01:44

reading about what CHAMP does that existing immutable hm impls don't, Clojure already uses a tree of arrays, which gets some of those advantages. And the lengths of these arrays were performance tuned.

noisesmith20:01:19

but yeah, using deftype or a bit of java code to implement the right protocols for Hashmap in clojure is a weekend hack, why not try

Lennart Buit20:01:51

You can probably bind to the Scala impl if you really wanted to

noisesmith20:01:54

this was discussed a couple of years ago on the mailing list https://groups.google.com/forum/#!topic/clojure/zO-5yUx2aSk

ghadi20:01:11

there are serious clojurists who have prototyped it and found the claims to not be achievable

dpsutton20:01:54

there was a phenomenal talk at clojure/west in 2016 about changing the tree structure but it had to do with sorting the values versus pointers to new nodes. I really enjoyed that talk

dpsutton20:01:02

not sure it was CHAMP related though. can't remember

noisesmith20:01:53

tl;dr of my links above: you can try @ztellman’s bifurcan lib if you want to use an implementation of CHAMP

Lennart Buit20:01:52

speed of my programs is way more often plagued by my bad programming, than with what hashmap algorithm is used :’)

Lennart Buit21:01:59

If I have some record in a clojure namespace and it gets serialized to EDN, its tag becomes a Javaified name. Can I programatically construct this same name?

Lennart Buit21:01:43

So, my-awesome-namespace.MyRecord becomes my_awesome_namespace.MyRecord

hiredman21:01:45

clojure.core/munge will do it, or (symbol (.getName MyRecord))

noisesmith21:01:58

@lennart.buit (class my-obj) should get you this, given an instance

hiredman21:01:22

but before you go to far with that, depending on what you are doing, using a tagged literal is often better then using record literals directly

JoshLemer21:01:21

Also some improvements that we are doing in the next Scala release which Clojure could also do, is to build up hashmaps / hashsets mutably (but never mutating one that has been returned to a caller)

Lennart Buit21:01:22

Well, I have records that are serialized to EDN, and I want to define a reader map that takes the generated tag and returns a record

JoshLemer21:01:17

Sorry if it already does this, I’m looking at PersistentHashMap.java right now and I don’t think it does do that

noisesmith21:01:30

@joshlemer that's how transients work currently

noisesmith21:01:38

implicitly used by eg. into

Lennart Buit21:01:43

but saying that {'my_awesome_namespace.MyRecord my-awesome-namespace/map->MyRecord} becomes tiresome quite quick

noisesmith21:01:36

@lennart.buit I'm confused - defining your record implicitly creates a reader for that record, it should just work

JoshLemer21:01:54

@noisesmith ah yes I stand corrected 🙂

hiredman21:01:54

not for clojure.edn though

hiredman21:01:00

but I think if you are creating lots of different kinds of defrecords, and also serializing them, that kind of sounds like the kind of system that would be better served using plain maps

Lennart Buit21:01:16

they are records because they are implementing protocols, but maybe you are right

Lennart Buit21:01:48

but hypothetically, how would I do this in the least amount of keystrokes given clojure.edn?

hiredman21:01:24

the problem is clojure.edn is designed explicitly so that you have to whitelist everything, because the clojure.core functions allow all kinds of stuff that are security concerns

JoshLemer21:01:36

hmm actually I don’t think the tree structure of the map is being mutated, just the root wrapping object

hiredman21:01:43

so the least amount of key strokes would be using clojure.core/read-string over clojure.edn/read-string(same for read), but you can only do that for trusted data

Mario C.21:01:34

If I am using Liberator and in my :handle-exception an exception occurs... What handles that? The same function? It seems it loops for a while

ordnungswidrig21:01:43

You should avoid throwing exceptions from handle-exception. You might have found a bug. Can you please find an issue at https://github.com/clojure-liberator/liberator?

ordnungswidrig21:01:38

Thanks for the heads-up. I need to investigate.

👍 5
hiredman21:01:49

if you are using clojure.edn because your data is untrusted(api exposed to the outside world, etc), then I think tying the data format to your internal class names (which is what those record tags are) is a bad idea

Lennart Buit21:01:58

I am okay with the whitelisting, actually quite prefer it, I am just a bit tired of typing the entire java-ified name of a record, making seven typos, not understanding why my code crashes, fixing 5 out of the 7, repeat for each record. While I can have the record imported…

hiredman21:01:18

you shouldn't be importing records

Lennart Buit21:01:56

sorry - I am actually not

hiredman21:01:02

(importing records instead of using the factory functions leads to common errors like failing to require the namespace that defines the record)

Lennart Buit21:01:00

Right, that was a bit of a hyperbole on my part, I don’t actually import the generated classes, I use plain old defns as facades for the map->... and ->... constructors

Lennart Buit21:01:13

Anyhow, given your concerns I will rethink what I have now

hiredman21:01:23

like, if this isn't an exposed api end point or whatever, just use the clojure.core versions of the functions, not the clojure.edn ones, and the record readers will just automatically work (if I recall)

Lennart Buit21:01:18

It is certainly not, I was looking for (.getCanonicalName ...) btw

hiredman21:01:37

how are your records printing?

hiredman21:01:03

user=> (defrecord Foo [])
user.Foo
user=> (->Foo)
#user.Foo{}
user=> #user.Foo{}
#user.Foo{}
user=> 

hiredman21:01:23

user=> (read-string "#user.Foo{}")
#user.Foo{}
user=> 

Lennart Buit21:01:44

Yeah they are, its just the default

hiredman21:01:50

if yours isn't behaving like that you have something breaking it (either your code, or some library you use)

Lennart Buit21:01:57

I think the other EDN reader will work fine, but I have to make up my mind whether I like it… haha. Help much appreciated!

jaide22:01:36

When working with hiccup, what’s the best way to create a custom component? Is it just a function I call that returns a hiccup vector or is there some macro I import like defelement so I can do [:my-element …]?

lilactown22:01:34

@jayzawrotny it varies on the library. are you using reagent, or weavejester's hiccup library, or rum...?

jaide22:01:12

Ah, I never realized those were technically separate flavors. I’m using weavejester’s hiccup lib.

lilactown22:01:35

in that case, you wouldn't create "custom components". instead, you just have functions that return hiccup data and call them as normal functions

jaide22:01:06

Thanks. Fortunately, that’s what I’ve been doing 🙂

Machado22:01:59

Hey, So I'm trying to create a simple CRUD to taste some TDD, and I'm completely lost on how to "mock"a in memory database

Machado22:01:11

Is a good strategy to glue it to an atom?

val_waeselynck23:01:02

Could be yes. You could also use DataScript.