Fork me on GitHub
#clojure
<
2019-08-14
>
ahungry00:08:49

with lein profiles/injections, is it possible to ensure that clojure.repl is require/use'd in every name space during interactive development? like, the equivalent of a global require? So that (doc doc) would work no matter which ns I change into as I develop?

Alex Miller (Clojure team)00:08:27

In long, there are various plugins in various tools that try to do some version of this but they’re all kinda meh

4
ahungry00:08:20

thanks - I like reading it right in the repl as opposed to an editor interface (like cider/emacs buffer for doc) or on a website, but I guess I'll make due

Alex Miller (Clojure team)02:08:40

from all ns'es you can do (clojure.repl/doc foo)

Alex Miller (Clojure team)02:08:23

I actually use Cursive and instead use the key command to open the doc typically, but sometimes use the fq form if I'm not in user

murtaza5206:08:03

I have a fn #(set [% id]) which returns a set. It first creates a vector and then converts it into a set. Is it possible to this in one step like what the vector fn does.

vlaaad06:08:19

@murtaza52 #(hash-set % id)

valerauko07:08:44

(let [ary (int-array 2 2)]
  (aset ary 0 1 3)
  (aset ary 1 0 4)
  ary)
Why does this throw an error saying that ary is not an array?
Execution error (IllegalArgumentException) at java.lang.reflect.Array/set (Array.java:-2).
Argument is not an array

vlaaad07:08:43

there is something wrong with arguments

vlaaad07:08:26

args are array index val

vlaaad07:08:02

(let [ary (int-array 2 2)]
  (aset ary 0 3)
  (aset ary 1 4)
  ary)
works fine

valerauko07:08:32

Oh it's the behavior of int-array

valerauko07:08:47

(let [ary (make-array Integer 2 2)]
  (aset ary 0 1 (int 3))
  (aset ary 1 0 (int 4))
  ary)
this works as expected

vlaaad07:08:32

ah, it's nested arrays

Jakub Holý (HolyJak)08:08:06

Hello! Is there a predicate that is true only for vector, list, and set but not a map? Thanks!

valerauko08:08:22

#(not (map? %))

👎 4
Jakub Holý (HolyJak)08:08:45

Correct but not desriable solution. This is true also for 123 and :hello 🙂

valerauko08:08:42

Does it have to be a single predicate? You could just combine them #(or (vector? %) (set? %) (list? %))

Jakub Holý (HolyJak)08:08:14

I could of course. But a single predicate would be nicer. Otherwise I'd do (and (coll? %) (not (map? %)))

valerauko08:08:21

It becomes a single predicate if you defn it...

👍 12
hkjels09:08:26

It would be quite clean with some and juxt

Jakub Holý (HolyJak)10:08:13

Or perhaps something like this ((every-pred coll? (complement map?)) coll-under-test)

👍 4
jaihindhreddy11:08:40

#(and (instance? clojure.lang.IPersistentCollection %) (not (instance? clojure.lang.IPersistentMap %)))

Jakub Holý (HolyJak)12:08:08

I believe using Clojure's built-in predicates is better than comparing with interfaces (which is, in a way, an impl. detail)

meow12:08:21

For MacOS, is installing Clojure via homebrew, and then Boot, a good way to get up and going?

meow12:08:31

Is there a different pathway for those thinking about Clojurescript?

meow12:08:46

I think the JS world is converging on advice for up-and-going setups

meow12:08:26

Is there anything like that for Clojure or Clojurescript?

Jakub Holý (HolyJak)12:08:47

have a look at #plum, it intends to be user-friendly tool for getting started. But it targets clj / #tools-deps , not Boot.

meow12:08:23

is shadow-clj similar but for clojurescript?

alpox12:08:36

shadow-cljs is very easy to get going and works very well with the npm ecosystem. I can highly recommend it for all ClojureScript development.

herald13:08:31

I see shadow-cljs often recommended if you're planning to use a lot of npm packages with clojurescript. Otherwise, tools.deps is pretty popular nowadays, although most older projects you find will be using leiningen. (this also applies to clojurescripts)

herald13:08:05

I'd recommend going for tools.deps like holyjak says, for both clojure and clojurescript, to get up and started [=

meow13:08:13

