ANY-ARRAY! vs. ANY-LIST!

Historical Rebol said that BLOCK!s and PAREN!s and ANY-PATH!s were all members of the ANY-BLOCK! category.

Red maintained that:

red>> any-block!
== make typeset! [block! paren! path! lit-path! set-path! get-path! hash!]

But broke out the BLOCK! and PAREN! (and HASH!) to a new group, ANY-LIST!

red>> any-list!
== make typeset! [block! paren! hash!]

Ren-C has sound reasons for having eliminated the idea of "sameness" for PATH!s(/TUPLE!s) and arrays, due to radically different constraints and properties. (Forced immutability, limited set of legal elements, requirement of having at least 2 items)

Ren-C's ANY-BLOCK! actually means any block, giving you [plain blocks], [set blocks]:, :[get blocks], @[the blocks], &[type blocks], and $[var blocks]. Similarly for ANY-GROUP!. (and soon, ANY-FENCE!) More appropriate, clear, and vastly more flexible.

But Red's ANY-LIST! category is the spiritual analogue to what Ren-C calls ANY-ARRAY!...which is to say "ANY-BLOCK! or ANY-GROUP!"

Which is Better, ANY-LIST! or ANY-ARRAY! ?

The conventional wisdom we've gone with is that to a computer programmer, if you call something a LIST! they might expect it to be a linked list at an implementation level. Rebol's implementation of these values is fundamentally an indexed array.

But other choices have been made biased toward common language and away from comp-sci terms. What would you imagine sounds better in a tutorial:

