Fork me on GitHub
#clojure-dev
<
2023-01-11
>
dmiller20:01:58

There is a marker interface clojure.lang.Sequential. I'm trying to figure out what it is good for. I think every data structure defined in Clojure that defines Sequential also defined Seqable. And vice versa. If I am wrong, please correct me. (Speaking at concrete class level. There are interfaces such as IPersistentStack that inherit from Seqable but not Sequential. But I think all concrete classes that implement IPersistentStack also implements one of the IPersistentXXX interfaces that eventually hit IPersistentCollection and hence Seqable.) If you look at where Sequential is checked for in the code, in every single example I can find, a positive response is followed by a call to RT.seq. RT.seq checks for ASeq, LazySeq, Seqable and then several platform types such as String and Iterable. Sequential plays no role in this at all. It appears to me that if one were to run into something that was Sequential and not Seqable, and it got passed into some piece of code that looked for Sequential, you'd end up with an exception being thrown.

hiredman20:01:18

Vectors and seqs (including lists) are sequential

hiredman20:01:24

Maps and sets are not

hiredman20:01:37

But all are seqable

hiredman20:01:48

So for example when json encoding you might encode everything sequential by emitting [ then using seq to walk the thing emitting each item, then followed by ]

dmiller20:01:10

I am not positing that Sequential is the same as ISeq. I'm positing that there is no example that shows Sequential is different from Seqable. Other than that if you defined something that was Sequential and not Seqable, you might end up with an exception in RT.seq.

hiredman20:01:16

Well, that is an example, maps are seqable but not sequential

hiredman20:01:56

Sequential means something has an order that is part of the interface of the thing

dmiller20:01:57

You are correct. I overstated what I'm looking for. I agree you can be Seqable and not Sequential. I'm looking for something that is Sequential but not Seqable. In other words, for some reason for Sequential to exist.

dmiller20:01:59

I agree that Sequential means that. But operationally, I cannot find a place in the Java code where it makes a difference. It does occur to me just now that I did not look in the Clojure source.

hiredman20:01:28

https://git.sr.ht/~hiredman/lions/tree/master/item/src/com/manigfeald/json.clj#L15 so here is some code that does what I said about using sequential to determine what should be encoded as a json array

hiredman20:01:52

Seqability is not sufficient there, because maps are seqable but should not be encoded that way

borkdude20:01:09

Also, strings are seqable? but not sequential?

dmiller20:01:34

Okay, thanks. I finally get it. I'm a little slow on the uptake been sitting here too long already today. By testing for map? first the code has already filtered out likely all Seqable-not-Sequential types and sequential? could be replaced by seqable?, but I'll definitely concede that the semantics are clearer this way, as well as allowing for other data types in the future. Thanks for an example from real life (so-called).

hiredman20:01:28

Yeah, and sequential? there could be vector? or seq? with little real world difference

phronmophobic20:01:10

> By testing for map? first the code has already filtered out likely all Seqable-not-Sequential types and sequential? Not so, sets are another builtin type that are Seqable, but not Sequential. Additionally, these interfaces are open for extension, so you can make your own and the library can still handle those cases. For example, https://github.com/achim/multiset/blob/master/src/main/multiset/core.clj

hiredman20:01:44

data.json does more like what you describe, but as a protocol, maps(associative collections) get the object writer and other java.util.Collections get the array writer

dmiller20:01:00

Doesn't map call seq on its collection argument? Semantics aside, I'm back to the case where if this function got a Sequential that wasn't Seqable, it would blow up in RT.seq.

dmiller20:01:03

Sorry, crossed paths with multiple responses. I'll concede that there must be situation where there is something that is Sequential and not Seqable and never makes it to RT.seq.

hiredman21:01:50

even if it is always the case that things that are Sequential are always processed by seqing, that doesn't mean they are equivalent

hiredman21:01:21

just like you might take an iterator over a map and a list, but want to do different things with the items you get by running the iterator based on the type of the source collection

dmiller21:01:17

I do concede the semantic difference. I was thinking purely operationally from current code. Thank you both for the clarifying this for me.

dmiller20:01:04

This is not quite correct: "But I think all concrete classes that implement IPersistentStack also implements one of the IPersistentXXX interfaces that eventually hit IPersistentCollection and hence Seqable" . I think it is true that every class that implements IPersistentStack implements Sequential either directly or through ASeq or APersistentVector or something else that implements Sequential.