clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
Cj Pangilinan 2020-10-27T01:53:06.258200Z

Good day! Does it makes sense if I use Clojure from Java? The reason is I am one of the team members in a project that uses Spring Boot and I am thinking of including the clojure jar as one of the maven dependencies. Then I will code some of the business logic in Clojure and call it from Java/Spring Boot while the other team members code in Java. I don't know yet how to call Clojure code from Java. Is it just using Reader, IFn, Clojure.var, etc? What are the recommended ways to mix the use of these 2 languages in a project if the team is composed of Java developers and Clojure developers?

2020-10-27T02:03:17.258800Z

@cjpangilinan it's quite easy https://clojure.org/reference/java_interop#_calling_clojure_from_java - clojure automatically initializes when you use it

👍 1
2020-10-27T02:06:40.261Z

As regards to how to organize things, I'd say it's similar to how any two subprograms are combined, though you should put more thought into it up front when crossing languages. Use require / IFn to get at and use clojure stuff from java, make sure the java side doesn't force you to do concrete inheritence or annotations which are clumsier on the clj side

emccue 2020-10-27T03:34:46.262100Z

@cjpangilinan You very much can, but if I had to guess it probably won't be the best way to introduce clojure to your team

emccue 2020-10-27T03:35:21.262600Z

Clojure really isn't "full duplex interoperability" like kotlin, and that tends to show

👍 1
vncz 2020-10-27T03:39:23.262700Z

Is there a better way to write this?

vncz 2020-10-27T13:19:29.277900Z

vncz 2020-10-27T03:39:59.263400Z

I find myself often in this situation where based on the result of an if I should either return X or a modified version of X

2020-10-27T03:43:51.263800Z

for starters (if-not t ...) unless you expect false

2020-10-27T03:44:42.264600Z

how about #(cond-> % t (assoc :response {:status ... :headers ...}))

seancorfield 2020-10-27T03:58:47.265600Z

Yeah, I tend to reach for cond-> straight away for conditional modification of something.

seancorfield 2020-10-27T03:59:40.266600Z

We have a condp-> macro at work that is a variant that threads through the predicate, so I'd probably write

(condp-> t
  some? (assoc :response ...))

Mikko Harju 2020-10-27T05:22:03.268400Z

I upgraded to OS X Catalina and in the same time upgraded my brew packages, when I invoke clj -A:nREPL -m nrepl.cmdline -i I get

WARNING: When invoking clojure.main, use -M
– I could not find any references when I searched around a bit. What is this related to? Thanks!

orestis 2020-10-27T05:42:16.269400Z

@mikko can’t find the change log, it’s a new release of the CLI tools: https://clojure.org/reference/deps_and_cli

orestis 2020-10-27T05:43:02.269800Z

Here’s the release notes: https://clojure.org/releases/tools#v1.10.1.697

Mikko Harju 2020-10-27T06:04:17.269900Z

Oh, so it's clj -M:nREPL -m nrepl.cmdline -i now!

Mikko Harju 2020-10-27T06:04:37.270100Z

Thanks! 🙂

Mikko Harju 2020-10-27T06:05:26.270300Z

Using that, the warning went away.

Hankstenberg 2020-10-27T08:05:24.273Z

Hi guys, I'm trying to use a Clojure function that returns an Array of Strings in Java. In the clj file I have: :methods [#^{:static true} [myfunc [String] "[Ljava.lang.String;"]]) (defn -myfunc [arg] .... (into-array (map str (keys some-sequence)))) When I try to invoke it from inside a Java class I'm getting: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String; Does anybody have an idea why?

thom 2020-10-27T08:07:16.274100Z

You want (into-array String ...) to give you a string array instead of an object array.

Hankstenberg 2020-10-27T08:10:41.275100Z

Wow, thanks! It even says that in the documentation of into-array. Wouldn't have thought that there's any special coercion functionality in that function. Much obliged!

Dosbol 2020-10-27T09:49:04.276600Z

Hi guys, is there any open-source ERP/CRM solutions in clojure(or wrapper) ? Thanks

vncz 2020-10-27T12:36:30.277500Z

@noisesmith @seancorfield Thanks for the pointer. I was also thinking about cond-> but I guess I haven't understood how to use it properly yet since it didn't look like it'd fix my use case

