Commits

Anonymous committed e42b9b7

Add thoughts on object-orientation, string formatting.

Comments (0)

Files changed (2)

doc/Object_Orientation.markdown

+Object Orientation
+==================
+
+Should Robin support object-oriented programming, and if so, in what sense
+should it be "oriented" towards "objects"?  It's a tough question.  It is
+so knotty, in fact, that instead of writing about in the Design Decisions
+document, I'm going to write about it in this standalone document -- even
+if Robin's support for it turns out to be minimal or non-existent.
+
+Why would we want object-orientation?  To achive polymorphism at the value
+level.  We already have polymorphism at the module level (your configuration
+file can point a module at any given implementation of it) and the device
+level (the device manager can return any device it likes for your request,
+so long as that device supports the requested operations).
+
+Still, polymorphism at the value level would be handy.  Consider
+environments.  We don't care how they're represented, so long as they support
+a few operations -- `lookup`, `extend`, perhaps `to-alist` and `from-alist`
+or the like.
+
+It doesn't make sense to model environments as devices, because
+they have no independent existence (through time, or otherwise) from the
+code that uses them.
+
+We could simply provide multiple implementations of an `env` module, which
+use different representations, but all support the given operations.
+However, this does not buy us any data hiding.
+
+So let's consider what an object system in Robin could look like, and how
+it could be implemented.
+
+Approach
+--------
+
+I would like to see the style of object-orientation to be prototype-based
+(with "manual" inheritance; if your object doesn't understand a method, it's
+up to it to pass that request on to some other object) and duck-typing based
+(no explicit classes; if an object supports some set of methods that a duck
+supports, then it's a duck, or at least you can treat it like one.)
+
+Should Robin be "purely" object-oriented -- that is, should *everything* be
+an object, or should there be some things which are not objects?
+
+I haven't decided.  If it is "pure", it will surely make the fundamental
+semantics more complex, because the base types will need to support some
+basic methods "out of the box".
+
+But the reason the core should be simple is to make a rigorous definition
+easier, and if we have a rigorous definition, and it's still not too hard to
+make a rigorous definition, maybe the extra complexity is worth it.
+
+If it's not purely object-oriented,
+
+* There might be some values I can't treat as objects.  Oh noes.
+* Different groups of developers might make up their own incompatible object
+  systems (think: Lua.)
+
+The second problem could be mitigated by providing an object system in the
+standard library -- you don't *have* to use it, but its presence would
+encourage developers to build their objects in a compatible way.  (Kind of
+like Perl; there, it's a convention, but a pretty strong convention.)
+
+Implementation
+--------------
+
+Objects, and their methods, can be implemented (almost) using macros.  An
+object is a macro which expects its first argument to be a literal symbol
+which is the method name.  The rest of the arguments are the argument to
+the method.  The return value is a (possibly) modified version of the object,
+or some other value, or possibly even a pair of these two things.
+
+I say "almost" because I think we need dynamic binding to do it purely as a
+macro, or at least it would be really, really helpful.  Consider:
+
+    (bind val 0
+      (macro (self args env)
+        (let ((method (head args)) (args (tail args))
+          (choose
+            ((equal? method (literal inc))
+              (bind val (+ 1 val) self))
+            ((equal? method (literal dec))
+              (bind val (- 1 val) self))
+            ((equal? method (literal what))
+              val)
+            (else
+              (super method args))))))
+
+How would this look?
+--------------------
+
+For example, lists:
+
+    (LIST head) -> VALUE
+    (LIST tail) -> LIST
+    (LIST cons VALUE) -> LIST
+
+We don't have a `List` class (and we don't want one either.)  Luckily, we
+have a built-in prototypical object for lists, `()`, so we can say...
+
+    (() cons 5)
+
+...but this actually makes the list `(5)`, i.e. it's in an unusual order:
+
+    ((() cons 5) cons 7)
+
+That one makes the list `(7 5)`.
+
+Things have a Smalltalk-y flavour after doing this.
+
+Of course, those are only the methods that lists implement.  A list,
+ultimately, should conform to a collection interface that other collections
+conform to, which supports things like `fold`, `find`, `size`, and whatnot.
+Basic lists should probably not support these out-of-the-box (the core would
+be too complicated.)  But, it should be possible, maybe, to wrap a list in a
+list-container, like
+
+    (list-container ((() cons 5) cons 7))
+
+If Robin is purely object-oriented, where do the non-instance methods live?
+Do we have class objects (metaclass etc a la Smalltalk?)  I'd rather not
+(duck-prototyping only.)  So that suggests we either put all these methods
+on some object (effectively a class object, in some aspects, perhaps), or
+retain plain macros (if objects are built from them then they're still
+available for that purpose), or something else...
+
+
+

doc/Practical_Matters.markdown

   (yaml, xml, binary, etc)
 - S-expressions are trivially serializable, except for functions
 
+Formatting
+----------
+
+Closely related to serialization.
+
+Many languages support a "standard" operation to convert an arbitrary value to
+a string.  Some even have two (e.g. Python's `str` and `repr`).
+
+But in reality, there are any number of ways to convert a value to a string.
+Why should the string representation of 16 necessarily be `"16"` -- why not
+`"0xf"` or `"XVI"`?  `"16"` is fine, but it should be explicitly noted to be
+the default for the reason that it's the most convenient for the audience of
+humans who use the decimal Arabic notation when dealing with numbers.
+
+How can we support both a reasonable (and possibly configurable) default
+formatting, as well as any number of other ways to format values which would
+be more appropriate in different contexts?
+
+Can we pass a "style" argument to the string-conversion function?
+
+Should we establish a "design pattern" for writing formatting functions, and
+provide support for implementing such patterns?
+
+(Also, `format` is probably a better name for this function than `str`.)
+
 Multiple Environments
 ---------------------