Hacker News new | ask | show | jobs
by Per_Bothner 1036 days ago
One of the issues R7RS-large ran into was in how to handle datatypes, such as collection types. Initially, Lisp-style languages had linked lists as the primary data type, but vectors were early added. So you had a "map" function (that worked on linked lists) and "vector-map" (that worked on vectors). Similarly, "length" vs "vector-length". What happens if you want to add more collection types - for example "bytevector"? Do you add "bytevector-map" and "bytevector-length"? Or do you generalize "map" and "length" so they also work on bytevectors (and also vectors)? The former is most compatible with Scheme history and tradition. The latter is IMO preferable going forward as new collection types are added - but it needs some way to talk about frameworks of types that are all sequences (linear collections). I.e. you need at least the concept of inheritance or "interfaces" as used in various languages, including Java and TypeScript.

Many languages in the Lisp/Scheme family have some kind of inheritance or interfaces, including Common Lisp, Dylan, Racket, Kawa, and many more. However, this hasn't been standardized for Scheme. R7RS-small has a mechanism to define new data types (records), but they were limited in functionality to C-like structs.

I (and others in the community) felt (and feel) that it is premature and unwise to add a bunch of new libraries for new data types until or unless we have some kind of framework for inheritance or interfaces. Others in the community (including the former chair) felt this was unnecessary and perhaps inappropriate for a language with the goals and history of Scheme.

There is no clear right answer or consensus for how to go forward, which is part of what caused things to bog down.

3 comments

I learned Scheme from George Springer in the '90s.

I just want a language with S-expression syntax and a proper numeric tower (like Scheme), with modern HAMT-based immutable collection types (like Clojure), and a native JIT so I don't have to mess with Java or JavaScript.

Does Racket fit the bill now?[1][2] Coming from Indiana, I was happy when they announced the move to Chez.

I was heartened by a post here yesterday about implementing a numeric tower on WASM.[3]

[1] https://docs.racket-lang.org/hamt/

[2] https://docs.racket-lang.org/guide/performance.html

[3] https://news.ycombinator.com/item?id=37158821

too many layers, too much undesirable heritage would be the problem with that, I'd guess
The lack of “interface” was one of the main reasons I never ended up using scheme to build production systems.

I loved playing with scheme in my university days 20 years ago, and loved how one can make up any fancy programming concept using call/cc and dynamic-wind. Except if you want to have multiple implementation of some protocol or collection. Hand roll your own object model or dynamic dispatch mechanism? Hard to make it scalable, composable and compatible with other projects.

> Initially, Lisp-style languages had linked lists as the primary data type, but vectors were early added

The Achilles' heel of every Lisp is dealing with any data structure that isn't a linked list. I'm talking aref, setf+aref, vector-ref, vector-set!, char, etc. It's all just a huge pain when compared to any other language (Python, Ruby, JavaScript, Java) that has syntax for arrays, hash maps, strings. Solving the generalized "map" or "length" is really only solving one side of the problem. The other side can't be solved because the language is s-exps and "everything is a function." It would fundamentally cease to be Scheme at that point.

I haven't used clojure since forever but I don't think this was particularly problematic. They even had nice literal syntax for different collection types and fairly powerful generalized collection abstractions, way better than the languages you mentioned IMO.
Also Clojure decomplects inheritance and interfaces.

It gives you protocols to define a set of related methods, without any restriction on the underlying data structure.

It gives you defrecord & deftype to define composite associative data structures, which the fields in an object are.

Then you can combine these in various ways, giving you all sorts of polymorphic code.

Clojure even has multimethods for cases, when a single operation should happen different ways, depending on some aspect of an arbitrary data structure. Someone defines a transformation function from arbitrary data to some other data to dispatch behavior over, then anyone can add define behavior for new dispatch values.

Why not copy these approaches?

This approach is already there in Common Lisp, and the biggest flavours that predated it.

I think is the whole point of Scheme community always having been a different set of folks.

In a way, it is like the C versus C++ communities of parenthesis based languages.