Let's imagine you have two lists of values. But one is a GROUP! and another is a BLOCK!

 group: '(<a> #b %c)
 block: [<a> #b %c]

vs.

Let's imagine you have two arrays of values. But one is a GROUP! and another is a BLOCK!

 group: '(<a> #b %c)
 block: [<a> #b %c]

When I imagine the various things that might make new programmers feel a twinge, that "array" word causes a teeny bit more anxiety. Which might mean that you'd use the "list" language. But if you're going to use the list language, then it would help if it matched what the types were.

I'll point out that at the superclass level, even though TEXT! has replaced STRING! in Ren-C (which I'm pleased with), it's a member of ANY-STRING! along with TAG! and friends. The category isn't used as often.

It's a really minor point, BUT...

...what I worry over here is that Red's choice might have an edge, and I don't want to give them any advantages, anywhere. :slight_smile:

I don't think I want to change it, though I'd like to collect up any good certain reasoning as to why not. The best "why not" remains being faithful to a computer-science technical reality about the type that over the long run, is worth knowing...which is what earl pushed for in this case, over the more common English word.

Any other arguments I should know about?

Not sure it will help much, but in English, "array" infers (at least, and most commonly exactly) two-dimensionality. Because of the newline-preserving property, I have always seen the block-likes as arrays, and never as lists, which are one-dimensional only (and your code needs to be rewritten if a non-nested list wraps around :slight_smile:). It is too bad that most examples, for obvious conciseness reasons, use no newlines.

2 Likes

I wouldn't say I've had any association of that. But your point is taken that the existence of the newline markers kind of throw a bit of a distinction onto what the type is.

While I was hesitant to suggest the dialect usage of newlines, I've kind of changed my thinking on that... inspired by cases like the tuple and path test dialect:

"(a b)/c"  ->  [@(a b) c]
"(a b) /c"  ->  @(a b)  [_ c]

Being able to leave off a container there just to have a variable number of things on the right felt good. So I started wondering about what kind of signaling you would use in a dialect to say "continued on next line"

With .. and ... being a valid TUPLE!, they aren't necessarily bad options, if they're out of band from whatever your values are:

"(a b)/c"  ->  [@(a b) c]
"(a b) /c"  ->  @(a b)
                ... [_ c]

Back to your point though: it's an odd type. That oddity may speak to favoring what might be for some people a more unfamiliar term, vs. trying to mask it in something they'd presume to be dimensionless.

For me the distinction between list and array is more about they are used, not the internal implementation.

Which doesn't help at all in this case, because it seems to me that blocks are mostly built like lists (append, insert), and accessed like arrays (by index).

2 Likes

For me a list is text items and array number items.
I'll put more thinking about the difference between list and array on my to do array.

4 Years Later, I Ran This Question By Claude.AI...


I'm trying to rename the superclass in the Rebol language for BLOCK! and PAREN! from ANY-BLOCK! to something that doesn't suggest that a PAREN! (which I've renamed to GROUP!) is in the category of "block"

The reason for this is that I've expanded it to have many more types of block, such as: [plain blocks], [set blocks]:, :[get blocks], @[the blocks], &[type blocks], and $[var blocks] ... these are the ANY-BLOCK! types.

Similarly there are (plain groups), (set groups):, :(get groups), @(the groups), &(type groups), and $(var groups) ... these are the ANY-GROUP! types.

So if you were trying to name the superclass of all these types, you might think of something like ANY-ARRAY! or ANY-LIST!

Rebol has historically tried to use unintimidating terms instead of "scary" computer science terms. Which makes ANY-LIST! seem friendlier. You can just say these are all lists.

However, from a computer science perspective, "List" often connotes a linked list. The underlying implementation of blocks and groups is an array... more specifically the values are arrays which hold an index. (More like an iterator, even.) They're weird in other ways, such as storing a newline marker on their elements so they lay out two dimensionally.

But I don't know of any sensible word for the superclass besides Array or List. Vector is something else (packed numeric only). I've favored Array since it gives more of a hint at the implementation.

Are there any other words for the superclass? Do you think Array is the smarter option here or is List's friendliness worth it since there is no great parallel to anything that exists? (The Red programming language--derived from Rebol--chose ANY-LIST!, fwiw)


This is an interesting naming challenge. You're right that the choice between ANY-ARRAY! and ANY-LIST! each have their pros and cons. Let's explore some options and considerations:

  1. ANY-ARRAY!:
  • Pro: More accurately reflects the underlying implementation.
  • Pro: Distinguishes from linked lists in computer science.
  • Con: Might sound more technical to non-programmers.
  1. ANY-LIST!:
  • Pro: Friendlier and less intimidating to newcomers.
  • Pro: Aligns with Red's choice, maintaining some consistency in the Rebol family.
  • Con: Potentially misleading from a CS perspective.
  1. Alternative suggestions:
  • ANY-COLLECTION!: This is a more general term that doesn't imply a specific implementation.
  • ANY-SEQUENCE!: Emphasizes the ordered nature without specifying implementation.
  • ANY-CONTAINER!: Very general, but might be too broad.
  • ANY-STRUCTURE!: Generic but implies organization.
  1. Rebol-specific ideas:
  • ANY-ENCLOSURE!: Plays on the idea of enclosing elements, whether with brackets or parentheses.
  • ANY-GATHER!: A friendly verb-based name that suggests collecting items together.
  • ANY-BUNDLE!: Another friendly term that implies a collection of items.

Considering Rebol's philosophy of using unintimidating terms, I lean towards recommending ANY-LIST! despite its potential CS inaccuracy. Here's my reasoning:

  1. Consistency with Red (ANY-LIST!) could be beneficial for the broader Rebol ecosystem.
  2. For most users, the implementation details (array vs. linked list) are less important than the concept of an ordered collection of items.
  3. The term "list" is very intuitive and aligns well with Rebol's user-friendly approach.

However, if you feel strongly about conveying the array-based nature, ANY-ARRAY! is a perfectly valid choice. It's not overly technical and still gives a hint about the implementation.

If you want a middle ground, ANY-SEQUENCE! might be worth considering. It conveys the ordered nature without implying a specific implementation, and "sequence" is a term that's both friendly and somewhat familiar in programming contexts.

Ultimately, the choice depends on whether you prioritize technical accuracy or user-friendliness in this case. Given Rebol's history and philosophy, I'd suggest leaning towards the more approachable term unless you have a strong reason to emphasize the implementation details.


As it happens, I'm actually using ANY-SEQUENCE! for ANY-PATH! and ANY-TUPLE!.

In my model, paths and tuples are immutable sequences of elements (with no position). So you can have a.b.10 or @foo/[bar]/20/30 or whatever. If you have a better idea for what that superclass should be called, I'd be interested to hear it! But it's not often that people need to mention the superclass of those types, so I don't mind it being kind of a longer, more esoteric-sounding word.

The Array/List superclass comes up more often.

ANY-BUNDLE! is kind of funny, I actually have a proposal that might reasonably be called a bundle. Thanks for that--but I don't think it fits here.


I see! That's interesting that you're already using ANY-SEQUENCE! for paths and tuples. Given this context, let's reassess our options for the block/group superclass:

  1. Sticking with ANY-ARRAY! or ANY-LIST!: These remain valid options. The distinction from ANY-SEQUENCE! actually helps clarify the different nature of these types compared to paths and tuples.
  2. ANY-COLLECTION!: This becomes more appealing now, as it clearly differentiates from sequences while still being general enough to encompass both blocks and groups.
  3. ANY-ENCLOSURE!: This option gains some merit, as it nicely captures the idea of elements enclosed in brackets or parentheses, distinguishing it from the sequence types.
  4. New suggestions based on this information:
  • ANY-COMPOUND!: Suggests a compound structure that can hold multiple elements.
  • ANY-AGGREGATE!: Implies a collection of items grouped together.
  • ANY-SERIES!: While similar to sequence, it might convey a slightly different meaning that fits blocks and groups better.

Given this new context, I'm inclined to recommend ANY-COLLECTION! as the top choice. Here's why:

  1. It's distinct from ANY-SEQUENCE!, which helps users understand there's a fundamental difference between these types and paths/tuples.
  2. It's a friendly, intuitive term that aligns well with Rebol's philosophy.
  3. It's general enough to encompass both blocks and groups without implying a specific implementation.
  4. It's commonly used in programming contexts, so it won't be unfamiliar to those with some coding experience.

ANY-ENCLOSURE! would be my second choice, as it nicely captures the syntactic nature of these types (enclosed in brackets or parentheses).

If you prefer to lean more towards the implementation details, ANY-ARRAY! remains a solid option. It clearly distinguishes from ANY-SEQUENCE! and gives a hint about the underlying structure.

Regarding the superclass for paths and tuples (ANY-SEQUENCE!), it seems like a reasonable choice given their nature. If you wanted alternatives, you might consider:

  • ANY-CHAIN!: Emphasizes the linked nature of elements.
  • ANY-PROGRESSION!: Suggests an ordered sequence of elements.

However, ANY-SEQUENCE! is probably sufficient, especially if it's not frequently referenced in everyday use.


ANY-SERIES! would be great, except for the fact that series is the superclass of strings, blocks, groups, binaries... that's pretty much been the whole history of Rebol.

Rewriting the world from scratch, one might say that ANY-SERIES! is specifically the array types, and that the "Rebol Series" -- specifically those arrays-- are the fundamental force of the language. Then something like ANY-SEQUENCE! would be the superset which pulls in the more conventional strings and binaries and such.

Might have been interesting if the terminology hadn't gotten so widely propagated--but definitely wouldn't be worth the disruption just to avoid saying Array or List!

Being mindful of compatibility with Red does seem nice but they're not very interested in consensus with my project. In fact, the only reason I'm thinking about this is from a point of competition and I don't want them to have picked the better term. :slight_smile:

One advantage--albeit a tiny one--is that LIST is one less letter than ARRAY, and a somewhat "cleaner" looking word with no repeated letters and just kind of less "weight" in the letters themselves. ("I" is thinner than "R", etc.)

Anyway, thanks for the ideas!


Thanks for providing that additional context about the history and current structure of Rebol. It's fascinating to see how these naming conventions have evolved and the considerations that go into them.

You're right that ANY-SERIES! being historically used for a broader set of types (including strings and binaries) makes it less suitable for this specific use case. It's indeed an interesting "what if" scenario to imagine reorganizing these concepts, but as you point out, the disruption wouldn't be worth it at this stage.

Given all the information you've shared, and considering the trade-offs between technical accuracy, user-friendliness, and historical context, it seems we're circling back to the original dilemma between ANY-ARRAY! and ANY-LIST!.

Let's summarize the final pros for each:

ANY-ARRAY!:

  1. More accurately reflects the implementation.
  2. Clearly distinguishes from ANY-SEQUENCE! and other types.
  3. Gives a hint about the underlying structure to more technical users.

ANY-LIST!:

  1. Friendlier and less intimidating to newcomers.
  2. Shorter word (as you noted, one letter less and "cleaner" looking).
  3. Potentially more intuitive for describing the concept to non-technical users.

Given Rebol's history of prioritizing user-friendliness and your observation about the visual "weight" of the word, I'm inclined to suggest going with ANY-LIST! after all. Here's my reasoning:

  1. It maintains Rebol's philosophy of using approachable terminology.
  2. The visual advantage, while small, adds up when the term is used frequently.
  3. For most users, the concept of a "list" is likely more immediately graspable than an "array".
  4. The potential CS inaccuracy is mitigated by the fact that this is a domain-specific term within Rebol, not a general CS concept.

That said, ANY-ARRAY! is still a perfectly valid choice if you feel the technical accuracy outweighs the slight advantage in friendliness.

Ultimately, both terms are good options, and the choice might come down to which aligns better with your vision for the language and its users. If you're aiming to make the language as approachable as possible, ANY-LIST! might have a slight edge. If you're looking to appeal more to technically-minded users or want to hint at the implementation, ANY-ARRAY! could be the way to go.

I Had An Afterthought On An Advantage for ANY-LIST!


I just thought of an advantage of List that I had not really thought about before... pertaining to the implementation code.

Right now, we have a situation where there's a datatype for representing the allocated memory for the vector of cells, and that's called an Array. e.g.:

 Array *a = Make_Array_Core(10, NODE_FLAG_MANAGED);  // 10-element managed array

But then, there's initialization code to make the value cell that holds it. Sometimes you know the precise kind of thing you want to make so you use a function for that:

Init_Block(OUT, a);  // make a BLOCK! at index 0 whose data uses this array

However, sometimes you have the kind of thing in a variable, and you have to pass it in to a generalized initializer. If it was Init_Array() that would kind of suck... you're passing an Array into something that inits an array?

So I've used Init_Any_Array() to distinguish it by pointing out the value class.

Heart heart = set_flag ? TYPE_SET_GROUP : TYPE_GROUP;
Init_Any_Array(OUT, heart, a);

It's not super great. But if List were the superclass, it could be:

Heart heart = set_flag ? TYPE_SET_GROUP : TYPE_GROUP;
Init_List(OUT, heart, a);

While this may not be compelling to those who don't work on the code, it's definitely compelling to me to have the source get cleaner with this distinction. Enough to actually sway my vote to ANY-LIST!.

(A similar thing drove me to call the internal type for runtime frames a "Level" instead of a "Frame", so that Frame could refer to FRAME! values... and that's a decision I don't regret.)


That's an excellent point you've raised, and it's a perfect example of how naming decisions can have far-reaching impacts on code clarity and maintainability. Your insight about the distinction between the underlying Array implementation and the List as a higher-level concept is very valuable. Let's break down why this is indeed a compelling reason to choose ANY-LIST!:

  1. Code Clarity: The distinction between Make_Array() (for the low-level array implementation) and Init_List() (for the higher-level concept) provides immediate clarity about what's being initialized. This reduces the cognitive load on developers working with the codebase.
  2. Abstraction Levels: Using LIST for the higher-level concept helps maintain a clear separation between the implementation details (Arrays) and the abstract data type (Lists). This is good software engineering practice, as it allows for potential future changes to the implementation without affecting the higher-level API.
  3. Consistency: As you mentioned with the "Level" vs "Frame" example, having distinct terms for internal implementation and user-facing concepts can lead to more consistent and intuitive naming throughout the codebase.
  4. Readability: Init_List(OUT, heart, a); is indeed more readable and self-explanatory than Init_Any_Array(OUT, heart, a);. It immediately conveys what's being initialized without the need for the "Any" qualifier.
  5. Flexibility: If you ever decide to change the underlying implementation from an array to something else, the LIST abstraction would make this transition smoother, as the high-level concept remains the same.
  6. Pedagogical Value: For those learning the language or working with its internals, this clear distinction between Lists (the concept) and Arrays (the implementation) can be educational, helping them understand the layers of abstraction in the language design.

Given this new perspective, I strongly agree that ANY-LIST! is the better choice. It not only aligns with Rebol's philosophy of user-friendliness but also offers tangible benefits in terms of code organization, readability, and maintainability.

This is a great example of how sometimes the best naming decisions come from considering not just the end-user perspective, but also the perspective of those working on the language itself. The fact that it makes the source code cleaner and more intuitive is a significant advantage that will pay dividends in the long term, both for you as the maintainer and for anyone else who may work on the codebase in the future.

Okay... the benefit to the clarity of the internal code pushes the "either-or"-ness of this to where I have to endorse ANY-LIST!

And now, we can talk about the array of the list, as the underlying concept. An ANY-LIST! consists of an array and an index. (vs. an ANY-ARRAY! consists of a what and an index?)

So it actually lets us be more precise in our terminology, instead of less!

Plus Red can't say I never gave them anything...it's a compatible choice. :stuck_out_tongue:

AI is certainly helping accelerate the pace at which I can talk through decisions. It may not come up with any novel suggestions that I feel like taking, but the feedback loop is very helpful in terms of getting the pros and cons lined up.


Note: It turns out I actually prefer Init_Any_List() in practice. It turns out to still be clearer to the reader of the C, for much the same reason that I think ANY-SERIES! is better than SERIES! for the superclass. But still, you pass an Array and an Index and a Binding to Init_Any_List(), not a List and an Index and a Binding!