Fork me on GitHub
#clojure
<
2019-10-12
>
peterdee00:10:11

Maybe just personal preference.

peterdee00:10:58

I didn’t read @seancorfield example before responding.

peterdee00:10:10

It’s not bad.

peterdee00:10:11

I like to use ?m in case I have to nest them, ?m ?m1 ?m2…

seancorfield01:10:04

@m131 In this particular case, none. It's just that as-> has a "strange" argument order -- value symbol -- compared to everything else that binds symbols and values -- and that's because as-> is designed to have the value threaded into it, as its first argument. So it's "natural" to use as-> inside -> (or the other thread-first operations). -> is the "base case" because you can thread into ->>, cond->, as-> etc etc.

erwinrooijakkers15:10:46

There’s also a good argument against using as-> not inside a threading macro by Stuart Sierra at https://stuartsierra.com/2018/07/15/clojure-donts-thread-as

erwinrooijakkers15:10:02

>Outside of ->, the arguments to as-> appear in the order value name rather than name value, making it unlike anything else in Clojure.

erwinrooijakkers15:10:35

>it places that name second in its parameters. To me, this clearly indicates that it is meant to be used in combination with ->.

erwinrooijakkers15:10:42

Ah actually that’s the same argument you make 😉

seancorfield17:10:41

He probably just makes the argument more clearly than I do 🙂

seancorfield01:10:09

So it bothers me to see (as-> value symbol exp1 exp2 ,, expN) rather than (-> value form1 form2 ,, (as-> symbol exp1 exp2 ,, expN) ,, formN)

👍 4
donotwant 4
ahungry06:10:42

Oh yea, i see and agree, thanks!

valerauko07:10:00

never occurred to me to mix -> and as-> this is interesting

donotwant 4
Ho0man07:10:39

Hi, I wanted to test my server-sent events and receive each event individually but the http client request fns all block until the whole response has been received. How can I get each individual event separately ? (sorry to ask here but I couldn't find a channel for http-kit)

p-himik15:10:16

Stuart Sierra has a few thoughts on this as well: https://stuartsierra.com/2018/07/15/clojure-donts-thread-as

sooheon15:10:12

Has anyone seen “clojure: error: Cannot execute clojure: No such file or directory” while running clj?

sooheon15:10:25

While running clojure directly works fine

chrisn15:10:08

Where in the clojure codesbase is the definition of 'def'?

Alex Miller (Clojure team)15:10:24

def is a special form, so it's defined in the compiler

chrisn15:10:14

Thanks Alex, that helps but I think I am on the wrong track in general. I have a few macros that attempt to export functions or symbols from other places into a given namespace. This works unless the thing being exported is a macro in which case it works until someone attempts to aot the thing after which the macro fails to work. What doesn't work every is cider's go-to-source. My thought was to override the meta data generated by def to include a different file and line but this type of thing is normally handled by a source-map type datastructure. I don't mind needing to redeclare macros when I am building out the API layer of a library but I cannot be redefining and maintaining a set of forwarding functions and ideally go-to-source works from editors. 1. Does anyone know if nrepl has a source-map type entry it looks for in the var's metadata? 2. Ideas on other ways?

Alex Miller (Clojure team)15:10:49

var's have file/line/column metadata and that's how Clojure's source function works. I don't know if cider has something additional.

chrisn15:10:14

I will scan nrepl to see if it supports some level of source mapping beyond that.

chrisn15:10:35

I would need to override the file/line/column metadata and I can't see how to do that.

Alex Miller (Clojure team)15:10:36

I suspect it's in cider, not nrepl

Alex Miller (Clojure team)15:10:13

I don't know how you're "exporting" into another namespace, but presumably that means making vars. vars have metadata.

chrisn15:10:46

That is how

chrisn15:10:02

Overriding file/etc. does nothing; the 'def' replaces it.

chrisn15:10:24

Maybe I can just add the var do the namespace directly instead of going through a def and macro?

Alex Miller (Clojure team)15:10:16

the potemkin library has stuff to do this "exporting" with btw

chrisn15:10:31

Good to know, I am a fan of potemkin

Alex Miller (Clojure team)15:10:25

seems like you just want the :file :line :column meta at the top level, not under :source-map?

Alex Miller (Clojure team)15:10:31

you might find resolve useful too for symbol->var

chrisn15:10:33

he solves it by altering meta after the def is created

Alex Miller (Clojure team)15:10:02

(and as an aside, I think doing this kind of thing is a bad idea, personally)

👍 8
dominicm15:10:28

lighter than potemkin, which does var watching to sync up things like dynamic vars. Important features in some senses, but usually a bad sign!

chrisn15:10:01

Yep. agreed.

chrisn15:10:57

So Alex, how do you get around this? I don't want users to include 10's of namespaces for things implementations of things and I don't want the implementation of a thing to be all in one file. For things like math libraries which have 100's of symbols that users expect to find under one namespace some level of 'lifting some of these things out of these implementation file' seems to make sense.

chrisn16:10:25

And I guess is a pattern I am used to from years of c, c++.

chrisn16:10:03

@dominicm That looks perfect to me, thank you!

dominicm16:10:51

There's 2 options I've seen recommended in place of this proxying: 1. impl namespaces & api namespaces, see core.async for examples. https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj 2. load, see clojure.core and clojure.pprint for examples. https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint.clj#L43-L49

chrisn16:10:53

1. reduces to either duplication or implementing everything in the API namespace. Some level of that makes sense sometimes. But pulling functions directly out of the impl namespace also makes sense IMO if the function can be defined and documented in one place it is better locality. 2. load is something else altogether, sort of an eval power tool. Thanks both of you, that is enough information to move forward 🙂.

dominicm16:10:18

Load isn't so bad in a language like clojure. It's basically require

chrisn16:10:31

Oh I wasn't saying it was bad. It is extremely interesting.

Alex Miller (Clojure team)17:10:45

I don't see the problem with having multiple API namespaces

Alex Miller (Clojure team)17:10:01

I also don't see the problem with having big namespaces

Alex Miller (Clojure team)17:10:36

Creating and using a proxying system seems both harder and more confusing than either of those imo

chrisn17:10:56

It's all tradeoffs as to how much effort a user needs to use to remember where something is and how structured or complex the actual implementation of what you are doing is and how much effort you want to do to organize and maintain some large file. I usually implement things in some more granular fashion with smaller files and then export a flattened namespace. Zach in potemkin I think states it well: https://github.com/ztellman/potemkin#import-vars I am with Zach on this one.

Alex Miller (Clojure team)18:10:42

He seems to imply "Clojure namespaces conflate the layout of your code and your API." as a downside and "This means that the structure of your code and the structure of your API can be decoupled." as an upside. In my opinion, the reverse are true. :)

seancorfield19:10:03

I'm with Alex there. Having used a variety of ways to import/export Vars across namespaces, I've concluded it's usually a bad idea -- and organizing your namespaces around the API is a better option.

Quest21:10:23

Little question, but need to explain context first. If I do something like (def myfn (partial foo "bar")), I can't instrument foo with debug bindings via cider-eval-defun-at-point -1 and have foo breakpoint when I run (myfn ...) at the REPL. This is because the partial is copying the value of the function. If I instrument with (def myfn (partial #'foo "bar")) (referring to foo by reference), then I can debug foo via calls to myfn as expected. Now the question: is there any downside to doing this by reference? I can't come up with any & in fact seems like it'd take less memory, but I'm making a PR against someone else's library and want to be sure.

Alex Miller (Clojure team)22:10:57

It’s slower to invoke

👌 4