clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
craftybones 2021-05-16T09:02:30.399Z

Has clj behaviour changed? When I evaluate an expression now the prompt vanishes and is substituted by the expression and the result of evaluation

craftybones 2021-05-16T09:02:56.399300Z

~> clj
Clojure 1.10.1
(+ 2 3)
5
user=> (+ 3 4)

craftybones 2021-05-16T09:03:27.400Z

This doesn’t happen with clojure

craftybones 2021-05-16T09:05:41.400300Z

some readline screwup?

lispyclouds 2021-05-16T09:09:52.400400Z

Maybe try updating rlwrap? They fixed this issue: https://github.com/hanslub42/rlwrap/issues/108

craftybones 2021-05-16T11:52:18.400800Z

Ah, interesting

craftybones 2021-05-16T11:56:37.401Z

That was it! Thanks!

Helins 2021-05-16T16:33:58.403400Z

Probably asking for the impossible: is there really no "easy" way for having maps which make a distinction between lists and vectors, in keys? While keeping it convenient (eg. no wrapping in a custom type which hashes differently, no map reimplementation)?

alexmiller 2021-05-16T16:43:48.403700Z

no

alexmiller 2021-05-16T16:44:14.404Z

why do you want to distinguish?

☝️ 2
2021-05-16T16:52:41.405400Z

You could wrap all keys in a very simple Clojure map, e.g. {:type 'list :value '(1 2 3)} is not equal to {:type 'vector :value [1 2 3]}. No custom type declarations required. If you wanted to mix those with maps that might have those exact same keys, then you would also want {:type 'map :value {1 2, 3 4}}

👀 1
2021-05-16T16:53:32.406400Z

But basically Clojure uses clojure.core/= to distinguish equal vs. non-equal for keys of maps and elements of sets, and Rich wanted sequences, lists, and vectors to all be equal to each other if they have equal elements in the same order.

Helins 2021-05-17T07:11:34.417100Z

@alexmiller I am currently working on Convex Lisp (https://convex.world) and equality is defined in a strict way (different types are not equivalent). It is both an implementation detail and for the sake of being more explicit. I am not by all means complaining about Clojure here. No solution is perfect, it was a good decision to lean on something that was convenient for a majority of use cases. In my use case, it is extremely convenient to use Clojure for working on Convex Lisp, both are identical in many aspects. This is just one example where I encountered a hiccup because semantics were different and I am trying to find a good enough solution without re-inventing the wheel. Besides that particular point, there is a 1-to-1 mapping in collections and I really would like to keep it that way.

2021-05-16T16:56:13.407200Z

Merely wrapping in a custom type that hashes differently is insufficient -- you would also need the custom types to return false for clojure.core/= when compared to each other.

alexmiller 2021-05-16T16:56:35.407300Z

imo, this was one of the most consequential, and also non-obvious design choices in Clojure

NoahTheDuke 2021-05-16T17:21:34.408100Z

I’d love to read/hear more about the consequences of this if anyone feels like writing it up

2021-05-16T17:22:14.408300Z

One of the consequences is that '(1 2 3) and [1 2 3] are the same value when used as map keys or set elements, as asked about above.

2021-05-16T17:22:45.408500Z

Another is that when you want these things to be treated as equal, then you do not have to explicitly convert a sequence or a list into a vector before using = to compare it to a vector.

2021-05-16T17:23:55.408700Z

If Rich had made a different design decision that lists, vectors, and sequences were always not equal to each other, regardless of their elements, because they have different types, then you would need such explicit conversions in order to compare their elements to each other, or you would need different variants or options of functions to do equality comparisons between them.

alexmiller 2021-05-16T17:29:45.408900Z

it mirrors the automatic seq-ing of inputs to seq functions - there is no friction to take a collection (any seqable collection) and view it as a seq for the purposes of map/filter/etc and the result is immediately = to any other sequential collection (requiring no post-conversion). one alternative could have been to require explicit conversion on the input (or output) in/out of the seq world. another alternative is to have all collections be seqs rather than present a seq view (pushes more requirements into the coll interfaces/impls)

alexmiller 2021-05-16T17:33:56.409100Z

there are a ton of tradeoffs in these approaches and they were consciously weighed (along with other more "stream" like ideas). I think the endpoint is quite elegant from a usage perspective and from a coll library design perspective, so much that most people don't even think about it while using it.

👍 1
1
raspasov 2021-05-16T21:19:24.409500Z

I agree it’s quite elegant. I generally tell people to default to vectors in order to eliminate any confusion, unless you really need lists or seqs specifically. Do you think that’s sound advice?

alexmiller 2021-05-16T21:20:52.409700Z

I think vectors are usually the best match for creating new sequential collections, but I try to write my code to be as agnostic about the coll type as possible

👍 1
1
raspasov 2021-05-16T21:22:37.410Z

Sure. It’s hard for me to think of code that would work on vectors but not on seqs or lists. Unless order is important, and you’re building a collection incrementally in a loop/recur or something like that via (conj …) .

☝️ 1
raspasov 2021-05-16T21:22:55.410200Z

But that’s also pretty rare (for the code that I usually write).

raspasov 2021-05-16T21:26:13.410500Z

The code is usually more about data transformation rather than building up data from scratch. In those cases whether you have a vector, list or a seq doesn’t really matter, since the order of seq-ing is the same.