Fork me on GitHub
#clojure
<
2018-04-13
>
stephenmhopper00:04:48

Is it possible to use transducers to explode a collection? Suppose I have a transducer called (map some-fn) where some-fn returns a collection and I want each element in that collection to be returned as a top level element in the transduction process. Is that possible?

noisesmith00:04:59

@stephenmhopper - that's what mapcat does

noisesmith00:04:05

user=> (into [] (mapcat rest) [[1 2 3] [4 5 6] [7 8 9]]) => [2 3 5 6 8 9]

stephenmhopper00:04:55

oh hey, that’s what I was looking for. thank you, @noisesmith

hlolli00:04:33

I have most likely a deadlock issue with a jni dll library on windows (linux and mac don't produce deadlocks for same c++ code), this happens at the point of instanciateing a class with new. Could I wrap the new call into some timeout error handler? (for debugging purposes, want to see some error instead of eternal freeze).

noisesmith00:04:21

@hlolli this is a bit OT but if you use gdb to attach to the process you can see exactly what it was doing when it deadlocked

noisesmith00:04:42

jdb might even be informative from a more jvm centric point of view

hlolli00:04:54

yes, I'm bit clueless, I'll try gdb, I guess I can find it on cygwin? jconsole doesn't detect deadlock on the java process, but this is as frozen as it gets. Thanks for the tip, didn't know about jdb

noisesmith00:04:59

both can tell you where a certain thread is in its stack, and what the locals are - that should be enough to know how it got stuck

noisesmith00:04:31

of course the gdb view of things will make more sense from the c lib's point of view, and hte jdb view will make more sense from the java side

emccue05:04:46

I'm kinda curious why clojure.algo.generic.functor isnt advertised more

emccue05:04:18

It just straight up solved every problem I've had with interfacing with libraries written in vavr

emccue05:04:20

^ its a really dumb example but it turned interop from agonizing to manageable

cmal06:04:35

Hi! Can I change the definition of a clojars library's private function that were used by a public function which is being used in my project, in my file that required this public function?

emccue06:04:00

@cmal Depending on your use case, there might be a better answer

emccue06:04:28

in general its best to keep encapsulation with the public interface your libraries provide

emccue06:04:46

so if you could say more details maybe I can help you find a better answer

emccue06:04:02

that will let you use a private var

emccue06:04:38

This is a general pattern for managing things you might want to mock out in tests (as well as other reasons)

emccue06:04:35

I think with-redefs gives you a scoped version of what you want, but there are some gotchas so be careful with concurrent code

emccue06:04:57

Theres also the things that other people will tell you

emccue06:04:08

those are probably much more informed opinions

benzap06:04:00

@emccue that's a pretty nifty trick, I ran into issues with private functions a while back, and this would have been awesome to know

leonoel07:04:54

@cmal the only acceptable way to tackle this problem is to make it public in a PR/patch, send it to the author of the library, and explain your use case. All other solutions are dirty hacks

benzap07:04:09

Guys! I think I found the answer to making collections in fif!

emccue07:04:59

I am actually impressed

emccue07:04:12

you seem to not have been eaten alive by maggots

emccue07:04:29

you ARE the maggot

emccue07:04:43

also, whats fif

emccue07:04:52

actually, why fif

emccue07:04:58

I can google the other stuff

benzap07:04:04

haha, I don't know. I read some article where a guy implemented a small subset of Forth

benzap07:04:26

I don't think i'm sticking with the XML stuff, i'm having a hard time deciding on variable names for this stuff

benzap07:04:26

The only reason i'm continuing with making this language, is so I can maybe replace a restful API with something akin to generating data structures. Similar to something called Falcor

benzap07:04:45

So just imagine a clojure server sitting somewhere, with http://localhost/api/fif sitting there, waiting for requests

benzap07:04:56

Oh, the glory

benzap08:04:23

It would also be cool to develop a frontend web client which can just point at random server instances with a fif repl, and poke around at the functions available, throw down a few queries

benzap08:04:04

It would be like that movie... what's it called again? Hacker?

pyr08:04:48

Just read the backlog, super interesting discussion with the differing views of @tbaldridge and @alexmiller

daveliepmann09:04:27

could you link to the earlier discussion? I scrolled and scrolled and seem to have missed it.

pyr18:04:00

@U05092LD5 it's way up, can't find it anymore now 😕

pyr08:04:38

Having ran teams whose main language was Clojure for 7+ years now, I tend to agree that pace of development is not an issue

pyr08:04:04

But I do wish some libraries would be handed over to 3rd-party maintainers if they are willing to step up, core.async is a good example. I do regret that Clojure has decided it would be an ecosystem without blessed libraries and that some very simple tasks need decisions

pyr08:04:42

If you look at contributor heavy projects like riemann, even dead simple things like http requests end-up being done through a number of libraries

caleb.macdonaldblack09:04:05

Anyone have any advice on formatting destructuring?

caleb.macdonaldblack09:04:33

I believe that is correctly formatted as I would any other nested map

caleb.macdonaldblack09:04:43

There are a couple of things I could do. I could put it all on one line (Probably my preferred method). I could format over multiple lines like shown. And lastly I could avoid destructuring such a deeply nested map

caleb.macdonaldblack09:04:20

Not sure what would be better if I was to avoid destructuring this nested map alltogether

caleb.macdonaldblack09:04:04

Definitely leaning toward all on one line though. It is densely packed logic and perhaps that is ok?

caleb.macdonaldblack09:04:41

^ That is what it look like all on one line

daveliepmann09:04:06

do you need all those names destructured?

caleb.macdonaldblack09:04:25

Yea I’m using every symbol defined here

andre.stylianos10:04:20

Hey Caleb! 👋 I usually avoid destructuring everything in one place with nested data

andre.stylianos10:04:48

For me it's much easier to read with separate destructruing steps

andre.stylianos10:04:05

Looking at your example I have absolutely no idea what's the shape of your data, and I would probably need a few good minutes to understand the input

andre.stylianos10:04:33

I'd prefer a lot of (get-in input [:kw1 :kw2]), more verbose but it's easy to parse in your head

andre.stylianos10:04:25

or just sequential let bindings where you destructure step by step

tatut11:04:17

It would seem that if you need that many destructurings, perhaps you should split the work of that function to many smaller ones

caleb.macdonaldblack11:04:53

@tatut This is being used in view code. There are sections/components in my view code where the whole map could be passed into each one. I could destructure only what I need in each component. I think that would be an improvement. My only issue is that some sections need values at all levels of depth in the map. For example one component uses the titles to construct a path. This component would still need to destructure deeply nested data.

joelsanchez11:04:32

with re-frame that would be trivial, just put all of that in the db and define subscriptions as needed

tatut11:04:15

I like the “regular functions” approach, functions take as parameters what they need and return a value… without any subscription magic

tatut11:04:27

still let-binding 20 names seems like it could be split to smaller pieces

caleb.macdonaldblack11:04:40

@joelsanchez Wow, why didn’t I think of that?! I am using re-frame. I’m currently returning the whole object. I should definitely make subs for all of these.

👍 4
caleb.macdonaldblack11:04:56

Looks like using subs in re-frame is going to be my solution here. This kind of heavy destructing is interesting to me though. I wonder if a macro like this would be a good idea.

caleb.macdonaldblack11:04:14

You could represent the entire tree as the data structure it could define the variables as the provided symbols

caleb.macdonaldblack11:04:20

An issue a see with this though, is that you cannot define the values of the map and the map itself at the same time

caleb.macdonaldblack11:04:45

But it is very clear right away what the data structure looks like

idiomancy12:04:04

Can I use a string as a property accessor in clojure? e.g., is there some way, given the string "yellow" to access (. Color yellow)?

mfikes12:04:34

@idiomancy This works, but perhaps could be improved

(defmacro str->color [s] `(. Color ~(symbol s)))

idiomancy12:04:12

oh neat, okay, gotcha, so one uses a macro there

Adam13:04:25

Hey all, I’m looking for a reliable Clojure Kafka client, any recommendations?

dadair13:04:23

I settled on using the standard Java interface through java interop, was relatively straight forward (there didn’t seem to be any great clojure wrappers)

8
Adam13:04:03

Got it, thanks!

tbaldridge14:04:32

Good advice for almost anything with a Java lib

Volodymyr Sereda15:04:09

Yes, we’re also just using the Kafka Java library. It works very well, and you can always wrap it in some Clojure code.

emccue15:04:53

Im writing a command line program

emccue15:04:18

This seems like an abuse of the let form

emccue15:04:32

is there anyone willing to bikeshed this?

dpsutton15:04:13

for the sake of testability i would have at this top level only printing help or passing those parsed args into a function that does all of the work and this top level just parses and either prints the help or invokes that function

dpsutton15:04:43

also passing a vector of expected parsed args would make this a bit more readable of what you expect to be in that args return value but this looks simple enough that it might not matter. but other than that it's not that abusive. (not a big fan of a system exit in a let binding for sure though)

joelsanchez15:04:20

marginally better

theeternalpulse15:04:19

Do namespaced keywords have to follow the parent namespace, or are they namespaced by their closest context/object. I know ::somekw will take the top level, but should I use :some-ns/kw only when referencing or also definining?

dpsutton15:04:45

i'm partial to this:

(defn write-csv [{:keys [output-file board-name]}]
  (let [client (make-li-client output-file board-name)]
    (with-open [writer (io/writer output-file)]
      (->> (all-messages client board-name)
           (map to-csv-format)
           (csv/write-csv writer)))))

(defn -main [& args]
  (let [options (parse-args args)]
    (if (:help options)
      (do (println summary)
          (System/exit 0))
      (write-csv options))))

joelsanchez15:04:22

I also prefer that

dpsutton15:04:50

now the writer is testable and invocable from the rpel rather than just from the cli

emccue15:04:54

The Options is a map with 7 keys

emccue15:04:09

which is partially why I didnt jump to the destructuring

emccue15:04:23

but even without that I like your approach better

dpsutton16:04:45

where can i find a list of valid var characters? want to make sure that $ is a valid function name and not just happens to be right now

noisesmith16:04:56

I think that's the closest thing to an official list

Alex Miller (Clojure team)16:04:30

that’s certainly used extensively in Datomic and unlikely to be made an invalid symbol

hypirion17:04:05

I think it's somewhat fair to assume the set of valid characters won't change. I know <>=&%$ also works, although you better be careful with & and % because some macros consider some symbols with those two chars as special.

dpsutton17:04:09

@alexmiller its used in datomic but always in a quoted vector though right? or are you speaking internally? (ie, '[find: ... :in $ ....)

Alex Miller (Clojure team)17:04:30

why does it matter if it’s in a quoted vector?

dpsutton17:04:58

i guess that solves it then. I thought it might change the considerations. thanks for your clarification 🙂

Alex Miller (Clojure team)17:04:22

quoting just prevents evaluation, doesn’t affect reading

dpsutton17:04:25

i didn't realize var names === valid symbosl but i guess it makes sense

dpsutton17:04:40

thank you very much

Alex Miller (Clojure team)17:04:41

there is nothing special about var names - they are just symbols

👍 4
Alex Miller (Clojure team)17:04:24

the main considerations are really in the reader to make sure that we can differentiate them from some other token

Alex Miller (Clojure team)17:04:06

so like a symbol can’t start with a : because it would then conflict with keywords

noisesmith17:04:28

or .foo and interop, right

Alex Miller (Clojure team)17:04:30

there are no such conflicts with $ and seems unlikely there will be in the future

pyr18:04:31

@devn sentry works really well

xiongtx19:04:25

I want to add some vars to an existing namespace (e.g. clojure.spec.alpha). I create a file and use (in-ns 'clojure.spec.alpha), then define some vars. But when I require clojure.spec.alpha in other files, the new vars I defined are not loaded. Is there a way to force the new vars to be loaded in the clojure.spec.alpha ns?

Alex Miller (Clojure team)20:04:54

I think you need to be more explicit about what you’re trying - can you show what you’re doing at the repl?

xiongtx21:04:53

I decided to change tact, but it’s not about the REPL. It’s about creating a new file that I wanted to be in another ns. I figured out that explicitly :requireing the original namespace of the new file solves the problem, but it’s tedious.

hmaurer20:04:03

Is it common practice to have a :type key in clojure maps, with a keyword indicating the “type” of the entity that the map is representing?

hmaurer20:04:22

Maybe I should ask that in #beginners

the2bears21:04:49

@hmaurer we don't have any key like that in any of our maps here 🙂

the2bears21:04:17

But if you do, make sure to namespace it.

hmaurer21:04:27

@the2bears do you have some way of describing what a map represents then? beyond just the keys it contains

the2bears21:04:11

spec does that in a way, but we don't use anything else to describe our maps, other than documentation

sveri21:04:03

@the2bears thats not completely true, you can use specs for generative testing with clojure.test.check

the2bears21:04:56

@sveri I meant we don't have anything else for describing maps, not what spec is capable of.

sveri21:04:37

ah, ok, sorry, I misunderstood you then.

👍 4
the2bears21:04:06

Yeah, I edited my original comment as it was pretty ambiguous.

sveri21:04:38

🙂 That happens to me all the time.

xiongtx21:04:49

I’m trying to import vars from one namespace into another like:

(defmacro import-def
  "import a single fn or var
   (import-def a b) => (def b a/b)
  "
  [from-ns def-name]
  (let [from-sym# (symbol (str from-ns) (str def-name))]
    `(do
       (def ~def-name (var ~from-sym#))
       (reset-meta! (var ~def-name) (meta (var ~from-sym#))))))

(defmacro import-vars
  "import multiple defs from multiple namespaces
   works for vars and fns. not macros.
   (same syntax as potemkin.namespaces/import-vars)
   (import-vars
     [m.n.ns1 a b]
     [x.y.ns2 d e f]) =>
   (def a m.n.ns1/a)
   (def b m.n.ns1/b)
    ...
   (def d m.n.ns2/d)
    ... etc
  "
  [& imports]
  (let [expanded-imports (for [[from-ns & defs] imports
                               d defs]
                           `(import-def ~from-ns ~d))]
    `(do ~@expanded-imports)))

(defmacro import-from-ns
  [ns]
  (let [publics (keys (ns-publics ns))]
    `(import-vars [~ns ~@publics])))
But (import-from-ns clojure.spec.alpha) is returning Unable to resolve symbol: spec in this context. If I evaluate its macroexpansion, no such error occurs.

Alex Miller (Clojure team)21:04:15

if you want to do this (for the record, I personally think it’s a bad idea), there are things in potemkin for this

xiongtx21:04:42

Yes, it’s a bad idea, it’s not my idea, and I need it to be cljs compatible

xiongtx21:04:10

Here’s all the above in a single macro:

(defmacro import-from-ns
  [ns]
  (let [publics# (keys (ns-publics ns))]
    `(do
       ~@(for [v publics#]
           (let [from-sym# (symbol (str ns) (str v))]
             `(do
                (def ~v (var ~from-sym#))
                (reset-meta! (var ~v) (meta (var ~from-sym#)))))))))