note that none of this has been implemented yet, and the design is still in flux! All of these items, although written as present-tense facts, are in fact future hypothetical wishlist items! I am just writing down ideas. I have many pages of notes on things i may or may not want to put into Oot. At this point, the design is unfinished; there is no coherent concept of a language called 'Oot', just a bunch of ideas towards such a proposal. There is no timeframe to actually implement this, and it most likely will never get finished. To be clear, i repeat myself: there is no such thing as Oot. Oot is not even vaporware. Oot has neither been designed nor implemented. No one is seriously planning to create Oot within any reasonable timeframe. These notes about 'Oot' contain many conflicting proposals.
Oot is a readable, powerful, programmable programming language focused on massive concurrency. It has a single fundamental data structure, graphs.
Oot is a high-level multi-paradigm language with elements of the lazy functional, imperative, logic, and object-oriented paradigms. Oot supports optional static typing (higher-order polymorphic gradual typing), automatic memory management, and advanced error handling. There are great libraries geared towards immutable data structures. Oot provides extensive tooling, and is open source with a permissive license.
Oot is a general-purpose language that particularly targets the application domains of expression of computation, exploration of brain-like computational architectures, glue language, exploratory numerical computing, command-line one-liners, prototyping (cross-platform client-side applications and also server-side), live coding, learning to program, and writing new programming languages.
Some downsides of Oot are: lack of speed; memory usage; its goals are insanely ambitous, but its creator is an talentless hack.
Oot aims to combine the readability and ease of Python, the functional laziness of Haskell, the commandline suitability of Perl, the straighforwardness of C, and the simplicity of BASIC (almost), with metaprogramming and massive concurrency.
Next, we're going to expand on each part of the above. Then, we'll go back and give lists of features associated with each goal.
Oot's number one concern is to be readable. We define readable to mean that a moderately experienced Oot programmer can quickly understand someone else's source code.
Some languages (for example, Perl) tend to encourage newcomers to write 'ugly' and hence hard-to-read code. Other languages (for example, Haskell) tend to encourage experts to write 'fancy' and hence hard-to-read code. An example of a language which does neither is Python. That is the sort of thing we strive for.
An important kind of readability is 'skimmability'. Skimming can mean the ability to quickly, incrementally gaining a partial understanding of code without fully understanding the definitions of the terms that occur in that code; to glance through some code and figure out most of the general structure without understanding the particulars; to guess what 'the gist' of some code is without thinking it through; or to traverse a code path or chain to some desired end without having to understand exactly what the other things along the way mean.
As a means to the end of readability, we pursue various other design criteria. Readability implies that code does what you think it will do, so Oot must minimize 'gotchas' (this criteria is also known as the principal of least surprise or least astonishment). This is related to regularity, because special cases are easily forgotten (causing gotchas); and also to language size and simplicity, because in order to understand source code you must recall and understand the language features it uses, and it's hard to remember a large number of of rarely used features, or to understand complex ones. Concise code is often more readable, in that a small program is easier to hold in one's head (and hence to quickly understand). But skimmability can be opposed to conciseness; if you want to understand the gist of something without reading the definition of every terms it contains, then there must be some redundancy to tell you something about what kind of thing the unknown terms are or what role they serve, information that could already be had if you just read every term's definition.
We want our language to be all of:
We define power as maximizing the range of ideas that can be succinctly and naturally expresssed with the language, while minimizing complexity (complexity is the opposite of simplicity) (the use of the word 'power' to denote this concept is inspired by the physics word 'power', meaning energy per unit time). This is a tradeoff. For any language, there are ideas that are difficult to express, or to express concisely, with that language. Any particular idea can be added to the language in the form of a new feature. But each time this is done, the cost is that the language becomes more difficult to understand and to remember. So, maximizing power in a language is like maximizing return-on-investment or profit in a business; add ideas to your language only when you get a lot of "bang for your buck". Each feature must increase expressivity or succintness enough to justify its complexity.
An expressive language is one in which programs can be written the way that you think of them. Expressiveness also aids readability, because if the writer can write a program the way they think of it, the reader does not have to think as hard to figure out the motivation behind it.
todo examples
A succinct language is one in which programs can be relatively short. When the goals of succinctness and readability conflict, Oot favors readability.
For example, Oot favors the ML function calling syntax (eg 'f x') instead of the traditional mathematical one ('f(x)'), because it is more concise.
todo examples
One strategy that Oot uses to achieve power is to try to unify what in other languages would be many concepts, into one general concept, allowing us to pay the complexity cost once and reap many applications. Examples of this strategy:
By 'massive' we mean situations where the number of concurrently executing threads may be comparable to the number of elements of data being operated upon (for example, one thread for each pixel in an image). (this scale is clearly ill-matched to the number of CPUs in present-day computers, so why would you want this? See 'exploration of brain-like computational architectures', below).
Some features Oot provides for massive concurrency are:
When many operations are provided for a few pervasive data structures, it becomes easy to compose functionality. Lisp and Haskell have lists. Python has lists and dicts. Can we do better? Oot has one fundamental data structure, the Oot graph. Lists, associative arrays, matrices, dataframes, relations, partial orders, and more are all special cases of Oot graphs.
In pursuit of as much generality as possible, Oot's graphs are directed, labeled, reified, multi, hyper graphs. Directed, meaning that there may be an arcs from one node to another one, without an arc from the second to the first. Labeled, meaning that nodes and arcs may have data attached to them. Reified, meaning that the target of an arc may be a node, or another arc, or it might be the graph as a whole. Multi, meaning that there may be multiple arcs going from one node to another node. Hyper, meaning that we generalize binary arcs, which have a source and a target, to n-ary arcs, which involve a number of nodes in a number of roles.
A value may have different representations in memory. For example, the integer '-1' might be represented as an 8-bit integer with a sign bit, as an 8-bit integer with twos complement, as a 16-bit integer with a sign bit, etc.
Often we find that one piece of data must be represented in multiple forms because the different functions that need to operate on it expect different data types. For example, a persistence framework may wish to attach metadata to persisted arrays, but this metadata must be hidden when the arrays are to be passed to library that expects plain arrays, yet still present after the mutated arrays are returned. Another example is when a tree data structure must appear as a linear array of nodes for the purpose of passing to a filtering function, but in actuality must retain its tree structure after the undesirable nodes have been filtered out.
Popular constructs for this purpose include type classes and OOP ad-hoc polymorphism; both of which work via the creation of an interface in the form of a set of functions supported by a type (or type class). To borrow the language of RESTful web architecture, this solution amounts to the creation of a new set of verbs for each interface.
Oot discourages types defined by the unnecessary creation of verbs in cases where they can instead be defined more simply as graphs conforming to a certain shape. This allows the pervasive graph operations to be applied to more types. For example, trees and arrays are both graphs with different shape constraints. If data in the shape of a tree needs to be filtered by a function that expects a linear list, instead of creating an adaptor that exposes a set of functions such as next(), the Oot way is to specify the shape transformation that says, for each node in the tree, which item in the list it corresponds to.
To assist in this, Oot provides the concept of 'views'. Oot views allow the same piece of data to be viewed in different ways. They are defined by a specification of the shape transformations (mathematically, homomorphisms) which define the various representations of the same piece of data. A mutation of the data in any of its views affects it in all views. When this sort of thing is implemented in other languages it tends to involve things such as pointers linking together data fields within distinct variables, but by contrast, Oot presents the abstraction of a single variable that holds a single value which can be seen from different views. Views are a type of ad-hoc polymorphism, a way for a piece of data to expose a different 'interface' to various consumers, but these interfaces differ via shape rather than via a distinct function signature.
todo
like spreadsheets
binding is tightly restricted between different state domains (or just 'domains')
todo
Nodes in a graph might correspond to values of a given data type; for example, you might have a graph whose nodes have integer values. But what happens when the type of the nodes itself has a graph structure? For example, if you have a data type A, where A is a list whose nodes are type B, where B is the type of arrays of integers? You might conceptualize an instance of A in two ways; first, as a simple list-shaped graph with opaque nodes of type A; or second, as one big graph whose nodes are integers. The question at hand is: when do we stop recursing into node values and decide to just consider something an opaque 'node'? The difference is not merely academic; for example, when a value of type A is operated upon by a generic library function that visits each node in a graph and applies some transformation, different results will obtain depending whether the graph is composed of arrays of integers, or integers.
Oot allows the programmer to fluidly move between these conceptions via the construct of 'boundaries'. A boundary can be visualized as a wall surrouding nodes in a graph; any remaining structure inside the wall is considered opaque (until such time as the boundary is moved or deactivated). A single graph can be marked with multiple boundaries of different 'color', only one of which is considered the 'active boundary color' at any one time.
Boundaries seem even more important when one contemplates the binding together of different variables in a Oot state domain. In essence, each Oot state domain could be considered as one big graph. The question of where one variable stops and another begins becomes merely a question of boundaries. Taking this viewpoint even further, the different state domains within a program can themselves be thought of components of a larger graph, a single graph containing the contents of all of the variables of the program as subgraphs, separated by various boundaries.
Oot works at a high level of abstraction. This means that you can write abstract code which is flexible enough to be adapted to various uses. It also means that you can express what you want a program to do, and Oot will handle some implementation details for you.
todo
flexible
safe (no segfaults, unless of course you call out to an extension/library written in another language)
todo
The goal of 'handling implementation details for you' can add complexity. Under what circumstances is it worth adding this sort of thing to the language, rather than leaving it to be built in a framework?
Oot's approach to this tradeoff is:
It is inevitable that new programming language constructs will be discovered, and also that there will be application domains for which Oot is almost enough, except for the omission of a few constructs. todo
A language built upon a small core language is also more portable, as only the core really needs to be implemented on the underlying platform, although further optimization can be had by providing platform-optimized versions of other elements of the language.
What's all this you hear from those Lisp guys about a style of programming where first you augment the programming language to suit your domain, then you write a program in your new language? We'd like to do that too.
And what's all this about a small language, a gem-like thing of perfect beauty, in which can be written a (meta-circular) interpreter for itself in only a few pages? Around which a larger, more practical language can be built? That's pretty cool, also.
As a bonus, the effort to find a set of primitives that are good for building a larger language helps us find powerful primitives, and a self-hosting language built on a small core is easier to port. Furthermore, if the language is small enough, and the abstractions are powerful enough to allow it to be implemented concisely, then the language implementation will be readable by ordinary mortals (sans a million optimizations, but we can keep them in a separate module).
todo list meta-programming features
However, we are aware that use of meta-programming features can make source code hard for others to read. Oot provides an (approximate) ladder of meta-programming mechanisms, and encourages the use of the less powerful mechanisms when possible (temperance will also allow us to optimize your code more). The most powerful metaprogramming mechanisms are only for use when all else fails.
todo self-hosting
Oot itself is made of three parts; Oot Core; a language written in Oot Core using metaprogramming; and a large standard library of language-like constructs.
Oot strives to be small, but not minimalistic. For example, 'nand' gates are universal for Boolean functions, but instead Oot bases its Boolean functions on 'and', 'or', and 'not'. Furthermore, we do not try to be minimalistic in the sense that we aren't trying to provide an orthogonal basis set of core primitives. Rather, we strive to be 'multi-paradigm'; when there are multiple paradigms, each with their own characteristic primitives (and when each set of primitives cannot be expressed in terms of another paradigm's primitives except in a clunky or non-local fashion), we try to provide some close to the union of these primitives (or at least all of the 'popular' ones), so that the language can express any of these paradigms.
Used well, metaprogramming can make programs more readable, by making the language more expressive in exactly the ways that are needed for a particular program; the time cost of understanding the black magic is repaid in making it quicker to read the rest of the program. However, a downside of metaprogramming is that it can also be (ab)used to make code that is concise but cryptic.
todo
Oot has a lazy evaluation strategy; values aren't evaluated until they are needed. This allows for separation between definition of data structures in the abstract, and the control flow used to traverse them. For example, if you are writing a chess-playing program, you can represent the entire tree of possible chess board states in a data structure, and worry about how and how far you traverse this unrealized data structure elsewhere.
A useful special case is infinite data structures; for example, you can have an array which contains all prime numbers; unless you try to traverse this array arbitrarily far, this does not cause your program to hang because thhe unaccessed members of the infinite array are never computed.
Lazy evaluation isn't always efficient, and the programmer can request strictness where desired.
(todo: actually, we're lenient; non-strict, but laziness isn't guaranteed either)
todo
attributes
higher-order polymorphic
supports both parametric polymorphism (generics) and ad-hoc polymorphism
Operator overloading and polymorphism is useful for to allow the names of library functions which perform analogous operations on different types of data to be made more succinct and memorable by allowing the same function name to indicate different (but, by convention, closely related) functions depending on the type of the arguments. For example, '+' can refer to both integer addition and floating point addition depending on the types of its arguments; this is easier to remember than having a separate 'iadd' and 'fadd', and also more succinct (since the need to distingush between fewer function names means that the length of these names can be shorter).
Gradual typing
success typing
can use assertions to override/escape type system
"everything is an interface"
todo
Mature code contains a lot of error handling, and programmers spend a lot of time debugging. Therefore, a primary concern of Oot is to reduce bugs (safety) and to provide convenient, readable mechanisms for handling errors.
Oot's approach to safety is to provide strong but optional safety constructs, and to provide an API to allow IDEs to determine which parts of code are safe. Two examples of this are its approach to static vs. dynamic typing, and to checked vs. unchecked exceptions.
Oot has gradual typing, meaning that you can write code without type annotations (and Oot will use dynamic typing to execute this code), or you can annotate some or all of your variables (allowing the compiler to typecheck your code, and also to achieve better performance by omitting dynamic typechecks). Similarly, by default Oot doesn't force you to handle or declare every type of exception that could be thrown by your code (that is, we don't have checked exceptions). Instead, Oot provides an API that allows IDEs to query Oot and ask which unhandled exceptions could be thrown by a given piece of code, and which variables are dynamically typed.
For larger projects which need more safety, Oot offers a 'strict' mode which requires all variables to be statically typed, and all exceptions to be handled.
todo
Oot supports tooling by providing APIs allowing tools to ask the language implementation to do things such as incrementally parse source code, locate which function or scope encloses a given position in source code, find potential auto-completions, etc.
As a text-based language, Oot interoperates well with existing tools such as text editors, build systems, cross-language IDEs, and version control systems.
Oot also strives to provide good tooling including a fast compiler, a canonical source code formatter (ootfmt), good compiler/interpreter error messages, and infrastructure for packaging and deployment.
Much of the practical utility of a language comes from its libraries. We value great libraries, and both the language and the community process are designed to encourage this.
Oot attempts to provide the power of meta-programming while avoiding the curse of Lisp (namely that libraries in a very powerful language have trouble creating enough 'gravity' to attract contributors).
todo
A language is most useful when it is used by many people, so Oot's source code is made available under a permissive open-source license.
todo: which license? Probably Apache? BSD/Apache/MIT? triple disjunctive license? or, aren't those already covertible?
What is a programming language for? Oot is for two things. First, communication between humans, for example an algorithm description in a textbook. Second, software development.
To be good at the first thing, Oot must allow a writer to clearly communicate exactly what they are trying to say (expressivity), and must minimize the labor required for the reader to understand it (readability). To be good at the second thing, Oot must minimize the amount of labor necessary to design, develop, and maintain correct software.
Neurons have an individual refractory period between spikes on the order of milliseconds, yet the brain can respond to a stimulus on the order of a hundred milliseconds. This suggests that the number of serial computation steps involved in recognizing a stimulus, deciding what to do, and orchestrating the motor response are on the order of hundreds of steps (Jerome A. Feldman, http://dl.acm.org/citation.cfm?id=42378 ?). This is many fewer serial steps than a typical computer must execute to accomplish a similar task. But the brain has billions of neurons running in paradigm, whereas a typical computer only has a handful of CPUs. This suggests that in order to explore or simulate brain-like computation, a very different programming paradigm is needed, one which relies on massive concurrency in place of long serial executions.
Another seeming property of the brain's computation architecture is that its 'CPUs' are mixed in with its memory. One consequence is NUMA
Yet another is that the brain is robust to errors (both incorrect or unavilable input, and also internal errors) and never 'crashes'. These sort of ideas are related to 'connectionism', a programme to model cognitive processes with interconnected networks of simple units. It is unclear exactly how the brain actually works, but in order to gain intuition in this area, one idea is to try to create programming languages that seem like they may be suited to this sort of thing. Oot is one such attempt.
Possibly the intuitions programmers develop while using such a language will also be of use for writing practical concurrent software on today's computers, a problem which is attracting the attention of programming language designers due to the the inability of Moore's Law to continue to exponentially increase the serial speed of CPUs, while still permitting a rapid increase in the number of CPUs running in parallel.
Another approach to modeling cognitive processess is symbolist A.I., with methods such as the representation of knowledge as a graph of 'nodes' representing various concepts. This is less alien to traditional programming practices than massive concurrency, and hence less in need of language support, yet Oot also intends to serve this application.
Conventional embedded systems with just one or a few processors is not a target application of Oot, however, if there were a machine that you could buy for around $100 with around 64K very slow, cheap, error-prone processors each with somewhere between 128 bytes to 32K of memory, i hope that Oot would be an okay language with which to program that machine. In fact, Oot seeks to be a general-purpose glue language in another sense; Oot seeks to be an okay language for programs that run on systems with a MIXTURE of: traditional systems (one or a few high-speed CPUs with a large shared memory); GPUs (massively SIMD); massively parallel MIMD systems (many slow CPUs each with a little bit of attached memory).
There are so many libraries already available in other languages, and so many projects already started in other languages, that Oot is expected to often be used to write new code to extend an existing project in another language, or which uses libraries written in other languages.
To this end, Oot is very concerned with interoperability. Oot supports calling to and from, embedding and being embedded, and compiling to and from a handful of popular platforms and languages, with attention paid to preserving idiomaticity, even in round-trip compilations. Oot supports bit- and byte-level manipulation of memory and has facilities for passing along debugging information such as source code line number. Oot programs can easily run other Oot code in a secure sandbox (although i am not very confident that this is actually very secure yet, as it hasn't yet been analyzed by many people), and can easily be stepped through one 'operation' at a time.
In addition, the very structure of Oot, such as the flexible abstractions of views and boundaries, the ease of attaching 'hidden' meta-data to data using labels and views, the representation-agnostic nature of the type system is designed to support the convenient adaptation of foreign data structures and interfaces; other parts of Oot, such as the focus on graphs, and the powerful meta-programming facilities, support compilation and embedding from or to foreign languages.
This affects the design of Oot, in that we want to provide facilities that make it easy to 'map' Oot programming constructs to code in other languages, and vice versa.
Oot can be used to try out the application of various algorithms, transformation, and visualizations to a data set. It can be run interactively or in notebook mode, linear algebra and array operations can be expressed concisely, and there are libraries supporting common numerical and array operations as well as some plotting.
Oot is a convenient language for writing one-liners from the commandline, and also for writing utility scripts. The Oot interpreter starts up quickly, does not require a lot of imports or introductory boilerplate at the beginning of each program, and can be passed flags for convenient pre- and post-processing steps.
Oot is suitable for writing programs which respond interactively to the user via a variety of UI paradigms. The implementation conveniently runs on various desktop, server, and mobile platforms, and the data model, binding facilities, event system, support for reactive functional programming, component architecture system, object oriented and metaprogramming facilities attenuate the boilerplate that traditionally clutters the connection between programs and UI frameworks.
Applications such as simulations, performances, servers, and learning to program often benefit from the ability to change the program code while the program is still running (see live coding). Oot has this; in addition, to make this work well, Oot tries to make it easy to build robust applications.
Oot aspires to be a good first programming language for someone who has never programmed before. The language is not too complex nor too large, there is not a lot of boilerplate to get started, the basic operation of the language is easy to simulate in one's head, it is easy to integrate with GUIs, it runs on cheap client-side platforms that kids are likely to own, and advanced constructs can be ignored until they are wanted.
However, Oot is emphatically a TEXTUAL language, in that the primary representation of program source code is a plaintext file that is intended to be edited with a text editor, in contrast to some other 'learn to program' languages which intend for the programmer to edit their source code via a visualization within a GUI.
As a 'programmable programming language', Oot should be a great vehicle for prototyping and perhaps even writing new programming languages.
Many of the same facilities that make Oot interoperable (graph-based data structures, ease of attaching metadata to data, metaprogramming) also make it a good target for prototyping new programming languages.
In addition, its emphasis on being a good 'glue language', able to use other languages' libraries, and to serve as a bridge between libraries in two different other languages, should make it possible for new languages built with Oot to have immediate compatibility with a large set of libraries from popular languages, easing adoption.
todo
team programming
sandboxing
modular
todo http://en.wikipedia.org/wiki/Scala_%28programming_language%29 has a nice list of individual features, most of which we have. also, add these to PL book constructs list.
Let us discuss some ways in which the goal of readability is achieved.
When syntax is 'scannable', your eye can quickly scan through code looking for where a certain thing occurs.
Declarative code is easier to understand than code which mixes the specificiation of what is true with how it is to be achieved. For example, code which explicitly states invariants in the definition of data types is easier to read than code which provides only the procedure for transforming data and leaves the programmer to infer invariants. todo
Mechanistic concepts are those which consist of a set of parts, each of which has simple behavior and few connections, which can be imagined as interacting in linear chains of causation over time as a program runs. Although theorems are easier to analyze than procedural code with many hidden special cases, mechanistic concepts can be easier to understand than theorems. One reason is that theorems are atemporal in the sense that a premise about later events might imply a conclusion about earlier ones. For example, unification-style Hindley–Milner? type inference can be hard to reason about when code which will execute later contains type constraints that affects the typing of code that will execute earlier. todo
todo
todo ez comments
todo footnotes
(from concise)
(from flexibility)
(from modularity)
todo: cp everything above '== Syntax ==', above, into this table
Oot is built upon a single powerful data structure, the Oot network (net).
Lisp is a homeoiconic language built upon lists. Oot is a homeoiconic language build upon networks (labeled directed graphs).
Semantically, a linked list, a doubly-linked list, an unboxed list (vector), and a hash table with natural number keys are all similar; they are all lists of things indexed by natural numbers, all of which support sequential access, random access, appending, insertion, and deletion. The differences are the space and time complexity of these various operations. In Oot, these things all look the same; if you want to choose one or the other for efficiency reasons, you use type attributes (a kind of annotation) to specify.
In Oot, the following two operations look the same: (a) looking up the third element of the array in variable "x", and (b) applying the function in the variable "x" to the number 3 and getting the result. This allows library functions to present a simple interface that can be thought of in terms of arrays, while allowing the caller to use arbitrary objects in place of those arrays.
Furthermore, fields on structures are treated the same way. This makes it easy to replace a structure that formerly used simple fields with one that uses intelligent getters and setters under the hood (this supports the so-called http://en.wikipedia.org/wiki/Uniform_access_principle ).
Data operations in Oot are, for the most part, expressed as functions on immutable values, rather than as changes to mutable data. Those that are not are clearly demarcated.
However, there is an exception. We freely allow 'local mutation', that is, mutation that takes the form of assigning a value to a symbol within a scope and then later reassigning a different value to that same symbol within the same scope. This kind of mutation could in theory be eliminated by renaming every mention of the variable after the reassignment (and doing some copying in the case of multiple branches, e.g. if the reassignment occurred in only one branch of an 'if' statement). We feel that this is useful to avoid having to create throwaway names for intermediate variables.
We feel that local mutation isn't bad; the bad (confusing) stuff is when you have aliasing of references, that is, when a change to the value of one variable 'magically' causes a change to a different variable (especially when the two variables are located in two different scopes, neither of which is an ancestor of the other).
Oot has a system to allow various frameworks to attach their metadata to values.
The Oot nets are labeled, directed, multi, hyper, reified graphs. Oot networks are:
Nodes in Oot nets can be arbitrary functions.
Each node in a net can used as a simple array or lookup table. However, Oot supports more powerful idioms that regard the network in its totality, rather than each node individually. For example:
Nets can be used to represent regular multidimensional labeled arrays, similar to R dataframes.
A net boundary is a border that cuts through a set of edges in the graph.
Boundaries in code are used to represent atomic operations, exception catching domains, etc.
Net patterns are a matching language that generalize regular expressions and database queries to nets. Net patterns are first-class objects.
A view is a different set of labels and edges associated with the same nodes. Views allow the same data to be presented in different ways to different functions operating upon it. For example, a dictionary could be presented as a list of key, value pairs, and mutations on this list could alter the dictionary.
A mutation to data in one view can affect the same data in other views. When one view is a projection of another, syntax is provided to specify the 'lineage' of data so that metadata attached to a node N1 in another view remains attached to the correct node(s) if N1 is mutated by way of replacing it with a new node.
Since network nodes can be functions as well as static lookup tables, they can be passed around as data.
todo
Oot has a lazy evaluation strategy; values aren't evaluated until they are needed. This allows for separation between definition of data structures in the abstract, and the control flow used to traverse them. For example, if you are writing a chess-playing program, you can represent the entire tree of possible chess board states in a data structure, and worry about how and how far you traverse this unrealized data structure elsewhere.
A useful special case is infinite data structures; for example, you can have an array which contains all prime numbers; unless you try to traverse this array arbitrarily far, this does not cause your program to hang because thhe unaccess members of the infinite array are never computed.
In other lazy languages (e.g. Haskell), it can be hard to reason about and memory leaks (e.g. "space leaks"), or to discover them via profiling. Oot makes this easier.
In addition to providing operators like Haskell's seq and deepseq, which forces strictness in a top-down manner, Oot allows you to mark data values as eager; a function fed eager inputs will eagerly evaluate them. This forces strictness in a bottom-up manner.
Oot presents the programmer with abstractions like 'fold'. The choice between functions corresponding to Haskell's foldl, foldl', foldr, foldr' is made by the compiler based on strictness analysis of the arguments. The sort of analysis discussion on this page ( http://www.haskell.org/haskellwiki/Stack_overflow ) is done by the compiler.
Oot automatically converts 'almost tail recursive' functions with only associative operations preventing them from being tail recursive, to tail recursive accumulating ones.
TODO
Oot can eliminate recursive tail calls, allowing efficient deeply nested recursion.
Oot allows functions to have multiple entry points (this is sort of like a object with multiple methods that is only executed once). The function can synchronize on conditions between these entry points before executing. The notation is uniform with message handling (see below).
For the most part, Oot "long-distance" operations are referentially transparent. Those that are not are clearly demarcated, allowing the programmer to steer clear of unwanted side effects and unexpected shared state.
You can ask the compiler whether any function is referentially transparent. This is accomplished in a similar way to Haskell's use of monads to type non-referentially transparent functions as 'tainted', but it is done implicitly without the need for the programmer to worry about those types or to manually change a bunch of type annotations if you decide to make something non-referentially transparent later.
You can do non-referentially transparent operations without tainting for the purpose of debugging and profiling, in a manner similar to Haskell's unsafeIO.
You can do seemingly non-refentially transparent things without tainting if you promise the compiler that their behavior is actually referentially transparent.
Variable scope is simply defined by the block of code that they are present in, except that there is also a way to refer to the "object" of which a function is a part (a "method" in other languages).
Closures and References are supported but any variable containing a reference or a structure containing a reference are clearly distinguished from values with sigils.
Syntactic sugar for passing objects that mimic dynamically scoped variables.
Oot provides a powerful, uniform, concurrency-friendly mechanism for messages to propagate and be handled.
This is used for event-driven programming, exception handling, dispatch, and parallelization.
Oot has a zoo of powerful constructs for correct, concurrent programming.
todo (see zoo in [1]