Anonymous avatar Anonymous committed 7f90cec

More notes in various places.

Comments (0)

Files changed (3)

 Robin supports a simple system of raising and handling exceptions.  This
 helps define the semantics of otherwise undefined operations, such as trying
-to obtain the tail of a non-pair.
+to obtain the `tail` of a number.
 Lastly, Robin unifies (to a degree) programming and static analysis.  The
 language itself defines essentially no rules of static correctness beyond
   being evaluated.  This might make the `self` parameter to macros redundant,
+  But, it might just be simpler to punt on this and make it a part of the
+  sugar in the humane syntax, which could support a form like:
+      forward foo in
+        let
+          foo = fun(a, b, c)
+                  if a then b(c) else foo(bar(a), b, c)
+        in
+          ...
+  ...and this would transform the binding as appropriate.  This would also
+  extend to mutually recursive definitions (`forward foo, bar in ...`)
 * Work out the static analysis modules.  See the Static Analysis document
   for more information.


 Again, `Pid ! Msg` where `Msg` is anything is very simple, but again, it
 is very low-level.  It is useful to have metadata about the message, like
 which process sent it, and when.  But I need to think about this more.
+#### Should symbols be atomic?
+Decision: Currently, yes.  
+Chance of changing: High.
+In the Lisp tradition, symbols are "atomic" -- you can't take them apart,
+you can't (always) create new ones at runtime, they have no intrinsic order,
+and so forth.  Beyond a certain conceptual cleanliness, this has the
+advantage that each symbol can be associated with, and after a compilation
+process, can be replaced by, a small integer of fixed size.  This is good
+for efficiency, but efficiency is not what we're going for here.  Later
+languages in the Lisp tradition introduced things like `gensym` to create
+new symbols, and a separate string type and operations like `symbol->string`
+and `string->symbol`.
+Being able to create new symbols during runtime is very useful in program
+transformation, and for our purposes, should outweigh any efficiency gains
+from having a fixed set of atomic symbols.
+Also, if two nodes of a distributed Robin system are exchanging terms
+produced by software the other knows-not-what, they *must* be prepared to see
+symbols that they don't already know.
+In Robin, we can regard having a fixed, static set of symbols in use in a
+program as a *luxury*; if a static analysis reveals that you can "afford" it,
+(i.e. that you're not creating new ones at runtime and so forth,) a compiler
+can replace the symbols with small integers for efficiency in your case.
+### Should symbols and strings be different types?
+Decision: Currently, yes.  
+Chance of changing: High.
+Given Scheme's approach to the above (`symbol->string` and `string->symbol`),
+let's ask ourselves: what's *really* the difference between the two types?
+In an essentially purely functional language like Robin, both symbols and
+strings are immutable.  In implementations where strings are "intern'ed",
+this is not so different from inserting symbols in a symbol table.  And,
+in a language like Robin where equality and identity are identical,
+`(equal? "foo" "foo")` should evaluate to true whether the two strings are
+two copies of the same text, or two pointers to the same single text.
+This all points to the idea that symbols and strings should be unified; or
+rather, that there should be no symbols, only strings.  A traditional
+symbol literal, then, should be one syntax for specifying a string; and on
+the other hand, you ought to be able to say things like
+    (''let'' (('X'a'X' 1)) (''+'' 1 a))
+with impunity.


 retain plain macros (if objects are built from them then they're still
 available for that purpose), or something else...
+One of the biggest problems here is how objects would interact with static
+analysis.  A macro which operates on an object doesn't care about how the
+object implements the methods on it, but it *does* care that the method
+operation meets the interface expectations.
+To do static analysis on objects, we would need to codify the expectations on
+the interface(s) that each object supports.  With traditional name-only duck
+typing, this is not possible; we would need to extend names with the interface
+module that they're from (so you can distinguish `tree:bark` from `dog:bark`.)
+Also, we would need to start putting metadata into interfaces somehow.
+We need to do this anyway, to some extent; if I make a new macro called
+`assign` which works a lot like `bind` or `let` but has a different syntax,
+how do I let the static analyzer know that it does that?  (For that matter,
+how does the static analyzer know that the concurrency macros bind a new
+value to one of the identifiers passed to them?)
+So, this should probably be put on hold until I have a better idea of what
+metadata will eventually look like.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.