Fork me on GitHub
#clojure
<
2017-11-15
>
Mudge05:11:51

Hey is it possible to use leiningen from the REPL instead of from the commandline?

noisesmith16:11:44

yes, you can for example launch a clojure repl from the leiningen jar, or include leiningen as a dep of your project. But if you aren’t making a tool that is meant to be used as a leiningen plugin or extension you might be on the wrong track here. leiningen is meant to be a build tool, ideally it and its libraries don’t exist on a production server

zignd14:11:26

guess i'll do the same next time i have questions, post them on SO and then link them here. as a newcomer it is very hard to find answers to some questions others might already had

leontalbot14:11:11

@zignd Yes. SO is better in SEO and UX that slack logs. 😉

zignd14:11:11

that's what i had in mind

leontalbot14:11:26

Is this a good pattern for libraries?

(def ^{:dynamic true} *var*)
(defn my-fn [{:keys [var]}]
  (do-smth (or var *var*)))

rickmoynihan09:11:18

Not really. Binding *defaults* isn’t really a done thing. Normally you’d (merge defaults overrides). Can even do patterns like:

(def default-sentiment-labels ["foo" "bar"])

(defn my-fn [{:keys [labels] :or {labels default-sentiment-labels}]
,,,)

igrishaev14:11:05

@leontalbot sometimes, such global variables might be useful. Say, cls-http stores default middlewares in such a global vector. And there is a macro (with-middlewares...) that substitutes them temporary with binding

igrishaev14:11:45

but as long as you can avoid using them, please do.

leontalbot15:11:36

Nice answer from Joost Diepenmaat on SO: “In my experience, having dynamic arguments /almost/ always causes more trouble than it saves down the line. You need a pretty compelling reason to have them and in this case I would definitely just make *var* a non-dynamic default-var. Note that clojure.java.jdbc (like the example in the docs) used to have a dynamic default db argument but that was removed ages ago.

the-kenny16:11:00

Does anyone here have some strong thoughts on what a simultanuous put and take on the same channel (via alts) should do? In IRC someone brought up the following:

(let [c (async/chan)]
  (async/alts!! [c [c 42]]))
First thought is deadlock, but it actually executes both operations, and returns either [42 c] (the result of the take) or [true c] (the result of the put). This feels wrong, as the documentation clearly states it should execute at most one operation.

ghadi17:11:00

@the-kenny This is a weird one -- I'm not saying it's not surprising, but let me offer an explanation of what's going on: alts will attempt its requested ops in a random order. For each op it checks: Did it work immediately? If so return, if not try the next one. In this specific example, one of the ops is selected and attempted (doesn't matter which), and because the channel is unbuffered, that op is enqueued (aka doesn't succeed immediately). alts moves on to the next/other op, and tries it. This op will succeed immediately because the originally attempted op is the complement. Technically, alts is upholding its contract of exactly one op succeeding, but it's the succeeding op that unblocks and runs the other op, not alts itself.

ghadi17:11:44

(I'm one of the committers to that project.)

ghadi17:11:39

Just to put it on the record, it would be unusual to see this puzzler in the wild (as well as bidirectional usage of a channel within the same function)

ghadi17:11:19

(I lament that Slack history disappears)

Empperi17:11:03

It does not, it just gets hidden since no one pays for this slack organization

Empperi17:11:24

The second someone pays the whole history will be there

seancorfield17:11:06

Feel free to discuss that in #community-development (but we have 11,000 members and no one is going to fund this at $57,000 per month).

ghadi17:11:40

"effectively disappears" 😃

taylor18:11:49

isn’t there some off-site archive? I think I’ve found things on it via google before

ghadi18:11:20

it's discontinuous

zylox18:11:52

you can get around it to some degree if you use the irc gate. have an irc bot connected constantly and have it save logs.

zylox18:11:33

doesnt do well with the advent of threads though since those messages appear inline

viesti19:11:41

hmm, doesn't seem up to date though, something wrong with logbot

ghadi19:11:48

yeah it's discontinuous

viesti19:11:39

:sadpanda:

borkdude19:11:54

What does Rich mean when Lisp is ‘tangible’. I’ve looked up the word tangible and I found ‘substantially real’. which doesn’t really make it any clearer.

ajs19:11:57

Like something you can touch, feel, mold

john19:11:48

In that context, it's fair to say that macros make Lisp a more 'tangible' language than others

Alex Miller (Clojure team)19:11:46

data is directly readable without going through an interface, your runtime state is always manipulable, even your tooling is often changeable on the fly

Alex Miller (Clojure team)19:11:20

or at least that’s what it means to me

noisesmith19:11:49

I’d add to that that the things that make up your program state are concrete and explicit (reified as data), not ephemeral “fictions” that are enforced by a compiler but missing in the runtime data itself

borkdude19:11:42

ah that makes sense yes. when I’m programming in a more static / less interactive language, you can’t really play around with it, you’re not as close to the data. All you can do is watch the program unfold, unless you explicitly build hooks and monitoring into it

noisesmith19:11:03

even just the fact that you can take an arbitrary piece of data, and say “what type is this?” or print it and expect a reasonable result

borkdude19:11:36

right, thanks

nickbauman22:11:20

For me “tangible” means a REPL that is the whole thing of what a REPL means, coupled with homoiconicity.

nickbauman22:11:15

For a contrasting example with Python. Python occasionally spits out results in its REPL that’s homoiconic. Or almost homoiconic. I once implemented a bunch of classes’ __repr__ magic functions with a string that was that type’s call to its constructor. This, when used in a REPL, made my Python custom classes behave in a homoiconic way.

nickbauman22:11:22

But don’t be fooled. If python were made to be fully homoiconic by default yet because of the language, you’d have to implement it without the parenthesis, not many would ever use this feature because macros would be so much harder to write because of the grammar rules being so complicated.

nickbauman22:11:16

I think this is what Rich was getting at.

nickbauman22:11:24

Does that make any sense?

rymndhng23:11:04

how do i figure out out which version clojure has decided to call when doing interop. I'm trying to understand why I have to typehint the executor as java.util.concurrent.ExecutorService and the function as a Callable? What's the strategy used? i.e. is typehinting Callable not enough?

hiredman23:11:18

it depends, if the compiler can figure out that you are invoking the method on an Executor service, type hinting Callable is enough

hiredman23:11:22

if you use interop to construct an ExecutorService and bind it to a local and use that, the compiler can figure it out, if you create it as a global (via def) then it can't, but you can type hint the var if you want

rymndhng23:11:24

what's really weird is we were trying the same JVM version inside docker and outside docker and we got different results w/ the same code

hiredman23:11:07

I would not be surprised at that

rymndhng23:11:28

mind if i ask you to pick you brain to explain why you aren't surprised? 😉

hiredman23:11:36

the executor issue is tricky because the class of the thing you are passing in, introduces more ambiguity instead of narrowing the scope

hiredman23:11:01

functions implement both Callable and Runnable, so it could be either

rymndhng23:11:49

aye, I think what we're going to do to reduce ambiguity is to reify a Callable

hiredman23:11:16

I think it is a little odd that you would get differences with just inside and outside of docker, but I am perfectly happy to hand wave that away as you also introducing some other difference

rymndhng23:11:42

yeah it's really weird, we've gotten inconsistencies in other ways as well (trying tests in this order): - ran our test using lein test (on 2.7.2) and the right version of .submit was used - ran our test using lein test (on 2.8.1) and the the wrong version of .submit was used - ran our test using lein test (on 2.7.2) and the the wrong version of .submit was used <-- freaky

hiredman23:11:06

the version of lein has nothing to do with it

hiredman23:11:20

(well, has less to do with it then you might think)

hiredman23:11:51

the important thing would be the build of the jvm (version and os) and the clojure version (which lein version might effect)

hiredman23:11:10

e.g. if you are locally running on the jvm on osx, and comparing it to the jvm on linux in docker, many (not often noticeable) things will be different

rymndhng23:11:29

oo thanks for sharing haha

hiredman23:11:38

I had a colleague years ago who spent a lot of time tracking down some flapping tests for a date parser that turned out to be due to the osx and the linux build of the same jdk treating dates that claim to be in dst, but being for a month that dst is in effect for differently

rymndhng23:11:48

thanks, would I be able to avoid this ambiguiety by setting warn-on-reflection to true?