Does someone in Clojurescript typically have some kind of dev process where they also code a backend in Clojure?

meow13:08:31

And can shadow-cljs do it all?

herald13:08:42

if they want a backend, they'll usually include the clojure code in the same project as well, yes. (sharing code between the backend and frontend is very easy with .cljc files) I highly doubt shadow-cljs can do it, but you could ask in #shadow-cljs if you want to be sure. (the rest, ie. boot, leiningen and tools.deps can however)

alpox13:08:25

I heard that shadow-cljs can be used through leiningen. I ran them seperately until now.

murtaza5215:08:02

@U0522TWDA can you post a link to plum, googled it but cant find anything on it.

meow15:08:18

Is there like a major blog post that people refer to for setting up their Clojure development environment?

ghadi15:08:53

there are a ton of resources -- lots of choices, depending on platform

ghadi15:08:00

may I suggest hitting up #beginners ?

murtaza5215:08:42

@slack1899 https://corfield.org/blog/2018/04/18/all-the-paths/ - this gives some history / overview on clojure build tools

murtaza5216:08:30

@slack1899 this can also be helpful - https://github.com/clojure/tools.deps.alpha/wiki/Tools#versioning-and-releasing - listing of different tools which build on tools.deps

lilactown16:08:40

meow, the guide on the Clojure site does a good job of going through the basics

lilactown16:08:05

Are you looking for something other than how to install the CLI?

borkdude18:08:30

I guess this can never happen in Clojure? just want to make sure:

(let [%x 1] #(+ %x 1))

borkdude18:08:10

what I want to make sure: if a symbol in a fn literal starts with percent, it's not something from the outer scope

Daniel Slutsky18:08:58

@danielsz’s article about Lisp, following Heart of Clojure, is now #1 at Hacker News: https://news.ycombinator.com/item?id=20696931 .

noisesmith18:08:07

@borkdude nobody sane would do it, but it's legal

borkdude18:08:52

@noisesmith not sure, because I can't get it to work in both CLJS and CLJ

john21:08:50

it happens to be legal in the reader phase, so users using weird tagged readers could be using those, IIUC

noisesmith18:08:13

oh wow, I thought it would be legal, but testing it I guess it's not

borkdude20:08:38

how does clojure decide what are the command line args to a script?

clj -e '(println *command-line-args*)' 1 2 3
(2 3)
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
1 (No such file or directory)

Alex Miller (Clojure team)20:08:03

I believe the command-line-args only apply to main classes

Alex Miller (Clojure team)20:08:48

here clojure.main is taking two commands -e and an expression and the last args are being interpreted as a script to run (1) and the args to it (2 3)

Alex Miller (Clojure team)20:08:31

so this isn't a valid command, which is making it kind of weird

noisesmith20:08:07

@borkdude

$ clj -e '(println *command-line-args*)' - 1 2 3 </dev/null
(1 2 3)

noisesmith20:08:18

that asks it to read from STDIN, then sends EOF on STDIN

noisesmith20:08:41

alternate, golfed

$ echo '(println *command-line-args*)' | clj - 1 2 3
(1 2 3)

markw22:08:54

when implementing ISeq on a deftype, is it required to also place the ISequential marker protocol on the deftype?

noisesmith22:08:26

what is ISequential? if it exists it isn't in clojure.lang

markw22:08:35

Sorry just Sequential

markw22:08:01

clojure.lang.Sequential to be precise, I would hope that was implied

markw22:08:38

I usually don't mess with deftypes but just now I was messing around and had a type that fully satisfied clojure.lang.ISeq, yet would complain that nth was not supported on the type

markw22:08:09

i somewhat instinctually looked for protocols that may be associated with that method, found Indexed and Sequential, figured Indexed didn't make sense for my case and just shoved Sequential in there and all my problems went away.

markw22:08:23

but I kind of just blindly did it based on a hunch

markw22:08:04

ahh so that's called before Seq is actually called

markw22:08:46

provided it's not any of the prior cases (charsequence, array, matcher etc.)

markw22:08:00

so without Sequential it can't even call it's own seq implementation

noisesmith22:08:04

hmm, even if you have Seqable I guess

markw22:08:29

yeah i had Seqable implemented

markw22:08:42

this took me quite a while to blindly stumble my way into

markw22:08:08

One more question ... when defining a function that shadows an existing protocol method in the same namespace, I was surprised that the protocol version still was visible. I assumed that latter defn would clobber the protocol version and this wouldn't work for example:

markw22:08:43

So it appears that the polymorphic version is still in the namespace, despite that I've defined over it. How does that work? Does the call to (some-thing 10 thing) somehow know there is an existing polymorphic version and check the types there first before dispatching on the "catch-all" (unimplemented) version or something? I wouldn't think so because for fallthrough implementations you have to explicitly implement them on Object.

ghadi22:08:30

the definition on L8 is shadowing the protocol def

ghadi22:08:01

you're in the realm of undefined behavior here

markw22:08:52

but it actually doesn't outright shadow it, because the body of the same function correctly dispatches on the first argument (the protocol version is called)

markw23:08:34

or maybe a better description is that it shadows it, but somehow the protocol version is still available in the namespace when called with the appropriate arguments

hiredman23:08:37

protocol functions have some metadata attached which the compiler uses to guide how they are compiled and re-defing doesn't clear that metadata

hiredman23:08:54

so some-thing is being compiled as a protocol call when it shouldn't be

markw23:08:01

i was going to say... it's as if every single call to some-thing is dispatching on it's type, whether or not implemented as a protcol method

markw23:08:20

like somehow the subsequent global def is being added to the protocol table as a catchall or something

markw23:08:23

i don't literally thing that is happening... i said "as if"

markw23:08:14

I would probably make the protocol version -some-thing to avoid any confusion, but I was surprised nonetheless that the shadowed version was available

hiredman23:08:26

it is a weird compiler bug and you shouldn't use it as a feature or try to explain how it is working, which is what @ghadi was getting at by calling it undefined behavior

hiredman23:08:15

if you create a protocol function then def it as a normal function, assume the compiler is going to output code that will zero out your hard drive

4
markw23:08:27

yah, i know the standard behavior is to prefix the protocol method with "-" and wrap that if needed

markw23:08:56

I was more curious when I accidentally wrote the code how it was working, not planning on using it for real stuff

markw23:08:04

just trying to understand

noisesmith23:08:05

why even use the same name in the same namespace?

markw23:08:21

strictly for my own education, I am not suggesting this is a good pattern

markw23:08:07

again, i would just do (defn some-thing [x this] (-some-thing this x)) if i needed this

markw23:08:08

Just trying to correct my mental model of how protocol definition/dispatch works, which was obviously not quite right when i stumbled on this

mfikes23:08:35

FWIW @creditobrasil the call (some-thing 10 thing) in your example causes a stack overflow in ClojureScript

markw23:08:27

that's what I would have expected

markw23:08:48

I'm not complaining or anything... just curious what's going on under the hood

mfikes23:08:36

Yeah, I suspect ClojureScript's behavior matches your mental model. 🙂

markw23:08:45

good enough for me

mfikes23:08:06

Even then, ClojureScript is a bit tricky (and I think so is Clojure) because the compiler can see and optimize a "self call"

markw23:08:17

i'll just stick with @hiredman's recommendation and assume any use of the shadowed version as presented will rm -rf my drive

mfikes23:08:39

I could also evoke the dancing frog.

hiredman23:08:49

(re: optimizing self calls)

mfikes23:08:05

Clojure doesn't do anything with self-calls? Cool.

hiredman23:08:40

and calling it undefined behavior is kind of stretch too because that assumes a definition where it is left out so as to be undefined

hiredman23:08:56

and there rather pointedly isn't a spec for clojure or clojurescript

mfikes23:08:33

ClojureScript often uses Clojure for that purpose. 🙂

hiredman23:08:35

so if you call it a bug in the compiler that is hard to fix or undefined behavior to some degree depends on how close you orbit to rhickey

mfikes23:08:45

Hrm, (doc def) seems to double the copy... wonder if that is a regression.

noisesmith23:08:15

there's an extra "Please see" in the middle, yeah

noisesmith23:08:19

happens with if too

mfikes23:08:05

I was curious about whether it is specified that the init in a def can refer to the name being defined.

noisesmith23:08:21

you can see it if you squint and read between the lines (the fact that it creates the binding, and then evaluates init, implies that the init can use the binding)

mfikes23:08:37

yeah, I agree