vncz 2020-10-27T13:18:39.277800Z

Oh ok I think I understand now

slipset 2020-10-27T14:55:59.281400Z

How come (= 3) ;; => true but (=) throws. This bites when (apply = xs) and xs happens to be nil or empty?

dpsutton 2020-10-27T15:05:43.282800Z

should (=) return true or false?

abdullahibra 2020-10-27T15:05:48.283Z

Hi everyone, is there something like tree-seq which could keep the structure of the tree?

abdullahibra 2020-10-27T15:06:23.283800Z

i'm at situation of: i have https://nlp.stanford.edu/nlp/javadoc/javanlp/edu/stanford/nlp/trees/LabeledScoredTreeNode.html and want to convert to into native clojure

slipset 2020-10-27T15:06:47.284300Z

@dpsutton I'd say (= (=) (= nil)) (if that hadn't thrown an exception 😉

2020-10-27T15:07:00.284400Z

Unlike + or *, = doesn't really have a natural identity value, mathematically speaking.

slipset 2020-10-27T15:07:39.284600Z

But how does then (= nil) make any sense?

dpsutton 2020-10-27T15:07:52.284800Z

yeah i agree that the single arity doesn't really make sense

2020-10-27T15:08:17.285Z

Not saying (= nil) makes perfect sense, but it makes more sense than defining a return value for (=) , IMO

dpsutton 2020-10-27T15:08:36.285200Z

but i'm not sure i agree that boolean logic doesn't have identities. seems false is the additive identity and true is the multiplicative identity, just like 0 and 1 under + and *

2020-10-27T15:09:02.285400Z

I think identity elements for or and and make sense, but less so for =

dpsutton 2020-10-27T15:09:04.285600Z

x || false = x for all x and x && true = x for all x

slipset 2020-10-27T15:09:11.285800Z

Thats like saying (> (* 2 (/ 1 0)) (/ 1 0)) 🙂

2020-10-27T15:09:36.286Z

There is no value you can add to a list of (= a b c <insert-something-here) that preserves the return value for all values of a, b, c

dpsutton 2020-10-27T15:09:38.286200Z

oh you're right andy. i'm conflating things

2020-10-27T15:09:49.286400Z

You can do that for or and and (modulo short-circuiting behavior)

dpsutton 2020-10-27T15:09:57.286600Z

good point. thanks

slipset 2020-10-27T15:09:58.286900Z

That last one was to @andy.fingerhut claiming that (= nil) makes more sense than (=) 🙂

2020-10-27T15:10:29.287100Z

I don't understand the logic of your statement.

slipset 2020-10-27T15:11:29.287300Z

To me, saying that (= nil) makes more sense than (=) makes as much sense as saying that (* 2 (/ 1 0)) is greater than (/ 1 0)

2020-10-27T15:11:56.287500Z

I said "Not saying that (= nil) makes perfect sense". If you want me to back down from that, well, it isn't exactly a firm conviction in the first place, as I tried to convey (apparently unsuccessfully).

slipset 2020-10-27T15:12:39.287700Z

It was the , but ... that followed I was commenting on.

slipset 2020-10-27T15:13:11.287900Z

But I'm far away from being certain on anything in these matters. You actually wrote the guide on equality in Clojure.

2020-10-27T15:13:20.288100Z

I think it makes 0 sense to define a return value for (=) . I think it makes 1% sense to define a value for (= x) as true.

quoll 2020-10-27T15:13:40.288300Z

While I agree with this, the multi-arity = returns true when: ∀x∈S, ∀y∈S : x = y or ∀x∈S, ∄y∈S : ¬(x = y) When S is ∅ then both the above statements hold. So I think it’s valid to return true when applying = to the empty set

2020-10-27T15:14:09.288500Z

I can't exactly get worked up about the 1-arity = case in any particular direction, and it is less than 1% likely to change in Clojure.

slipset 2020-10-27T15:14:40.288700Z

I guess what I get worked up about is that this leads to unexpected runtime errors.

slipset 2020-10-27T15:14:54.288900Z

Much like the two-arity reduce can do.

2020-10-27T15:15:06.289100Z

Lots of things in Clojure lead to unexpected run time errors, if your expectations do not match the Clojure implementation. This is a fact of life 🙂

