[racket] Best practices for classes

From: Vincent St-Amour (stamourv at ccs.neu.edu)
Date: Mon Oct 6 13:46:07 EDT 2014

At Sat, 4 Oct 2014 10:13:14 -0500,
Robby Findler wrote:
> That said, I do think that our integration of generic operations and
> our standard library deserves some more care and perhaps redesign to
> make things hang together better. As it stands, we have some
> conveniences, but they are limited by backwards compatibility concerns
> (like the one in the previous paragraph). I have heard that some are
> considering this as part of "racket2" but I don't know how far along
> those plans are.

Last year, I started work on a generics-based collections library:
   https://github.com/stamourv/generic-collections

I agree that something like this should be part of Racket 2, and I think
that this library may be a good starting point.

The closest I have to documentation is the description of the interfaces
involved:
  https://github.com/stamourv/generic-collections/blob/master/main.rkt#L748

I started writing a design document, to better explain the big picture,
but I haven't finished it. If there is interest in exploring that space,
I can spend some time to polish it.

If anyone has comments, suggestions, or would like to help, don't
hesitate! I don't currently have time to work on this (but hope to in
the future!), but would be happy to help anyone who decides to.


Here's a brief summary of some of the highlights:

  
- The library is designed to accomodate generic consumption,
  construction and transformation of collections, while preserving the
  "type" of a collection (e.g. mapping from lists to lists and vectors
  to vectors, not from lists to an opaque sequence type, as the current
  sequence functions do).

- The library accomodates both "structural" collections (such as lists),
  that are built and traversed structurally, and "indexed" collections
  (such as vectors) that are built and traversed statefully.

- Thanks to generics' fallback methods, it's possible for collection
  implementers to define a few basic methods, and get a lot of methods
  (think all of racket/list) for free, while still being able to
  override specific operations.

  A collection that implements either the "structural traversal" set of
  methods (`empty?`, `first` and `rest`) or the "stateful traversal"
  set of methods (`make-iterator`, which returns something that
  implements the `gen:iterator` interface) gets `foldr`, `length`,
  etc. for free.

  A collection that implemements either the "structural building" set of
  methods (`cons` and `make-empty` (generics need an instance to
  dispatch on, so we can't just have a generic `empty`)) or the
  "stateful building" set of methods (`make-builder`, which returns
  something that implements the `gen:builder` interface) gets `range`,
  `make` (think `make-list`) and `build` (think `build-list`) for free.

  A collection that implements traversal and building methods gets all
  "transducer"[1] methods (`map`, `filter`, etc.) for free.

- Thanks to generics' default methods, it's possible to retrofit these
  interfaces on top of built-in datatypes. This should make that library
  a 95% compatible[2] replacement for the current collection operations.

- Operations are n-ary where it makes sense (e.g. n-ary map) and can
  operate on different collections (e.g. `(map f <list> <vector>)`).


Vincent



[1] Unrelated to Clojure's transducers. I picked the name before they
    were announced. I'm open to naming suggestions.

[2] The library is currently backwards compatible for all operations
    except `member`, whose current design doesn't make sense for indexed
    datatypes, and is an IMO questionable pun anyway. The library
    instead uses `member?`, which takes a failure thunk, and is thus
    closer to other, more modern Rackety APIs.

Posted on the users mailing list.