Water is a language for the web that embodies the three primary functionalities needed for general purpose information manipulation into one unified language:
- Code: Water is a general purpose object oriented programming language that is, at its core, more flexible than Javascript, Visual Basic and Java.
- Data: Water permits the description of persistent structured data on the web via an XML syntax yet having the capability of computing values that may contain self-referencial interconnections.
- Markup: Since Water is a superset of HTML, it inherits all of HTML's capabilities.
The syntax of Water is a superset of HTML, or, more properly, a superset of XML. HTML has proven to be an easily understandable markup language since it has been learned by millions of people in the several years that the web has existed. XML is a standard for putting structured data on the web. Water extends the syntax of XML to make a language less cumbersome to write code in. Water provides a way to define functions and call them in addition to defining and instantiating objects. The object system is a multiple-inheritance, prototype-based object system with annotations. This will be described below, but for now it's sufficient to say that it is more powerful yet simpler than the class-instance object systems currently in vogue in languages such as Java and C++.
Today's "internet-time" working environments don't permit us the luxury of putting everything on hold while we learn a new language. Even if we know the language of implementation well, we usually can't even take the time for a nice comprehensive design of the ideas. We must get prototypes up fast yet despite programmers' pleas for re-design, prototypes get turned into products due to competitive pressures. We need a language that supports this reality.
Like HTML, Water permits you to just write a paragraph of English text and call it a web page. Also like HTML, you can take another pass and add markup without having to rewrite your original text. You need only learn the HTML tags that you need to know. However, should you require more dynamic behavior, with Water you needn't learn a new scripting syntax such as Javascript, or worse, a whole new programming environment such as Java. You can simply insert Water tags into your page using the same basic syntax that your markup is in. Plain text, markup, data, and code can be freely intermixed with no barriers between those functionalities and no "impedance mismatches" between text, markup, data and code. Water tries hard to give the user the most functionality per learning effort, emphasizing economy and elegance at the expense of hairy and rarely used features.
Right now the plethora of languages on the web causes more than headaches. New ones seem to be born monthly. Having to learn two or more to get a task done is more than twice as hard as one language because the interface between the languages is always additional hair which is, more often than not, poorly documented.
Why do we have HTML, XML, Java, Javascript, C++, Visual Basic, VRML, XSLT, PHP, etc? Because none of them are flexible enough to give programmers the functionality they need in building a modern Web application. Looking within the scope of what each of the above intends to cover, we often find serious flaws. But when we try to move outside of that scope, say doing markup in Java, we have a full-fledged disaster on our hands.
We do not need a new language for implementing some specialized functionality. Sooner or later that specialized functionality will need general purpose utilities like conditional execution, loops, functional abstraction, etc. When these are added on to special purpose languages late in the game, elegance is compromised by compatibility with the original specialized language and we end up with a mess. Its far better to add a special purpose capability onto a general purpose language than the other way around. Water is designed to not let the generality get in the way of special purpose functionality. For example, HTML is essentially an "add-on" to the core of Water. You can create a static web page containing only HTML tags as you do now, yet Water makes it easy to extend the page into a full-blown program. Since Water can accomodate plain text, you can start with text and gradually introduce markup and active code.
We do not need a new language whose primary virtue is that its easy to learn because it looks like another language. If you want a language that's, say, easy for C programmers to learn, then you'd have a hard time beating plain old C.
We do not need a new language to eek out that last bit of speed from our hardware. With smarter compiler techniques, the interface between the human and the language is becoming far more important than the interface between the language and the machine. Java was initially attacked on the grounds that it was too slow, and under some running conditions still is. But smarter compiler technology and native code compilation will make that argument obsolete. Don't get me wrong. Efficiency of execution is very important. But it shouldn't unduly cloud key syntax or semantics design.
We need a new language so we can accomplish all of our tasks with one language. The requirements are tough:
- Flexible and extensible
- Comprehensive, encompassing markup, persistent structured data and general purpose code
- Easy to learn WHILE doing
- Easy to remember after initial learning
- Easy to implement [or it will never exist]
- Easy to write tools for.
Good environments can be built on top of mediocre languages with a good deal of effort. Great environments need a language that supports tool building. The difference between good environments and great environments is tens or even hundreds of percents in speed of implementing reliable, maintainable programs. Increasing programmer productivity is the ultimate goal, not just by handing existing programmers more powerful tools, but by giving people who consider themselves non-programmers the power to radically customize their computer.
The target audience for Water spans a broad range of skill sets. An HTML developer can learn the basics in a few days, yet a Lisp or SmallTalk developer will feel right at home with Water's power and flexibility. Although Water can fulfill most of the needs of the general purpose programmer, someone who's spent years learning a difficult language like C or Java is hard to convince to give up on their investment even if they can exceed their previous productivity in a few weeks. Although many Water programs look trivial, the beauty of Water is the elegance and consistent that makes complex things look simple. Water is not simplified at the expense of being able to accommodate complex programming tasks.
Water brings to the table capabilities that are not simple "add ons" to an existing language. It contains concepts not present in today's popular languages. Yet it doesn't start off by throwing today's web author in cold water either.
- Minimal differences between markup, data, and code. Seamless integration between HTML and code.
- Minimal differences between classes and instances. Prototype object systems have just one kind of object. No need to learn separate operations for classes and instances since there's no distinction between a class and an instance. An object can be used "as an instance", and/or it can be "subclassed" with the new object inheriting the desired characteristics of its parent(s) while other characteristics are modified to differentiate the new object from its parent(s).
The language "Self", invented at Sun but never made into a product, had a simple and elegant prototype-based object system. Self's object system differs from Water in that it was only single-inheritance and had a "copy down" semantics for inherited values rather than the "dynamic look-up" mechanism of Water. Water's multiple-inheritance is easy to avoid should you find that it adds too much conceptual hair. The dynamic lookup of Water makes object creation faster and uses less memory than "copy-down". It also preserves locality of reference for shared data which may have additional speed advantages for hardware with limited caching. But if "copy-down" is desired, the "init" function for object creation of a given parent object can choose to copy down desired fields. If this proves to be important, Water could provide higher level support to make this easy. Hence, Water is a superset of Self in these regards.
- Minimal difference between "instance variables" and "methods". Each are stored as values of fields in an object. You can get the value of an instance variable or a method by just getting the value of a named field. Methods are implemented by objects just like everything else in the language. To CALL a method, you use the function calling syntax which looks like using an HTML tag.
- Minimal differences between a function call and object creation. The tag name refers to the parent object. The parameters after the tag name serve as either function arguments or field initializers depending on whether the value of the tag is a method or not.
- Minimal differences between aggregate data types. Objects, vectors and hash tables are all represented by the same data structure. An object is a set of fields whose keys can be any object [interned strings, numbers, other objects]. When you're treating an object as a vector, a looping mechanism permits looping over all fields whose keys are integers. A "length" field makes finding out the size of the vector quick as well as facilitating "adding an element" to the end of the vector.
- No differences between the object system and the type system. For example, "integer" can be thought of as a "type" but its really just another object in the object tree that happens to be the parent object of all integers. You can reference all objects used as types via the path syntax, just like you can reference all fields of objects. In fact, since any object can become a parent, any object can effectively be a type.
- Minimal differences between the init method to create new objects and normal methods. An init method can, in fact, return any type of object and should declare the returned type of object.
- Minimal [but very significant] differences between local variables, and object fields, for creating, setting and referencing.
- Minimal differences between a field and an annotation to that field. Water provides a way to add information ABOUT a field. Say you have a field named "color" in an object named "car". You might want to add a comment about the field such as "all colors besides black and white cost extra" or declare that the type of the field must be an integer. Annotations are the mechanism that Water uses to associate information about a field with that field. Annotations of a field "foo" are indicated by another field with a naming convention of "foo@annotation-name". A looping mechanism makes it easy to find all annotations of a given field or to ignore all annotations of an object when you want to loop through an object's field values.
- Water provides an easy way for a programmer to specify the "evaluation kind" of each parameter in a method definition. This controls how each argument in a call to the method is interpreted. It can be treated as code and evaluated (the default), treated as an expression to be parsed but not evaluated (especially good for "delayed evaluation" where a method takes code as an argument and can evaluate the code when it chooses), treated as the string of its source code (and not even parsed), and hypertext, which treats text within angle brackets as code to evaluate and other text just as strings (especially convenient for implementing HTML tags as Water objects or method calls).
- Water's object system permits the parent of an object to be changed at runtime. Not a common situation, but sure makes it easy for a parent to "adopt" a child.
- In HTML you usually use keywords to specify each attribute. XML requires the use of keywords. In Java and Javascript you can't use keywords to specify any argument. Water permits you to use keywords when you want to be more explicit or pass arguments "out of order" and pass arguments by position (without keywords) when you want to be more concise. There is no extra overhead for declaring keywords when defining a method, they are simply the parameter's name.
- "Active Values" on object fields facilitate simple constraints and, along with other dynamic features, help to implement spec changes after most of the implementation is done by permitting field references and setters to turn into method calls without changing the referencing and setting code at all.
- Water is especially easy to write tools for due to its extensive introspection capabilities, evaluation kinds, elegant object system, uniform syntax, ultra-dynamic behavior and small size.
Some of Water's features provide fixes for inconsistencies and other unnecessary complexities in Java that will probably never be fixed in Java due to its momentum and lack of vision.
- Unlike Java, all Water data types are full-fledged objects. There are no "ints" and "Integers", just "integers".
- Unlike Java, Water has true multiple inheritance. There is no extra "interface" mechanism.
- Unlike Java, Water supports both a prefix syntax and an infix syntax--automatically. Water does not need precedence rules or parentheses.
- Unlike Java, the types of fields and method return values need not be declared. They default to the most general type of object. However, type declarations are encouraged as they help declare the programmer's intent and can be used by programs to find inconsistencies in the programmer's intent as well as speedup execution.
- Unlike Java, the "init" method is just like a regular method. Its body returns a value [usually but not necessarily a subobject of the called object]. It's syntax is just like a regular method, rather than Java's "constructor" syntax.
- Unlike Java, instance variables can be created or removed within an object at run time.
- Unlike Java, you can add methods to a "class", extending its behavior without having to edit and recompile the original source. Water gives the programmer more flexibility in modularity so that a method for a class need not reside in the same file as the class definition if that's what the programmer chooses.
- Unlike Java, Water's evaluation kinds permit the easy construction of high-level code manipulation methods which in many cases reduce the complexity of packaging up and calling advanced functionality.
-Unlike Java, there is rarely a need to create a "singleton", ie a class with one instance object. That's because in Water, a "class" object can be treated just like an instance object. You can call its methods directly using the "class" as "this". There is no need to have a distinction between static variables and instance variables, nor static and instance methods. And each "instance" object in Water can get its own special version of a method, if the programmer so chooses, to distinguish its behavior from that of its sibling objects. "Static" is another concept you just don't have to know about in Water.
- Compared to Java, Water is much more consistent with itself. For example, Java has three different syntaxes for programatically determining the length of an array, a vector and a string. Water has one.
Water has a lot in common with Javascript:
- Water and Javascript can be embedded in HTML
- Water and Javascript are interpreted
- Water and Javascript both have "eval" though Javascript doesn't have a "parsed but not evaled" representation using for programs that manipulate code.
- Water and Javascript objects can both have fields added dynamically, after an object is created.
But there's a lot of differences as well:
- Water can be "more" embedded than Javascript within HTML. Generally speaking, Javascript can only be attached to certain control attributes of HTML tags. Water permits active code just about anywhere within HTML.
- Water's syntax is much more like HTML than Javascript's.
- The object system in Javascript is designed to be a "prototype" object system. Yet it is, at the very best, poorly documented. Water's prototype object system is easier to use.
- Water permits (but does not force) the declaration of types for arguments and object fields. Javascript does not permit type declarations.
- Water has much more flexible argument definitions which can take default values and "evaluation kinds" in addition to names and types.
- Water has a simple, concise syntax for referencing objects through long paths in the object hierarchy and interconnected field values.