2020-10-27T15:16:03.289300Z

I am not thereby arguing that no one should ever ask about these things, or attempt to see if they ought to be changed. I've filed more issues than most people about nits like this.

slipset 2020-10-27T15:16:29.289600Z

This is also true, but this specific class of errors, applying a function which doesn't have a zero-arity variant to a list that sometimes empty, is not a class of errors I'm often considering.

2020-10-27T15:17:46.290200Z

@quoll That is almost true. Technically, it is when adjacent pairs all return true for =. There is no checking of all pairs performed.

slipset 2020-10-27T15:17:50.290400Z

I guess what I'm saying is that I'm totally fine with (apply < [1 2 \a]) throwing, but I'll always be surprised when (apply < xs) throws because xs is nil

2020-10-27T15:18:21.290600Z

You can write your own less-than function that doesn't surprise you.

slipset 2020-10-27T15:18:50.290900Z

I could write my own language that doesn't surprise me 🙂

quoll 2020-10-27T15:18:55.291100Z

(defn apply= [s] (or (empty? s) (apply = s)))

2020-10-27T15:19:14.291300Z

Sure can. Everywhere is walking distance if you have the time 🙂

quoll 2020-10-27T15:20:04.291500Z

> That is almost true.  Technically, it is when adjacent pairs all return true for `=`.  There is no checking of all pairs performed. I believe that is an implementation artifact, and not part of the definition

2020-10-27T15:21:15.291700Z

The definition you gave is a perfectly logical mathematical definition. It isn't part of the implementation, although the implementation is certainly guided by such ideas at some point.

quoll 2020-10-27T15:22:21.291900Z

I have lecture notes from 1989 that show a proof for: > if l=m and m=n then l=n We spent an hour on it, proving it via 2 methods. I only remember the second one. This was the class that convinced me that I was not interested in pure mathematics

2020-10-27T15:22:22.292100Z

If someone finds a case where = is not transitive, though, and (= a b c) returns true but (= c a b) returns false because of the implementation, and you point out that definition, what do you expect will happen? My expectation is "fix the non-transitive = implementation, if you can. If you can't, sorry"

quoll 2020-10-27T15:24:01.292300Z

My perspective here is that = is implemented in a way so as to express the mathematical concept as closely as possible. The implementation does not cover the case of (=) and the question raised was, “What does a zero-arity = even mean?”

2020-10-27T15:24:41.292500Z

Yep, and we talked about 4 mathematical functions that have very natural choices for identity elements, but = isn't one of them.

quoll 2020-10-27T15:25:10.292700Z

I proposed an answer to that. It doesn’t actually matter for the implementation, since the implementation is not going to change. But it should guide anyone who is wanting to apply = to an empty sequence

2020-10-27T15:25:56.292900Z

It looks like a fine definition to justify someone's choice of what their (my-custom-equals) function returns.

seancorfield 2020-10-27T16:12:24.293900Z

That argument would certainly persuade me that (=) should be true if anyone ever implements it...

2020-10-27T16:56:57.294600Z

Note that a change to (=) behavior could be considered by some as a breaking change, i.e. they expect it to throw an exception, because it has before. I have no knowledge of whether the Clojure core developers consider that a concern or not, for such changes, but it might be. Sometimes backwards compatibility means things that were error before remain an error in the future.

2020-10-27T16:57:57.294800Z

This description of Hyrum's Law is a good short read, if you haven't seen it before: https://www.hyrumslaw.com/

seancorfield 2020-10-27T17:11:15.295Z

Yeah, I have had cases in projects where I've fixed a bug and then had users complain that they depended on the previous (buggy) behavior... and I've usually introduced some sort of flag that allows folks to choose which behavior they get (HoneySQL has several such flags at this point!).

quoll 2020-10-27T17:34:16.295600Z

I think in this case that it’s not about (=), since no one would call that. But rather what happens when = is applied to a seq and the seq happens to be empty. Which means that it just needs a function for applying = to a seq, and not changing =. Since it’s a boolean result, the function would be either: (defn apply= [s] (or (empty? s) (apply = s))) or (defn apply= [s] (and (seq s) (apply = s))) (I argue that it should be the former, as already stated).

2020-10-27T17:41:21.295800Z

Even if no one would call (=) in that form in their code, it seems like slipset is exactly concerned with the case of calling (apply = xs) where xs is an empty sequence or collection, and doesn't want an exception in that case. He knows he can write his own custom function for this. If he was content with that solution, I don't think we would have had a discussion with so many comments.

quoll 2020-10-27T17:42:30.296100Z

I was focused on the question asked at the top of this thread

slipset 2020-10-27T17:46:11.298300Z

This is correct. I’m first and foremost concerned with the apply thing. What the semantics of (=) is, is a side effect of the first concern.

seancorfield 2020-10-27T17:50:07.298500Z

There are several functions in Clojure that accept one or more arguments but not zero arguments and apply is painful for all of those (of course, now I can't actually remember what other functions I've seen people complaining about). I think we also have the situation that some n-arity functions have different semantics for their 0-arity form, returning a transducer? (again, can't think of an example right now)

roklenarcic 2020-10-27T17:56:56.300700Z

I’ve used depstar to make a JAR of my library. Verbose output explains that it’s been compiled by JDK 14: Build-Jdk: 14.0.1 . I am worried if people with JDK 8 will be able to use my library.

slipset 2020-10-27T18:03:15.302700Z

The transducer ones I don’t mind, but <,>,=,not= all come to mind as the ones I mind.

roklenarcic 2020-10-27T18:03:30.303100Z

Ah I see that JAR contains only .clj files, but what if any part of it was AOTed? How to select the java version level for those class files?

alexmiller 2020-10-27T18:06:22.303400Z

I would recommend using source and target of 8

alexmiller 2020-10-27T18:06:29.303600Z

Clojure itself is AOT compiled with Java 8

alexmiller 2020-10-27T18:07:05.304100Z

Most likely mixing the two is fine (but will require at least Java 14 to run an application, which may not be what you want).

seancorfield 2020-10-27T18:12:20.305200Z

Library JARs should not be AOT compiled in general. Uberjars can be AOT'd but the expectation is that you would run them yourself and you control the JVM environment on which they run @roklenarcic

borkdude 2020-10-27T18:13:23.306Z

one example: I publish an (uber)jar for the VSCode clj-kondo extension which only requires people to have Java (8>=) on their system

borkdude 2020-10-27T18:13:44.306400Z

I make sure I compile with 8 (by printing the java version before compilation, there are better ways)

borkdude 2020-10-27T18:14:21.306800Z

I use jenv to quickly switch between java versions per project or shell

borkdude 2020-10-27T18:18:10.307200Z

I guess I could not AOT this and rely on clojure main to invoke this right?

borkdude 2020-10-27T18:18:28.307500Z

if clojure was part of the uberjar

borkdude 2020-10-27T18:18:38.307800Z

java -jar clojure.main -m ...

2020-10-27T18:39:05.308400Z

surely java -cp some.jar clojure.main -m ...

victorb 2020-10-27T18:56:22.310900Z

Is there something like JS' "Shorthand property names" in clojure.core? I'd imagine there is some macro that creates {:a 1 :b 2 :c 3} from (let [a 1, b 2, c 3] (shorthand [a b c]))

victorb 2020-10-28T09:33:36.337300Z

These are all great, thanks folks!

victorb 2020-10-27T18:58:34.311Z

(defmacro as-map [&amp; syms]
  (zipmap (map keyword syms) syms))
also does the trick

❤️ 1
2020-10-27T21:41:26.311700Z

related

(ins)user=&gt; (defmacro locals [] (into {} (map (juxt keyword identity)) (keys &amp;env)))
#'user/locals
(ins)user=&gt; ((fn [x] (let [y (+ x x)] (locals))) 21)
{:x 21, :y 42}

borkdude 2020-10-27T22:07:39.311900Z

@victorbjelkholm429 I have this one in a project I work on:

(defmacro -&gt;map
    "(-&gt;map a b) ;;=&gt; {:a a :b b}"
    [&amp; symbols]
    (assert (every? symbol? symbols))
    `(hash-map
      ~@(interleave (map keyword symbols) symbols)))

Jakub Holý 2020-10-27T22:16:07.314800Z

hello! is there a good way to check whether a function (passed as an argument) has 0 or 1 arity? (I am trying to find a non-breaking way to evolve an API that previously took a 0-arg callback while I want to start sending it an argument, w/o breaking all existing clients)

wilkerlucio 2020-10-27T22:18:43.317800Z

hello, is there a way to leverage the structural sharing for transfering data? my use case is that I have a map that goes though a complex series of operations until its done, to help with debug I'm doing snapshots of this map as the program builds it up. while running on the machine I get the memory savings from structural sharing for free, but I also need to transfer that data (all the snapshots) over the wire, and if I do that, than there is no structural sharing to help reduce the data size. so I wonder if there is a solution around for that

2020-10-28T09:24:29.337100Z

@wilkerlucio I wrote some compression code in Clojure that keeps a dictionary of items that it comes across. So if anything occurs twice you get compression, this happens recursively. It also allows the use of an external dictionary (/ schema) for common items mapped onto integers for extra compression. The resulting compressed datastructure is serialized via transit. All this comes at the cost of some cpu (I think, didn’t measure), but it is much smaller than any other option (gzip, plain transit etc). If you want more details please let me know. I’m also thinking about new options like data templates

2020-10-27T22:20:21.317900Z

AFAIK the function object itself doesn't expose that information

borkdude 2020-10-27T22:20:54.318400Z

@holyjak Only in the unsupported realm of hacks: https://stackoverflow.com/questions/1696693/clojure-how-to-find-out-the-arity-of-function-at-runtime

2020-10-27T22:21:01.318900Z

@wilkerlucio transit does some structural sharing, there might be something else that does it more aggressively

borkdude 2020-10-27T22:21:22.319Z

What I mostly end up doing when designing an API is MIMO: map in, map out. This has enough flexibility for future extension

borkdude 2020-10-27T22:24:33.319600Z

you could also just catch an ArityException and handle the old case in the catch

2020-10-27T22:26:38.319800Z

thinking out loud - you could also use dynamic bindings instead of providing the values as args (the way clojure.test encourages for example)

2020-10-27T22:26:50.320Z

but using a hash map in the first place definitely wins

borkdude 2020-10-27T22:27:18.320200Z

metadata opts on the fn also works

borkdude 2020-10-27T22:27:26.320400Z

bit of a hack maybe, but it works

Jakub Holý 2020-10-27T22:30:38.320700Z

Thank you all! What do you mean by metadata opts, @borkdude ? The metadata added automatically by clojure for regular functions? That could be a good optimization to try but they will be missing for anonymous fns / lambdas so I would still need to catch the ArityExc. @noisesmith Yeah, I thought about dynamic bindings but it feels very non-functional and opaque, passing data like that, I prefer an explicit solution.

borkdude 2020-10-27T22:32:33.320900Z

@holyjak Never mind, the metadata solution won't work. I think the ArityException solution might be the least hacky if you want to keep supporting the 0-arity

2020-10-27T22:34:14.321300Z

I'd say (try (f x) (catch ArityException _ (f))) is the simplest (and performs better than the reflection option)

👍 1
borkdude 2020-10-27T22:34:38.321500Z

yep

alexmiller 2020-10-27T22:43:32.322400Z

I hate to suggest it but java serialization is probably the best example of that

alexmiller 2020-10-27T22:43:50.322900Z

Objects in the stream are only transferred once

alexmiller 2020-10-27T22:44:41.324100Z

I don’t recall if Clojure collections are customized though in such a way that would foil structural sharing, can’t look atm

2020-10-27T23:02:50.324900Z

@wilkerlucio @alexmiller a simple proof of concept, the baseline usage for clojure data structures is a bit large

(defn to-bytes
  [&amp; data]
  (with-open [b (ByteArrayOutputStream.)
              stream (ObjectOutputStream. b)]
    (doseq [d data]
      (.writeObject stream d))
    (.toByteArray b)))

(defn from-bytes
  [ba]
  (with-open [bs (ByteArrayInputStream. ba)
              stream (ObjectInputStream. bs)]
    (into []
          (take-while (complement #{::done}))
          (repeatedly
           #(try
             (.readObject stream)
             (catch IOException _ ::done))))))
(ins)user=&gt; (to-bytes {:a 0 :b 1})
#object["[B" 0x4784013e "[B@4784013e"]
(ins)user=&gt; (def b *1)
#'user/b
(ins)user=&gt; (count b)
536
(ins)user=&gt; (from-bytes b)
[{:a 0, :b 1}]

phronmophobic 2020-10-27T23:04:24.325Z

is there any way to show that this method takes advantage of structural sharing of clojure's data structures?

2020-10-27T23:04:58.325200Z

working on that now - making a relatively large structure and putting it in multiple spots in a parent coll

🦜 1
phronmophobic 2020-10-27T23:08:27.325800Z

I've long been interested in the idea of being able to have a poor man's database just by doing (write-to-disk-on-change my-atm) and it would simply write the atom to a file and as long as you're just conjing onto some clojure data, it might theoretically be able to sync with the on-disk file incrementally. still not sure it's a good idea

2020-10-27T23:08:58.326Z

this is what databases are for right?

phronmophobic 2020-10-27T23:10:08.326200Z

yea, but it may be ignorance of the options, but if I have some nested maps, is there a database that can sync incrementally the whole nested data structure?

phronmophobic 2020-10-27T23:10:29.326500Z

for example, a map that holds all the UI data for a re-frame app

jmckitrick 2020-10-27T23:11:42.327700Z

When it comes to the ‘heavies’ in the Clojure community (years in the field, active in core development, etc), what’s the approximate distribution of CIDER, Cursive, etc? Any idea?

mpenet 2020-10-28T08:55:01.333700Z

most companies/startups I worked with have a split emacs/cursive with more users on emacs. I have seen many go from cursive -> emacs after a while (usually juniors) and can't recall one doing the opposite.

mpenet 2020-10-28T08:55:55.333900Z

about inf-clojure I think that's quite uncommon outside of rh, stu and a few others. Personally I don't know a single dev who uses it exclusively

mpenet 2020-10-28T08:57:38.334100Z

I don't see a reason not to use cider if you're on emacs really. I guess for core dev you might want something very minimalistic to avoid "false signals", but otherwise cider brings a ton of useful features

vlaaad 2020-10-28T08:58:55.334300Z

I went from emacs to cursive 🙂

mpenet 2020-10-28T08:59:13.334500Z

I personally know only 1 that used vscode, he's on cursive now

mpenet 2020-10-28T08:59:46.334700Z

@vlaaad yeah I guess ymmv, it's very difficult to have an overview of this stuff even with the survey imho

mpenet 2020-10-28T09:00:33.334900Z

I doubt the majority of clojure devs I know from work fill the survey

mpenet 2020-10-28T09:02:41.335200Z

it's good to have a few decent choices, we're not going to settle the editor wars anyway 🙂

cfleming 2020-10-28T09:02:59.335400Z

I definitely know of a lot who have gone Emacs->Cursive, including several that everyone has heard of

cfleming 2020-10-28T09:03:12.335600Z

But I tend to hear about those cases I guess 🙂

mpenet 2020-10-28T09:03:27.335900Z

sure, I mentioned what I saw in my entourage, I don't doubt that

cfleming 2020-10-28T09:04:17.336100Z

Sure, and no problem either way, like you say we have good options, and a lot depends on the culture you’re surrounded by too - it’s just easier to use what most in your group are using.

cfleming 2020-10-28T09:04:33.336300Z

Or what you’re already used to.

mpenet 2020-10-28T09:04:41.336500Z

yes, I think if you've been using emacs for 20 years you're less likely to move to something else

seancorfield 2020-10-28T15:27:59.340Z

I used Emacs for years but switched, and I know several Emacs users who prefer inferior mode, so it depends on who you know 😊

mpenet 2020-10-28T15:47:51.340200Z

sure, as I said we mostly report anecdotal records, the conclusion imho is that tooling is good and we're fortunate to have quite a few good choices available. I wouldn't say one is better than the other just because some people around me use it (or not)

2020-10-28T16:55:33.344200Z

I went from emacs/cider to emacs/monroe before switching to vim, currently I alternate between neovim/fireplace and neovim/vim-clojure-static

mpenet 2020-10-28T16:57:04.344500Z

Neovim looks really nice now

mpenet 2020-10-28T16:58:26.344700Z

I have heard good things about conjure

jmckitrick 2020-10-28T18:13:58.348200Z

I’m about to make a big move career-wise into Clojure, and I’ve been using emacs/CIDER for a very long time. But I’d hate to miss out on really great stuff in Cursive just out of stubbornness.

seancorfield 2020-10-28T18:24:11.348500Z

Yeah, I hear great things about Cursive but I dislike IntelliJ immensely 😐 The company even gave me free licenses of it to review a few different versions some years back but I just hated it 😞

seancorfield 2020-10-28T18:26:06.348700Z

My advice is to use whatever editor you're most comfortable with, as long as it has a (reasonable) Clojure integration -- but I'm in the camp of minimal tooling so as long as you can: load a file into the repl, eval a form into the repl, pull up docstrings easily, maybe run tests via a hot key... that's about all I care about.

💯 1
seancorfield 2020-10-28T18:26:44.348900Z

(I never type into the REPL so having any sort of "integrated REPL pane" is not useful to me)

jmckitrick 2020-10-28T18:42:31.349300Z

@seancorfield before I totally commit to full-on CIDER, I’d be willing to try a minimalist setup. One on emacs and one on a different editor. I guess that would be emacs and clojure-inferior, then atom and a REPL. I’d probably lean toward emacs, especially if it’s super responsive with such a setup. But unless it’s very compelling, CIDER is probably going to be my choice.

seancorfield 2020-10-28T18:46:40.349500Z

If you already like CIDER, I think you'd find inferior-mode to be disappointing. My main focus is so that I have the same experience "everywhere" so I can connect my editor to a Socket REPL in a running program -- locally or remotely -- and have the exact same editor experience as I would have with a local REPL (and I don't want CIDER/nREPL/middleware in my running programs).

jmckitrick 2020-10-28T18:48:07.349700Z

That makes sense… connecting to a running instance should be as lightweight as possible.

2020-10-27T23:26:05.327800Z

there's a yearly survey that asks about tooling / editors etc. but I don't think it's broken down to cross reference experience and tooling together

Jakub Holý 2020-10-27T23:40:14.328100Z

thank you!

seancorfield 2020-10-27T23:43:09.328500Z

I can't remember if the survey writeup also makes the raw data accessible, but that would be the way to figure it out I guess.

cfleming 2020-10-27T23:44:33.328700Z

My impression is that it’s probably roughly 50/50 Cursive/Emacs. But on the Emacs side my impression is also that a lot of the more experienced people tend to use simpler Emacs setups, i.e. probably clojure-mode but not CIDER. I have no data to back that up though.

seancorfield 2020-10-27T23:45:24.328900Z

I get the impression that the "heavies" use the tooling in roughly the same percentages as the overall community, with a slightly heavier lean toward Emacs. Yeah, what Colin said...

seancorfield 2020-10-27T23:46:41.329100Z

Rich and Stu (and several other "long-timers") use Emacs in a fairly minimal configuration: inferior-mode, plain REPL, perhaps via a Socket REPL in some cases?

seancorfield 2020-10-27T23:50:31.329300Z

If I ever went back to Emacs, I'd probably go down that path instead of CIDER. Ideally, I'd want a way to connect Emacs to a Socket REPL. I'm probably a bit of an outlier as I used Emacs on and off since way back in its 17.x version days, and came back to it once I got into Clojure a decade ago after trying a few other editors. But then I switched from Emacs to Atom back in 2016 I think? And I use Atom/Chlorine, a Socket REPL, and a deliberately minimal set of key bindings and commands now. I was using Cognitect's REBL but I've switched to Reveal now for the most part (because it's easier to customize and it's getting new features faster).

seancorfield 2020-10-27T23:51:35.329500Z

We run Socket REPLs in a lot of our processes, so having an editor that can connect to a Socket REPL and eval code from source files that way is very important to my workflow -- in fact I just patched a bug in production that way about 30 minutes ago 🙂

2020-10-27T23:51:35.329700Z

https://clojure.org/news/2020/02/20/state-of-clojure-2020 - emacs at 43%, then intellij, then vscode, then vim

2020-10-27T23:51:57.329900Z

everything else is under 10%

alexmiller 2020-10-27T23:56:22.330300Z

range and repeat may be too specialized to really test this theory