Alphabetical listing by Path
The XML syntax for CDATA is supported to allow for the creation of strings with weird sets of characters in them such as unbalanced quotes. A CDATA 'call' is bounded by open and close angle brackets. Inside the open angle bracket is the character sequence ![CDATA[ Inside the close angle bracket is the character sequence ]] Between those delimiters you can have any character sequence except ]] followed by a close angle bracket. The result of executing a CDATA call is to return a string of the characters between the CDATA delimiters. Note that for a CDATA call the ending is not slash close-angle nor a full closing tag named CDATA. See also <string>foo</>
When Water looks up a field in an object and doesn't find it in the object or any of its
ancestors, it calls the method "_if_missing_method" with the object as "_subject"
and the field name as the first argument (named "the_key").
If _if_missing_method is itself not found, execute_expr returns null.
The method _if_missing_method is looked up just like a regular field reference
For example, if we have a hierarchy of:
thing
vehicle
boat
and we execute boat.anchor, and there is no anchor field in boat, vehicle or thing,
then execute calls boat._if_missing_method.
If there is no such field in boat but there is one in vehicle, then
the one in vehicle will be called with the name of the missing field
as "_subject" like so: "anchor".<thing.vehicle._if_missing_method/>
Whatever this call returns is the returned value of our original boat.anchor.
Example:
<defmethod _if_missing_method the_key>
"big_hairy_missing_field"
</defmethod>
Take care to define your versions of _if_missing_method all with an argument
named "the_key".
The original caller of boat.anchor is never aware that anchor isn't actually
a field in boat. If you really want to tell, you can call container_of or 'has'.
Most of the time you attempt to access a non-existent field, you probably want
the system to error so you can find out about and fix typos as soon as possible.
So if you do define _if_missing_method, be sure to remove it when you're done
or it will continue to "not error".
Example: thing.<remove "_if_missing_method"/> will set Water back to its
default, "error upon non-existent field" behavior.
See xml_and_water for an extended example.<active_value />
You can set a variable such that instead of just returning the value in the field, it will execute arbitrary code instead. The documentation for "set_value" has an extensive description of active_value.
<and rest="unnamed"='ek_expression' />
Returns true if its subject and all of its args execute to true. You may call and with or without a left-hand subject. Examples: true.<and true true/> returns true true.<and false true/> returns false <and true true/> returns true.
<append rest=required />
Returns a new vector containing all the elements of "_subject" and
each vector in rest.
_subject defaults to the empty vector.
Does not modify any arguments.
Examples:
<vector 3 5/>.<append <vector 7 9/>/> returns <vector 3 5 7 9/>
<append <vector 3 5/> <vector 7 9/>/> returns <vector 3 5 7 9/>
See also: concat,
file.append which extends the content of an existing file.<assert a_type= name=null if_failure=<get_type_checking/> />
If '_subject' is of type "a_type" then return '_subject' otherwise, indicate the failure based on the arg: 'if_failure'. "error" means error. "warning" means print a warning but still return '_subject'. "off" means don't even do the type check, just return '_subject'. The default value is <get_type_checking/> which will be one of the above three options, which itself is "off" by default. See also: get_type_checking
An attributes tag is a way to encode flexible attributes like tohse of ConciseXML
in a pure XML 1 syntax. ConciseXML is more convenient syntactically,
but when you must have XML syyntax, use the 'attributes' tag.
Note that 'attributes' is not a method, it is a syntax handle specially by the
Water parser.
Examples:
<defmethod> <attributes>foo myarg=required=number="ek_code"</attributes>
myarg
</defmethod>
<foo> <attributes> 291 </attributes> </foo> returns 291
<foo> <attributes> myarg=291 </attributes> </foo> returns 291
Concise XML for the above is:
<defmethod foo myarg=required=number="ek_code"> myarg </defmethod>
<foo 291/> returns 291
<foo myarg=291/>
The to_xml formatter puts out strings that contain calls to 'attributes'.
See also: to_xmlboolean.<random_instance />
Returns true or false with equal probability, just like flipping a coin. Example: boolean.<random_instance/> returns true or false. See also: integer.random_number, integer.random_instance, thing.random_instance
<cache_instance add_vector_key=false if_exists="set" />
cache_instance is a method typically used in an init method of a defclass.
It stores an instance in the "of" field of the class.
First cache_instance looks up the 'primary_key' of the parent of the
_subject to cache_instance. The primary_key of 'thing' is "id" so
that is used if there is no other primary_key found.
Then the _subject is examined for a field with the key of the primary_key,
i.e. "id". If the _subject as no primary key in it (no lookup is performed here),
then no further action is taken and the _subject will not be cached.
Otherwise, if there is no "of" field in the parent of subject then
it is created using <thing/> as its value (making an object with parent 'thing').
Then the name of the _subject is retrieved by getting the value of the field
within subject whose key is the value of 'primary_key'.
Then the field of the primary key name is set within the value of "of"
to the _subject.
Here's how it works;
<defclass boat>
<defmethod init> _new_object.<cache_instance/> </defmethod>
</defclass>
<boat id="bluebelle"/>
The above call returns our new instance since the init method is called
and its last expression is a call to cache_instance which returns
its subject, in this case the '_new_object' which is our new instance
of boat named "bluebelle".
But the important thing is the side-effect. Now
boat.of.bluebelle returns our new object.
Note that since there was no primary_key in boat, the primary_key
defaulted to 'id'. Since our new instance has an id of "bluebelle",
the instance was cached.
We can create an instance WITHOUT caching it if we like by not giving it
an id such as <boat/> or <boat weight=123/>. We might do this if we were
creating a temporary boat.
Caching an instance makes it convenient to reference the object via
a path of its class name, followed by "of" followed by the name of the
instance.
Should we want our "name" field to be called something other than 'id':
<defclass boat primary_key="licence_plate">
<defmethod init> _new_object.<cache_instance/> </defmethod>
</defclass>
<boat licence_plate="bluebelle"/>
boat.of.bluebelle.licence_plate returns "bluebelle"
cache_instance takes one argument, add_vector_key (default false).
If this argument is true, an additional key is added to the "of" object which
is the next highest integer key available in the "of" object.
This makes it easy to count the number of instances, maintain the
order they were created in and reference them by an integer like so:
<defclass boat>
<defmethod init> _new_object.<cache_instance true/> </defmethod>
</defclass>
<boat id="bluebelle"/>
<boat id="old paint"/>
boat.of.<length/> returns 2
boat.of.0.id returns "bluebelle"
boat.of.1.id returns "old paint"
The formatting method to_h2o has special support for cached instances.
boat.<to_h2o only_print_instances=true/> turns off the printing of the
call to defclass and the printing of all its attributes.
It does however leave on the printing of the "of" field and all the "of" fields
of all the subclasses of the class you are printing.
Use only_print_instances=true when you want to save the instances of a
class in a file but not the classes that they came from since you probably
load them as part of the loading of your application.
See also: defclass, init, to_h2o<call a_object=required args=<thing/> a_context=<context/> />
Call is a method to perform calls programmatically.
It is an advanced feature not needed for most uses.
The subject of the call can be passed in either as an explicit argument of _subject,
or as the left hand subject to the call of 'call' itself.
The first argument is the "method" or the class of the object to be constructed.
If it is a string, it is taken to be the name of the method or object within
the subject.
The second argument is an object containing the args to pass to the method.
This can be a vector, in which case all arguments are "by position".
You can also use a record as the value of the second argument.
The unnumbered non-system fields will be used to pass args by key,
with the key being the key of the field and the value being the value passed in.
the numbered field of the record (in which case you'll have a 'supervector'),
will be the by-position arguments.
With call you can pass arguments by-position as well as by key.
All of the arguments to call are executed, then the actual call
is made with those values.
Examples:
Given a definition of thing.<defmethod foo boo bar baz> boo.<concat " " bar " " baz/> </>
<call "foo" <vector 10 20 30/> _subject=thing/> returns "10 20 30"
and is equivalent to thing.<foo 10 20 30/>
thing.<call thing.foo <thing boo=10 bar=20 baz=30/> /> returns "10 20 30"
and is equivalent to thing.<foo boo=10 bar=20 baz=30/>
<call thing.foo <thing 0=10 1=20 baz=30 _subject=thing/> /> returns "10 20 30"
and is equivalent to thing.<foo 10 20 baz=30/>
If the method takes rest arguments, then the same rules apply as to how the
arguments are mapped to the parameters as will normal calls, i.e.
First all the keyed arguments are mapped to the same-named parameters,
then the first arguments are applied to all the required arguments of the
method, finally the remainder of the by-position arguments are used
for rest args. As usual in calls, if rest args are permitted, then
no by_position args get mapped to optional parameters.
Constructing new instances of a class works similarly:
<call thing.<defclass boat weight/> <vector 241/> /> returns <thing.boat weight=241/>
The context arg can take a record or a context just like execute_string
See also execute, execute_string.<char rest=false />
The way to make a character literal is <char "a"/>
You can use the escape sequences on strings to get non-printing characters.
Example:
<char "\n"/> for newline
<char "\t"/> for tab
See the documentation on "string" for more escaped characters.
Note that unlike the Java type "char", the Water "char" is
a real object.char.<less a_char=required />
Returns true if "_subject" is alphabetically less than the argument. The ascii numerical equivalent of the character is used in sorting.
char.<less_or_equal a_char=required />
Returns true if "_subject" is alphabetically less than or equal to the argument. The ascii numerical equivalent of the character is used in sorting.
char.<more a_char=required />
Returns true if "_subject" is alphabetically more than the argument. The ascii numerical equivalent of the character is used in sorting.
char.<more_or_equal a_char=required />
Returns true if "_subject" is alphabetically more than or equal to the argument. The ascii numerical equivalent of the character is used in sorting.
char.<to_lowercase />
If "_subject" is an upper case letter, returns the corresponding lower case letter otherwise returns "_subject". Example: <char "A"/>.<to_lowercase/> returns <char "a"/> See also char.to_uppercase, string.to_lowercase
char.<to_uppercase />
If "_subject" is a lower case letter, returns the corresponding upper case letter otherwise returns "_subject". Example: <char "a"/>.<to_lowercase/> returns <char "A"/> See also char.to_lowercase, string.to_uppercase
from and two can be any combination of one character strings,
characters, or integers. If integers, the ascii character of
that integer will be used.Creates a string whose first char is a open square braket and whose last char is a close square bracket.
Each of the rest arguments may be a string, a character or an integer.
The arguments are concatenated together, wrapped in square brackets and returnd as a string.
String-valued arguments have their outer square-brackets stripped off if any and used as is.
Chars are used as chras in the resulting string.
Integers are converted to their ascii equivalent chars and used in the resulting string.
Args of the format that are generated by not_char_set ie [^abc] are not allowed and will cause an error.
The content is not evaluated during the call. Each char in the content source is inserted into
the resulting string.
Example:
<char_set abc def>ghi</> returns [abcdefghi]
<char_set abc <char_set def/>/> returns [abcdef]
An open square bracket can be inserted into a char_set as is but a close
square bracket must be escaped.
Example:
<char_set "a[\\]"/> Includes three characters, a, open square bracket and close square bracket.<char_vector_to_string />
Converts a vector of chars into a string. If an item in the vector is not a char, error. Example: <vector <char "w"/> <char "e"/> <char "r"/>/>.<char_vector_to_string/> returns "wer" See also: string_to_char_vector, from
<
Creates a color from components red, green and blue each of which can be an integer from 0 through 255. Examples: <color 255 0 0/> makes pure red <color 0 255 0/> makes pure green <color 0 0 255/> makes pure blue <color red=0 green=0 blue=255/> same as above <color 1 2 3/>.green returns 2, the integer value of green
<combine a_method=concat first_value=optional />
"_subject" is a vector. a_method is called with first_value as "_subject" and the first element of the vector as the first argument. The result is stored and used as "_subject" for a second call to a_method with the 2nd element of the vector as the new first argument and so on until the end of the vector is reached. Using just the default arguments, to_html is called on each of the elements in the vector and concatenated together to yield one big string. Examples: <vector 2 3 4/>.<combine number.plus 0/> returns 9 <vector 2 3 4/>.<combine number.plus 1/> returns 10 If first_value is not passed, then it is as if the first_value is the first element of the vector and we process the 2nd through nth vector elements the same as above. Example: <vector 2 3 4/>.<combine number.plus/> returns 9 See also: is_sorted
<compute_file_path_for_field the_key=null dir_to_start="logical://system/" />
Warning: this method probably busted due to the switch
away from the field "subobjects".
"_subject" must be a subobject of its parent and have an "_id".
Examples:
With an object hierarchy of:
thing
color
size
number
plus
minus
integer
thing.number.integer.<compute_file_path_for_field/>
returns D:somedir/com/glueworks/glue/thing/number/subobjects/integer.h2o
thing.number.integer.<compute_file_path_from_field "plus"/>
returns D:somedir/com/glueworks/glue/thing/number/integer/plus.h2o<concat rest=required />
Returns a string of the concatenation of calling to_html on "_subject" plus each of the rest arguments. _subject defaults to "". Examples: "abc".<concat "def" "ghi"/> returns "abcdefhi" <concat "def" "ghi"/> returns "defghi"
<container_of key=required />
Returns the object that key was found in or false if key isn't in any ancestor. Note: if "_subject" is false, and key is "_parent" then this method will return "the object in which the field was found" which happens to be the "false" object, so that's misleading. But note that all objects (except thing) have a parent, so normally container_of isn't called with key of _parent anyway and rarely on the false object. See also 'has'.
Returns the current execution context. Context is used as an optional argument to execute_expr and execute_string to describe the execution context for the code to be executed. The context contains the stack of local environments being called as well as the fluid variables currently defined. See also: environment_of_call.
<copy include=return_true=defmethod limit=optional include_limit=true other_named_args=true />
Returns a copy of _subject.
If subject is a literal (string, number, boolean, char, null), just return it.
include is a method that is called for each field key that may be copied.
if it returns true, the field is included in the copy, otherwise it isn't.
Copy uses two attributes to determine how many ancestors to go up from '_subject'
and grab field values from.
'limit' is an object that is presumably an ancestor that sets the limit of how
far up copy will go looking for fields.
If include_limit is true, include the fields of the limit object,
otherwise don't, only include fields below the limit object.
Never are fields above the limit considered for copying.
Only the value of the first field of a given key that is found on the way up
is used in the copy.
By default, include is 'return_true',
limit is '_subject' and
include_limit is true
so that all the fields immediately in '_subject' are copied and no more.
If additional named arguments are passed to copy, those fields are added to the
result. If an additional arg has the same name as a field in the original,
then the passed in value will override the original's value for the field.
See also: for_each for a more complete description of 'include'.
merge_down_into for a way to copy fields into an existing object.
defmethod.copy which is very similar but does a few special things for methods.<copy_down />
Used within an 'init' method to easily copy down all the data
fields of the class into the instance. It returns the modified _subject.
<defclass foo x=5>
<defmethod init>
_new_object.<copy_down/>
</>
</defclass>
Now all the instances of foo will have their own version of the field x.
foo.<set x=99/> will not be seen by the foo instances since they
now shadow the value in their parent.
Note this is similar to class_instance object systems wherein the instances
always have their own copies of the instance variables.
In Water, if an instance doesn't have a variable it looks up into its parent
to get the value.
Only the field keys in the _field_order of the parent are copied down.
Fields that already exist in the subject are not copied down.
See also: init<count predicate=required />
count returns the number of specified items in "_subject" which is expected to be a vector.
If "_subject" has no integer numbered fields, zero is returned.
If predicate is a method, then that method is called with "_subject" equal to each
element of the original "_subject". If a predicate call returns non-false,
then that counts as one for the result.
If predicate is NOT a method, then compare each element in "_subject" with the
predicate via "is" and if that returns true, then that counts as one.
Examples:
<vector 1 2 3 4 5 6/>.<count <defmethod more2> _subject.<more 2/></> /> returns 4
<vector 1 2 4 1 7 8 1/>.<count <defmethod is_one> _subject.<is 1/></> /> returns 3 i.e.
the method is_one is called for each element of the vector and returns true for 3 of them.
A simpler (but less general) way to write the same thing is:
<vector 1 2 4 1 7 8 1/>.<count 1/> returns 3
"line one\nlinetwo\n".<count <char "\n"/>/> returns 2 , i.e. finds the 2 newline chars in "_subject".Processes the header of a csv string just like csv_to_objects with keys="from_header" and returns the header as a vector of strings. Does not look at the non-header portion of the csv string.
Very similar to the method 'to_objects' using the default value for field_separator ( comma ) and the default value for object_separator ( newline ), however, fields may be double-quoted strings that can contain commas and newlines. If a line has no fields, no object is created for it. By default, the maker is called with by-posiiton arguments from the fields of each row. However, you can specify calling the maker using keyed arguments using the 'keys' parameter. This defaults to null meaning pass arguments by-position. If it is a vector, that will be a vector of the argument keys to call the maker with. You can automatically get the keys to use from the csv data by specifying a row to get the keys from as an integer. Usually this will be one of the rows specified for the header (see below). Alternatively, you can specify to get the rows from the header by passing in "from_header". (see below) A header is declared by passing in the header_first_row and header_length. header_first_row defaults to 0 meaning the first row in the csv data. header_length defaults to 0 meaning there are no rows in the header. If the header_length is positive, there is a header. The rows in the header will NOT be used for data and no output objects will be generated from them. Data will come only from rows after the header. Rows before the header will be ignored. If you simply want to skip say, the first 5 rows at the top of the csv data, declare a header_first_row of the first row of actual data, ie 5, and leave the header_length defaulting to 0. This acts as if rows 0 through 4 did not exist in the data at all. If you have a multi-lined header, and you specify a 'keys' value of 'from_header' then each field will be a concatenation of each field in the header for that column. An underscore is placed between the fields. Each key from the header is "trimmed" to get rid of whitespace before or after a header field. When calling a maker with keys, if the number of data items is less than the number of keys, the extra keys will not be used in the call. If the number of data items is greater than the number of keys, then they will be passed by-position to the maker. A maker that cannot handle the arguments it is passed will error in the usual way that any method or object constructor would error if it was passed too many arguments. See also: to_objects
<data />
Takes a string in XML syntax and returns a "data" representation of it Parses the XML and converts tagnames (other than <ex thing/> or <ex vector/>) to a symbol instance. The string of XML can be given as the subject or the content. <Example <data><foo><bar>10</bar></foo></data> <<symbol "foo"/>><<symbol "bar"/>>10</></> /> <Example "100".<data/> 100 />
<datetime year=null month=null day=null hour=null minute=null second=null millisecond=null base=null date_separator="-" time_separator=":" />
datetimes are constructed by passing in a base datetime and the overriding particular
attributes of the base datetime. Once a datetime is created, it is considered to be immutable and
cannot be changed. To get a slightly different datetime, you must create a new one.
The base datetime defaults to year 1, month 1, day 1, hour 0, minute 0 second 0, millisecond 0.
Thus the call <datetime/> returns a datetime with those defaults.
A base datetime can be any one of:
A string such as "Mon Feb 18 20:21:00 EST 2002", "3/22/2002", or "3/24/02"
A Water datetime object
A java date object.
If base datetime is a string, any format acceptable by Java's Date constructor that takes a
string argument is legal. Note that any string returned by some_water_datetime.<to_html/>
is acceptable.
year Must be a full year integer ie 2002. If you say 2 that means 2 years after 0 AD.
month an integer between 1 and 12 inclusive
day an integer between 1 and 31 inclusive
hour an integer between 0 and 23 inclusive
minute an integer between 0 and 59 inclusive
second an integer between 0 and 59 inclusive
millisecond an integer between 0 and 999 inclusive
Examples:
<datetime>3/22/2002</> March 22, 2002
<datetime base="3/22/2002"/> March 22, 2002
<datetime base="3/24/02"/> March 24, 2002
<datetime 2002 3 24/> March 24, 2002 at 0:0:0
<datetime 2002 3 24 14 45 46 555/> March 24, 2002 2:45:46 PM and 555 milliseconds
<datetime year=1999 base="3/22/2002"/> March 22, 1999
datetime.current returns a datetime of the current day and time.
date.current returns current date (time of 0:0:0)
time.current returns current time
datetime.time is a method that takes 4 arguments, hour, minute, second and millisecond.
The default for each is 0. It constructs a datetime with year=1, month=1, day=1.
Examples:
<time 14 20/>.<to_html/>
14:20:00
There are many ways to print a datetime.
a_datetime.<to_html/> returns string of format: "Sun Mar 24 21:05:41 EST 2002"
a_datetime.<m_d_yy/> returns string of format: "3/24/02"
a_datetime.<mm_dd_yy/> returns string of format: "03/24/02"
a_datetime.<mmm_d_yyyy/> returns string of format: "Mar 24, 2002"
or roll your own by accessing different fields of datetimes:
a_datetime.yy a two digit string
a_datetime.mm a two digit string representing the month
a_datetime.mmm a three letter month abrieviation
a_datetime.month_name a string with a full month name
a_datetime.h24 a two digit string representing the hour from 0 to 23
a_datetime.hh a two digit string representing the hour from 0 to 11
a_datetime.am_pm either "am" or "pm"
a_datetime.nn a two digit string representing the minute
a_datetime.ss a two digit string representing the second
a_datetime.ww a two letter string representing the day of the week.
a_datetime.www a three letter string representing the day of the week.
a_datetime.day_of_week_name The day of the week in full English.
a_datetime.day_of_week Returns an integer for the day of the week, 0 for Sunday, 6 for Saturday.
Datetimes have comparators: equal, less, more less_or_equal, more_or_equal
and arithimetic: plus that takes an argument of a duration and
minus that takes an argument of a duration or a datetime.
See also: duration, datetime_interval.
<db_resource
a_uri=required=
db_resource contains the classes and methods for
Water Database. Water Database is the standard Water
library for connecting Water programs to relational
databases.
Water Database uses standard JDBC drivers. Below are
instructions for how to configure different databases.
To setup databases with specific drivers: (Example: MySQL)
1. Download a JDBC driver. It should be packaged as a .jar file.
2. Put the JDBC .jar file into the 'jre/lib/ext' folder of your
Java Runtime Environment.
(Example: C:/jdk1.4/jre/lib/ext or C:\Program Files\Java\j2re1.4.1_02\lib\ext)
3. Configure the database for local and/or remote access
(Example: for MySQL, use the MySQL Control Center (mysqlcc) program)
Enter usernames and passwords (or leave empty)
4. Start the database
(Example: D:/mysql/bin/mysqld )
5. Execute Water Database commands (see examples below)
To setup a local Access 97 database under Windows:
1. Under the Control Panel, setup the ODBC settings and
2. Add a System DSN
3. Choose a type of "Microsoft Access Driver"
4. Enter a Data Source name (Example: my_db)
5. Click "Select..." button to select an mdb file (Example: my_db.mdb)
6. Choose "Advanced..." and setup the Default Dir (Example: C:\my documents)
7. Enter user and password fields (or leave blank)
8. Start the database
9. Execute Water Database commands (see examples below)
Create a new database repository. A single repository can
hold one or more databases. Note: repository is a subclass of
db_resource, but it is promoted.
<Example
<repository
a_uri="jdbc:mysql://localhost/"
protocol="com.mysql.jdbc.Driver"
/>
result=repository.of."jdbc:mysql://localhost/"
/>
Any SQL query can be executed on a repository using
<ex execute_sql/>. <ex execute_sql/> takes an SQL statement
in the hypertext content area. An ending semi-colon is not
required.
<Example
repository.of."jdbc:mysql://localhost/".
<execute_sql> SHOW DATABASES </>
result=
<vector>
<thing Database="primary_db"/>
<thing Database="mysql"/>
</vector>
/>
The database connection can be found in field named
"a_connection", although you typically do not need to
access it. The connection gets created on the first
database request.
<Example
repository.of."jdbc:mysql://localhost/".a_connection
/>
CREATING A NEW DATABASE
<ex database/> Creates a new database within the repository.
If no connection is given, it will reuse the connection
from the repository. The database can be accessed as a field
in the repository. The following example shows creating a
new database named "test_db":
<Example
repository.of."jdbc:mysql://localhost/".<database "test_db"/>
result=repository.of."jdbc:mysql://localhost/".test_db
/>
Alternatively, you can create a database connection that
is separate from the database connection for the repository.
Set the database resource to the local variable "my_db"
<Example
<set my_db=repository.of."jdbc:mysql://localhost/".test_db />
/>
Create a new database table named 'book' using SQL:
<Example
my_db.<execute_sql> CREATE TABLE book(isbn VARCHAR(255),
title VARCHAR(255),
author VARCHAR(255),
publisher VARCHAR(255))
</execute_sql>
/>
Use SQL to look at the newly created table:
<Example
my_db.<execute_sql> SHOW TABLES </>
result=<vector <thing Tables_in_test_db="book"/> />
/>
Use 'execute_sql' to insert two rows into the table:
<Example result=1>
my_db.<execute_sql> INSERT INTO book VALUES
("283223","Water","Plusch","Wiley")
</execute_sql>
my_db.<execute_sql> INSERT INTO book VALUES
("458328","Water Programming","Fry","Clear Methods")
</execute_sql>
</Example>
Perform a SQL SELECT query on the new table to retrieve the
data. Notice that the instances are generic things, and are
not of type 'book'.
<Example
my_db.<execute_sql> SELECT * FROM book </>
result=<vector>
<thing "283223" "Water" "Plusch" "Wiley"/>
<thing "458328" "Water Programming" "Fry" "Clear Methods"/>
</vector>
/>
If you have a Water Contract (defclass) for the corresponding
database table, you can specify that the returned instances
should be of that class. <ex execute_sql/> takes an argument
named 'class'.
<Example
<defclass book isbn title author publisher/>
/>
<Example
my_db.<execute_sql class=book> SELECT * FROM book </>
result=<thing
<book "283223" "Water" "Plusch" "Wiley"/>
<book "458328" "Water Programming" "Fry" "Clear Methods"/>
/>
/>
The following example shows how the first instance can be retrived
using a simple Water Path:
<Example
my_db.<execute_sql class=book> SELECT * FROM book WHERE isbn="283223" </>.0
result=<thing.book isbn=283223 title="Water"
author="Plusch" publisher="Wiley"
/>
/>
<ex a_connection/> can be explicitly created and passed into a database
in the <ex a_connection/> field.
<Example>
<set a_db=
<database "test_db"
a_connection=db_resource.<connection "jdbc:mysql://localhost/"
"com.mysql.jdbc.Driver"
username="" password=""
/>
/>
/>
</Example>
<Example
a_db.<execute_sql> SHOW TABLES </>.<length/>
result=1
/>
CONNECTING TO EXISTING DATA
A very common scenario is that data already exists in
a database, and Water is used to access and manipulate
that data.
If you have an existing database named "test_db" and
an existing table named "book", then the following will
create a Water Database object that represents the
relational database, and assign it to the <ex my_store/>
local variable. If the database already exists, use the
path to the database instead.
<Example
<repository "jdbc:mysql://localhost/"
protocol="com.mysql.jdbc.Driver"
username=""
password=""
/>
/>
<set my_store=repository.of."jdbc:mysql://localhost/".<database "primary_db"/>/>
Any SQL command can be called using <ex execute_sql/>:
<Example
my_store.<execute_sql> SELECT * FROM book </>
result=<vector>
<thing "283223" "Water" "Plusch" "Wiley"/>
<thing "458328" "Water Programming" "Fry" "Clear Methods"/>
</vector>
/>
A Water Contract 'defclass' can be created automatically from the
database table definitions using <ex derive_classes/>.
<Example
my_store.<derive_classes/>
/>
It is possible to create custom mappings of SQL datatypes
to Water types. <ex db_resource.map_sql_type_to_water/> and
<ex db_resource.map_water_type_to_sql/> are the mapping tables.
The use of these maps has yet to be documented.
The <ex defclass/> for book is now defined in <ex thing.book/>
and can be used as a class in <ex execute_sql/> to return
objects of the appropriate class.
<Example
my_store.<execute_sql class=book> SELECT * FROM book </>
result=<vector>
<book "283223" "Water" "Plusch" "Wiley"/>
<book "458328" "Water Programming" "Fry" "Clear Methods"/>
</vector>
/>Debugging tools are continually being improved. This describes the basic ones.
Expressions
If you get a syntax error, it is likely due to an incomplete expression.
Most of these are unbalanced angle brackets, double, or single quotes.
Double click on the beginning or end of what you think is a complete expression,
and the parser will be run on the expression, highlighting the complete expression.
Double click just before an open angle bracket or the first of a pair of quotes or
double click just after a close angle bracket or second of a pair of quotes.
If there is no complete expression, only the first character will be highlighted.
Execution
Select any source code in the editor and hit the Execute button.
If you get a syntax error, double click on nested expressions until you
find the problem.
Note that in selecting source to execute, if it is, say an expression in
the body of a defmethod and that expression contains parameters or local variables,
execution will error if those are unbound (which will usually be the case).
Make a call to the method supplying the proper arguments to test it.
If you have a lot of top level expressions in a file and you're not sure which one is
failing, use the Options menu to turn on the "Execute makes results vector" flag.
Then get rid of any selection and hit Execute. The entire buffer will be executed
and a vector of the result of each of the top level expressions will be returned.
Stepping
If execution fails, try stepping through an expression to see exactly which part
of it fails. Start by using the Step button instead of the Execute button.
Use the other buttons in the bottom of the IDE to control stepping.
Print Statements
Sometimes stepping is too slow as the problem is very deeply nested.
In such cases, print statements can come in handy.
Use the method "echo" to make print statements to the Java console.
Echo can take any number of arguments of any type. It will print all of them out
and return the value of the last one.
Inspect
If you want to be able to interactively inspect and navigate into fields of objects,
use the inspector.
There are four different ways to inspect objects.
First, from the development environment, use the tools menu to inspect various important
object in Water. "thing" is the root object. From it you can get to all classes
as well as documentation on classes and methods. Note that the item "Inspect Latest Result"
lets you inspect the value of the last expression you have executed. You can usually
do this by clicking on the upper right window, but if that fails, use the menu item.
Clicking on the lower right pane (where the HTML is rendered) will show you the
string of html source code in the inspector.
Second ii is an "active value" that you can stick in a path to see intermediate values
Example: thing.number.ii.integer
Third iip is a method that gives you the option of pausing execution at the point of the call
Example: thing.number.<iip p/>.integer
When the above is executed, after "number" is evaluated, the result is shown in
the inspector, then execution pauses until the developer clicks on the "Execute"
button in the development environment.
A particularly easy way to use iip is via the edit pane right click menu item
named "Inspect Breakpoint".
Fourth inspect is a method used to inspect an object where inspection is part of the normal
operation of the program.
Both ii and iip are meant to be temporary, debugging tools whereas inspect is
intended to be a permanent part of the program being developed.
By searching for the string "ii" you can easily find and remove all calls to ii and iip
from your source code.
Extended Example:
<defmethod foo a=1 b=2>
<bar 33/>
</>
<defmethod bar c=3 d=4>
_environment.ii
5
</>
<foo/>
When the above is executed, the call to foo, calls bar then
the local variable _environment is inspected. The value of _environment
is the current local environment containing all the local variables
which includes the arguments passed to the method.
The inspect window that comes up will show you the values of the variables
c, d, _subject and the name of the current method in the variable "_this_method".
Note that calling ii does not halt processing so the computation will
continue until its natural completion, perhaps modifying the values of
the local variables to new values after the lexical position of the call to
ii.
If you want to look at the entire stack of environments and stack variables,
call <error "some error message"/>
Type Checking
By declaring parameter types and return_types for methods and turning
type_checking on, you can catch bad arguments or returned values.
Example:
<defmethod foo a_num=required=integer return_type=string> true </>
<set_type_checking "error"/> This may also be done via the Steam window Options menu,
Type Checking submenu.
<foo 3.2/> errors because the parameter is declared to be of type integer but a float was passed in.
<foo 1/> errors because the method returned true, a boolean but was declared to return a string.
Note that changing the setting for Type Checking does not affect other causes of errors.
Development Strategy
Water and the development environment lends itself well to highly incremental development.
Write just a line or two before verifying that it works. Do lots of little
test cases to methods. Using the method "test" to make formal test cases
will help out. Select an expression, click right and choose <test /> to
wrap a call to test around your expression.
Using the Tools menu item Execute Next Expression (or typing Alt+N) lets
you very easily execute successive expressions. This is especially useful for
quickly executing a bunch of calls to "test" and seeing which ones fail.
See also: stepping, set_type_checking, get_type_checking, echo, error, iip, inspect, try<defclass _id="defclass"='ek_expression' rest="all"='ek_expression' other_named_args=true='ek_code' />
When you want to make a new object you can just create one at random a la
<thing />
But if you want it to act like a "class" and link it into the type hierarchy, i.e.
have its parent contain a field with the name of the new object and a value of the new object,
then it is easier to say
par.<defclass kid color="red" />
In this case, the value of par.kid will be your new kid object created by the call to defclass.
All expressions in the content of a defclass get executed during the defclass call
with "_new_object" bound to the new object.
It is common to use "_new_object" to initialize stuff within the new object.
The value returned from defclass will be the new object being defined,
which is not necessarily the value of the last expression in the body of a defclass call.
The syntax and functionality of the arguments you pass to defclass to define each field
is very similar to the parameters of a method. Read the documentation about defmethod
for a complete description.
See also: thing.init "subject and new_object", cache_instance,
inherit_field_order, defmethod.<defmethod _method_name=null='ek_expression' rest="all"='ek_expression' other_named_args=true='ek_expression' />
A call to defmethod creates a new method, binds it to a field in the _subject,
and returns the new method object.
The first argument is the name of the method. It becomes a field key in
_subject whose value is the new method object. The rest of the attributes name parameters
to the new method. The content of the call to defmethod contains the code that describes
the behavior of the method.
The name parameter:
<defmethod foo /> will create a method with a name of foo. The new method will be
the value of a field named "foo" in the subject of this call which at top level will be thing.
You may create a method in an object, say the string object with:
thing.string.<defmethod foo />
You can make an "anonymous" method if you really don't care about naming the method.
Example: <defmethod> 123</>
This call to defmethod returns a method that, when called, returns the number 123.
If you want to use this method you must save it away in some variable or
use it immediately in a call such as: <<defmethod> 123</>/> returns 123.
Parameter Names
<defmethod foo p1 /> designates a parameter named "p1" which is required,
can be of any type, and is of execution kind "ek_code".
Parameter Default Values
<defmethod foo p1=78 /> designates that p1 is optional and that its default
value is 78. The default value is given as code that is executed when the
method is called without the specified argument. The code is executed in the
environment of the method definition. It may not contain references to other
parameters of the same method call.
You may also use required or null to indicate required and optional explicitly.
Example:
<defmethod foo arg1=junk />
junk is an expression indicating a default value.
If your call does not pass that arg, i.e. <foo/>, then the default expression, in this case
"junk" will be executed in the outer lexical environment of each call to <foo/>.
Parameter Types
To indicate a type to a parameter you must specify a default value like so:
<defmethod foo p1=78=integer />
This indicates that the value passed in for this parameter must be an integer.
As of April 2001, the parameter type is for documentation only. No actual checking
is done to verify that passed in arguments conform to the specified type.
Parameter Execution Kind
How the argument is processed at the time of the method call is determined by
the execution kind of the parameter.
There are four execution kinds:
- "ek_code" (the default) The source code of the argument is read and executed
before being passed to the method.
-"ek_expression" The source code of the argument is read but not executed
before being passed to the method. An expression such as
a variable, a path, a call, a number, a string, or a boolean will
be passed.
-"ek_string" The source code is not read or executed but is just passed in as a string.
When using "ek_string" for an execution kind, be aware that for
an "attribute" arg i.e. any arg that is not the content arg,
when passing in a value, the actual source code string for the
arg must be a valid Water expression. For example, in calling the method
<defmethod foo arg=required="ek_string"> </>
you can not pass in an arg that contains a single quote
because the single-quote is an invalid char. You can however have:
<defmethod foo content=required="ek_string"> </> <foo> don't</>
-"ek_hypertext" A vector is created of strings and other objects.
All the text before the first open angle bracket will become the
first element of the vector. It is not read or executed.
The source from the first open angle to its closing angle will be read and executed.
The result will become the next element of the vector.
Each successive string or call will be treated as a string or code to be executed.
Example:
<defmethod foo p1=78=integer="ek_code" p2=79="ek_string">
1.<plus p1/>
</defmethod>
Rest is a special arg that, if a defmethod id defined to take it, collects all the
args after the last defined named parameter into one vector.
Example:
2.<plus 3 4/> returns 9
If a rest arg is allowed we can also pass it in as a vector by naming
the arg in the call like so:
Example:
2.<plus rest=<vector 3 4/> /> returns 9
And we can combine both techniques.
Example:
2.<plus rest=<vector 3 4/> 5 6/> returns 20
To define a method that takes "rest" arguments, just make one of its
arguments "rest".
<defmethod foo weight rest>
rest.1
</>
<foo 32 42 52 62/> returns 52 because while executing the code of foo, the
local variable "rest" is bound to an object that has fields of:
0=42, 1=52, 2=62. So rest.1 returns 52.
Note that 32 is bound to "weight".
When there are both required parameters and rest, the position-passed arguments map to
the required arguments. If there are any additional position-passed arguments,
then they will be put in the "rest" object.
Methods that take optional arguments as well as rest arguments will bind
the non-required position-passed arguments to rest, not to the optional args.
To pass an optional arg to a method that takes rest, you must pass it by keyword.
Example:
<defmethod foo weight height=22 width=33 rest>
<vector weight height width rest.0 rest.1/>
</defmethod>
<foo 100 200 300 400 500 600/> returns <vector 100 22 33 200 300/>
because height and width use their default values whereas
<foo 100 height=200 width=300 400 500 600/> returns <vector 100 200 300 400 500/>
Content is a special arg that's passed in the body of an element.
Example:
<thing> 3 5 7</> gives thing a field named "content" with a value of a vector
of items 3 5 and 7.
We can do the same thing via:
<thing content=<vector 3 5 7/>/>
To access the 2nd item of the vector that's the value of content:
<thing content=<vector 3 5 7/>/>.content.1 returns 5
Defclass is very similar to defmethod with the treatment of its parameters.
It has required, optional, rest, pass by keyword, default values, types and
execution kinds.
Return Type
You can declare the return type of a method with a special "parameter" named "return_type".
Example:
<defmethod foo a_num=required=integer return_type=string> true </>
<set_type_checking "error"/>
<foo 2.3/> errors because the parameter expected an integer but was passed a float
<foo 1/> errors because the returned value was 'true', a boolean but was declared to
be a string.
Execution of a Call:
Take the call 1.<plus 2/> for example:
1 is the subject.
plus is the method name
2 is the argument.
1 is executed and returns 1 (numbers are self-evaluating).
plus is looked up in 1. 1 has no fields so we look up plus in the parent of 1,
which is integer. Integer may not have a plus field so we look in its parent,
number. Number has a plus field so we get its value, the plus method.
You can see this by executing 1.plus, often useful in debugging.
2 is executed and returns 2.
Since the value of plus is a method, we now call the method.
(If plus were not a method, we would make an instance of it.
See the doc on defclass.)
In calling, first local variables are made of each parameter of the method.
In this case, plus has only one parameter, but it is "rest" which means it will
be bound to a vector of the arguments passed to plus. We also bind the local variable
'_subject' to the subject of the call, in this case 1.
With all of our parameters and '_subject' bound to the values passed in, we now execute the
'implementation of 'plus'. If there are any local variable references,
they execute to the values that have been passed in.
In this case, _subject will execute to 1 and
rest.0 will execute to 2.
The last expression executed in the method implementation has its value returned.
You can explicitly call 'return' to make an early return,
but usually that's not necessary.
See also: "subject and new_object", optional, defclass, return, debugging,defmethod.<copy include=return_true=defmethod limit=optional include_limit=true other_named_args=true />
Creates (and returns) a new method that is the same as the '_subject' method, but with either new arguments, new default values, and/or a new implementation. The new implementation should be put in the content of call to copy. New or changed arguments should be passed as attributes in the call to copy. This only works for default values. It does not yet support types and execution_kinds for a parameter. Similar to: <foo.<copy/>.<set bar=20/> /> Also known as 'currying'. After copy has copied the fields to copy, if a field of other_named_args exists in the original, it is copied into the new copy. Thus you may not add a field to the copy named "other_named_args" if that field is not in the original. <defmethod foo bar=10> "hello".<concat bar/> </> <test <foo/> "hello10"/> <test <foo.<copy bar=20 baz="aaa"/>/> "hello20"/> <test <foo.<copy> "bye" </> /> "bye"/> <test <foo/> "hello10"/> <defmethod foo bar=10> "hello".<concat bar/> </defmethod>. <copy bar=20/> Will give same result as: <defmethod foo_copy bar=20> "hello".<concat bar/> </defmethod> <defmethod foo bar=10 other_named_args=true> "hello".<concat bar/> </defmethod>. <copy bar=20/> Will give same result as: <defmethod foo_copy bar=20 other_named_args=true> "hello".<concat bar/> </defmethod>
Removes the email of the given index from host of user.
An index of 0 (the default) removes the oldest email.
An index of 'latest' means remove the newest one.
If their are email messages in '_subject', then we will removed
the email message with the highest number on '_subject', which is
not necessarily the highest one on the server since email may have
come in to the server since we last retrieved messages.
An index of 'all' removes all the email for user.
If there are email messages in '_subject' then just remove all of those,
which are not necessissarily all those on the server as more may have
come in since we retrieved messages.
'where' tells where messages will be deleted from, client, server, or both.
client means just the email messages in '_subject'.
server means leave '_subject' alone and just delete messages on the server.
both means delete the messages in both. 'both' will always remove the
same numbered message (or messages, if index="all") from both client
and server. Thus if there are 3 messages on the client, then only nessages
0, 1 and 2 from the server will be deleted.
It is recommended that either you delete mail from the server using
<get_email index='all' delete=true/> and use
<delete_email index=0 where="client"/> or use
only the server via
<get_email index=0 delete=false/>
<delete_email index=0 where="server"/>
or, living dangerously,
<get_email index=0 delete=true/>
or,
<get_email index="all" delete=false/>
<delete_email index=0 where="both"/>
Returns true if successful, false otherwise.To do: show example of environment setup in startup.sh
showing correct system folder when using a .jar file
A Steam Engine may be deployed in a Servlet Engine as a Java Servlet.
You can configure a Servlet Engine (for example, Apache Tomcat)
to route requests to a Steam Engine which routes requests to
the appropriate Water Server. The Water Server executes
the request and returns the result.
A Water Server can directly listen for a connection on a port,
or Apache can be configured to listen and route requests to
a Water Server.
For a standard Apache:
TOMCAT_HOME/conf/server.xml
TOMCAT_HOME/conf/web.xml
<Example name="server.xml configuration file">
<Server port="8005" shutdown="SHUTDOWN" debug="0">
<Service name="Tomcat-Standalone">
<Connector className="org.apache.catalina.connector.http.HttpConnector"
port="8080" minProcessors="5" maxProcessors="75"
enableLookups="true" redirectPort="8443"
acceptCount="10" debug="0" connectionTimeout="60000"
/>
<Engine name="Standalone" defaultHost="localhost" debug="0">
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="catalina_log." suffix=".txt"
timestamp="true" />
<Realm className="org.apache.catalina.realm.MemoryRealm"/>
<Host name="localhost" debug="0" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="localhost_access_log." suffix=".txt"
pattern="common"/>
<Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" prefix="localhost_log." suffix=".txt"
timestamp="true"/>
</Host>
</Engine>
</Service>
</Server>
</Example>
<Example name="web.xml configuration file">
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>Clear Methods Steam Engine</servlet-name>
<servlet-class>org.waterlang.SteamEngineServlet</servlet-class>
<init-param>
<param-name>execute_water_source</param-name>
<param-value>(server root_object=thing port=8080 host_name='localhost' listen_on_port=false/)</param-value>
</init-param>
<init-param>
<param-name>starting_uri</param-name>
<param-value>logical://user/</param-value>
</init-param>
<init-param>
<param-name>license_key</param-name>
<param-value>930583372304105</param-value>
</init-param>
<init-param>
<param-name>system_folder</param-name>
<param-value>file:///D:/jakarta-tomcat-4.1.18_test/common/classes/</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>invoker</servlet-name>
<servlet-class>org.apache.catalina.servlets.InvokerServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Clear Methods Steam Engine</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<session-config> <session-timeout>30</session-timeout></session-config>
</web-app>
</Example>Running Water: Deploying a Pure Water Program
If you have a Water program that is running in your IDE, and you want to deploy
it, this document will describe how to do it.
The deployment of a Water program is actually quite simple and
can be done without any Wizards or GUI tools.
==========================
Step 1: Prepare your Water program
Your program should be stored in an .h2o file that is the name of your
program. For this example, we will assume your program is stored in a
file named "my_app.h2o". The content of the file is Water source that
creates Water objects. If your program consists of multiple files,
your main program file, my_app.h2o, needs to load those files.
Your application should have been tested through a standard Web browser.
Executing your my_app.h2o file will define your program objects, and
then creating a Water server for your application would look like:
<server root_object=my_app/>
To prepare your Water program for deployment, you should not
create any Water servers in your program files. Comment out any
Water expressions in your program that create servers.
The last expression of your main program file (my_app.h2o) should return
the root_object that will be served.
For a simple "Hello World" application the contents of the file would be:
--------------------------
"Hello World"
--------------------------
==========================
Step 2: Choose a computer
The computer for deploying your Water program will need to be accessible
to the users of the program through a standard HTTP port. For this example,
we will assume that the address "www.my_server.com" will point to your
"server box".
==========================
Step 3: Store your Water program
Your Water program will usually be stored in one or more .h2o files.
You need to upload this file (via FTP or other means) to a folder on
your server box. This file should not be accessible to end users -- only
to people who are releasing or managing your systems.
Let's say that you saved your program file on the server box at:
C:/water_apps/my_app.h2o
==========================
Step 4: Create a JNLP file
The JNLP file is used by Java Web Start to start a Java program. The
JNLP file will contain the information to load the Steam Engine, load
your Water program, and create one or more Water servers.
Create and store a JNLP file at some location that is only accessible
to system administrators of the machine. By convention, the JNLP file
will be either in the folder containing the Water program files or in
a folder parallel to it.
The example below is the entire contents of a default JNLP file.
Any value between the double-hash marks (##) needs to be changed for
your application.
Contents of my_app.jnlp:
------------------------
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="##file:///C:/apps##" href="##my_app.jnlp##">
<information>
<title>My App</title>
<vendor>My Company</vendor>
</information>
<security> <all-permissions/> </security>
<resources>
<j2se version="1.4"/>
<jar href="http://www.waterlanguage.org/product/steam_engine.jar" main="true"/>
<jar href="http://www.waterlanguage.org/product/steam_ide.jar"/>
<extension name="regex" href="http://www.waterlanguage.org/product/regex.jnlp" download="lazy"/>
</resources>
<application-desc main-class="org.waterlang.Start">
<argument>
execute_water_source="
(server root_object='##file:///C:/apps/my_app.h2o##'.(execute_file/)
port=8080/)
"
starting_uri="logical://user/"
license_key="##0583372304105##"
system_folder="webstart"
</argument>
</application-desc>
</jnlp>
------------------------
The following files should now be on your server box.
C:/water_apps/my_app.h2o
C:/water_apps/my_app.jnlp
The typical JNLP file will load the main program file and start a
single Water server on a particular port. The Water code for this
action is the value of the "execute_water_source" attribute above.
It can contain any Water source, but any angle-brackets
need to be replaced by parentheses. Also, only single-quotes are
allowed in the source -- no double-quotes.
The default Water expression in the above JNLP file creates a server
with a root object. The root object is returned from executing
your main Water program file.
==========================
Step 5: Start the Water Server
Double-click on the "C:/water_apps/my_app.jnlp" file to load your application
and create a server for it.
To start your program from the command line, call "javaws" with the URI to
your JNLP file:
"C:/Program Files/Java Web Start/javaws" "file:///C:/water_apps/my_app.jnlp"
You might want to configure your server to automatically start your Water
program.
==========================
Step 6: Test the Water program
Once your Water program successfully loads, you can hit the server
with a Web browser at: http://localhost:8080/
...or use the name of your server:
http://www.my_server.com:8080/Derives a class from example instance data.
The 'parent_class' argument is an existing class
object or the string name of a new class to create.
<Example
<data> <person first="Mike" age=28/> </data>.
<derive_class parent_class="HQ"/>
<!-- RETURNS: -->
<defclass HQ>
<defclass person first=required=string
age=required=integer
/>
</defclass>
/>
The instance data can represent multiple classes. Each new
class will be a subclass of the parent_class. The example
below shows how the 'person' and 'address' classes were
created under the parent_class named 'HQ2'.
<Example
<data>
<person name="Mike" mail=<address street="33 Park"/> />
</data>.<derive_class parent_class=<defclass HQ2/> />
<!-- RETURNS: -->
<defclass HQ>
<defclass person first=required=string
mail=required=address
/>
<defclass address street=required=string/>
</defclass>
/>
The data is assumed to be "normalized"
ConciseXML data. See 'normalize' for how to
automatically convert XML 1.0 data to ConciseXML
data.
See also: normalize, data<do repeat=optional=number.integer rest="unnamed"='ek_expression' />
'do' executes all its arguments (it has rest arguments) and all the expressions in the content,
and returns the value of the last one.
Examples:
<do 2 3 4/> returns 4
<do 2> 3 4 </do> returns 4
If there is a call to 'while' and/or 'until' in the content of a do call, then do will loop.
Here's the order of execution.
First each rest argument is executed in order. You may not have a call to 'while'
in the rest arguments. The rest arguments are executed only once, at the beginning of the call.
Next each expression in the content is executed.
If a call to while is encountered, then 'do' will loop through its content until
a first argument in a call to while returns false. When that happens the
content of the while call is executed once. The value of the last expression in the while content
is returned from the 'do'.
'until' is very much like 'while' except that it "hits" when its first argument executes to 'true'.
'while' hits when its first argument executes to 'false'.
The content of a 'do' call may have any number of calls to 'while' at top level within the content.
A call to 'while' may be at the top of the loop, at the bottom of the loop, in the middle,
or all three places if you like.
The first one whose first argument executes to false will be the one that halts looping
and has its content executed to make the value to return from this call to 'do'.
If there is no content, then the value of the last rest argument is returned.
If there are no expressions in do, then null is returned.
Example:
<do <echo "one"/> <set count=0/> >
<echo "two"/>
<while count.<less 2/> > <echo "in while" count/> </while>
<set count=count.<plus 1/> />
<echo "three"/>
</do>
This call prints out 7 lines: "one", "two", "three", "two", "three", "two", "in while 2",
then returns 2.
Here's the execution flow:
First the call <echo "one"/> is executed, then the call <set count=0/> .
We then enter the content and execute <echo "two"/> .
Next the call to while is encountered.
The expression count.<less 2/> is executed. Since 'count' is 0, it returns true
and execution proceeds to <set count=count.<plus 1/> /> and <echo "three"/> .
We are now at the bottom of the do content but since we encountered a call to 'while',
we continue by executing the first expression in the content, <echo "two"/> .
Next the condition of while returns true again since 'count' is 1.
We proceed on to executing <set count=count.<plus 1/> /> and <echo "three"/>
then back to the top of the content.
After executing <echo "two"/>, the call to count.<less 2/> returns false since
count is now 2. Now the content of the call to while is executed.
Here it is just a single expression (but could be many) of <echo "in while" count/> .
After printing to the console, echo returns the value of its last argument, count,
which is 2. That 2 is returned from the entire call to 'do'.
In addition to while and until calls in the content, 'do' may have a 'repeat' attribute.
The value is the number of times to execute the content.
Example:
<do repeat=3 "hi".<print/>> "hello".<print/> </do>
This call to do prints out to the console:
hi
hello
hello
hello
and returns the value of the last call to print which is "hello".
When do has a content, it maintains the number of the iteration in a local variable
whose name is 'counter'.
Example:
<do repeat=3> counter.<print/> </>
print to the console:
0
1
2
and returns the value of the last expression which is 2.
The counter variable is maintained whether you use repeat, while, until or any combination
of those including none.
Example:
<do> counter </> returns 0.
The counter is not available in the rest args, i.e. <do counter/> will error because
counter is not in the content and therefore not bound.
If you use both repeat and while and/or until, whichever one would stop the looping first
does stop the looping. Thus you might have tricky logic using 'while' but just to make sure
you don't write an infinite loop, you may set 'repeat' to a number higher than you
ever expect to go say, 1000, just to be sure to stop runaway code.
If repeat is set to null, then it will not stop a while or until loop. However,
if no while or until is used in the content, then the content will be executed just once.
If repeat is set to 0 then the content will never be executed, but, as usual
the 'rest' args to 'do' will be executed and the value of the last will be returned.
<do> <while true/> </> and <do repeat=null> <while true/> </> have the
same behavior, i.e. they loop infinetly.
If an error is encountered while executing the expressions in the content of a do
then a call to 'if_error' is looked for in the top level of the content of the do,
below the expression that errored. If such a call to 'if_error' is encountered,
then the expressions in the content of the call to 'if_error' are executed.
Example:
<do> <error "errors happen"/> <if_error> 992.<plus 1/> </if_error> </do> returns 993.
In the content of the if_error call, you may reference the local variable 'error_object'.
It is bound to the string of the error message.
If the last cause in the content of a call to do is a call to 'finally', then the
expressions in the content of the call to finally are always executed exactly once
and they are the last expressions executed in the call to 'do'.
Example:
<do repeat=3> <print counter/> <finally> <print "done"/> </finally> </do>
The numbers 0, 1 and 2 are printed, then "done" is printed.
There can be at most one call to finally in a call to 'do' and it must be
the last expression in the content.
Returned Value
In general 'do' returns the value of the last expression it executes.
This means that:
- If there is no content, the value of the last rest arg is returned.
- If there is a content and there are no errors, no while, until or finally calls,
then the value of the last expression in the content is returned.
- If there is a while, until or if_error call that is executed and no finally, the
value of the last expression in the content of the executed while, until or if_error
is returned.
- If there is a finally call, then the value of the last expression in the content of the finally
is returned except:
If the last expression executed before the finally happens to be a return
that returns from the 'do' or above, then the finally expressions will be executed
for side effect only, and the return will be processed as it normally is.
Examples:
<do 2 3> 4 <while counter.<less 3/>> 5 </while> <finally> 6 </finally> </do> returns 6
<do 2 3> 4 <error/> <if_error> 5 </if_error> <finally> 6 </finally> </do> returns 6
<do 2 3> 4 <while counter.<less 3/>> <return 5 "do"/> </while> <finally> <print "done"/> </finally> </do>
returns 5 but still prints "done".
<doc
name=optional='ek_string' fields=optional precond=optional=
Water supports the ability to add documentation to any object. The following code first creates documentation for book and then defines the book class. <Example> <doc book> This is the documentation for book. </doc> <defclass book isbn title/> </> In the IDE, to retrieve the documentation for an object, just double-click on the name of the object in the editor to show its contract in the HTML viewer. Click on the link to open the documentation window. The documentation is stored in the 'doc' meta-field. The following example shows how to programmatically get the doc string for book: thing.<get <field_key "book" "doc"/> /> In some cases, the documentation for an object might exist in another file. For that case, the documentation will likely be loaded after the object is defined. <Example> <defclass book isbn title/> book.<doc> This is another way to add doc for book. </doc> </> You can add documentation to any subclass or individual methods. <Example integer.number.<doc plus> This is documentation for 'plus' </doc> /> Examples can be included in the documentation. <Example book.<doc> Examples can be included in the documentation. <Example 1.<plus 1/> result=2 /> </doc> />
<doc_field key=required='ek_string' />
Set the documentation string for the field named in the first argument to
the string in the content.
Example: thing.boat.<doc_field rudder> The steering mechanism</doc_field>
thing.boat.rudder_f_doc returns " The steering mechanism"<duration years=0 months=0 days=0 hours=0 minutes=0 seconds=0 milliseconds=0 />
A duration is a time interval. You create one by passing in any number of
years, months, days, hours, minutes seconds, milliseconds.
These values are all added up to create the duration.
Note that the values passed in need not conform to their normal range restrictions.
For example you can create a duration of 45 days, or
14 months and 92 minutes.
Some care in using durations must be exercised. A year is considered to have 365.25 days
to account for leap year. The days per month is considered to be 365.25 divided by 12.
Durations are kept as a millisecond resolution but the above considerations may make only
the higher level values meaningful to your application.
When you are getting values out of a duration you may use
singular nouns: year, month, day, hour, minute, second, millisecond
to get the "limited" version [ie month will always be between 1 and 12 inclusive]
or the plural form: years, months, days, hours, minutes, seconds, milliseconds
to get the full duration in terms of those units.
Examples:
<duration months=18/>.year returns 1
<duration months=18/>.month returns 6
<duration months=18/>.years returns 1.5
Durations have comparators: equal, less, more less_or_equal, more_or_equal
and arithimetic: plus, minus, times, divide.
See also 'datetime' for datetime.<plus duration/> and datetime.<minus duration/><echo rest=required />
Takes any number of arguments. Prints out their values and returns the value of the last one. echo is intended to be for debugging print statements. use 'print' or 'status' for permanent parts of code, then you can easily search for calls to 'echo' and remove them once your code works.
returns true if string ends with a_string, otherwise returns false. If case_sensitive is false, the case of the strings doesn't matter.
<equal an_object=required case_sensitive=false=boolean whitespace_sensitive=false=boolean />
This is a "deep" comparison of "_subject" and the first argument. Two objects that are the same or whose field values are equal are equal. Pass in case_sensitive and/or whitespace_sensitive of true to have especially liberal comparison of strings. whtespace_sensitive=false (the default) means that all whitespace in the strings are ignored for the purposes of the comparison. Returns true if "_subject" and an_object are equal, false otherwise. Since this method can walk large object trees, it may be expensive. equal is careful to handle circular data structures without infinite recursion. Two objects which are the same in all ways except that they each point to themselves from the same field are "equal" but they are not "same". See also "same".
<error message="an error occurred"=string />
Prints its string argument in the Java console and stops all processing.
See also "try".
Example:
<try <echo "did it"/> <echo "did it2 "/> <error "hey"/> <echo "did it3"/> >
<echo "caught it"/>
</>
When this call to try is executed,
1. "did it" is printed on the console,
2. "did it2" is printed on the console
3. "hey" is printed on the console
4. "did it3" is NOT printed because that call to echo is never executed.
5. The expressions in the content of the TRY call are executed.
In this case there's only one, so
"caught it" is printed on the console.
6. The value of the last expression in the content of TRY is returned,
in this case the string "caught it".
See also: warning<execute env_or_context=null execution_kind="ek_code" returns="last" />
If _subject is a string, read the string and evaluate the resulting expression.
This is similar to execute_string.
If _subject is a file, read each expression in the file and evaluate it,
returning the result of the evaluation of the last expression.
This is similar to execute_file
If _subject is anything else, send the object, usually an expression to
the evaluator. This is similar to execute_expr.
env_or_context is the environment to evaluate the expression in.
An env is just an object that contains the binding of local variables.
Examples:
"2.<plus 3/>".<execute/> returns 5
"2.<plus aa/>".<execute <thing aa=7/>/> returns 9
Execute can also take Water expressions to execute as the content argument:
<execute> 2.<plus 3/> </> returns 5
Execute takes an executing_kind argument. This defaults to "ek_code"
"ek_code" Treat the _subject or content as an expression and execute it.
"ek_expression" Just returns the subject or the expression(s) in the content
"ek_data" Converts the _subject or content into "data".
"ek_string" If there's a content, just return that string.
else if there's no content, error.
See also: execute_string, execute_expr<execute_expr env_or_context=null execution_kind="ek_code" returns="last" />
Takes an expression as "_subject", executes it and returns the result.
Examples:
<expr>foo</>.<execute_expr/>
a_vec.<for_each> value.<execute_expr/></> executes each expr in a_vec
and returns the last one.
The env_or_context parameter is documented in execute_string.
See also: execute_string<execute_path rest=optional='ek_expression' />
Has the same functionality as a normal path using dot notation,
but calls to execute_path are XML 1.0 friendly because the path parts
are in the content (or attributes), and execute_path does not
use dots between path parts.
Example: <execute_path> thing number integer </>
returns thing.number.integer<execute_string env_or_context=null execution_kind="ek_code" returns="last" file="No file" offset=0 />
Each expression described in the string is executed in order.
Example: "2.<plus 3/>".<execute_string/> returns 5
If returns is "last", the default, only the value of the last expression is returned.
If returns is "all", then a vector of the values of all the top level expressions is returned.
"env_or_context" is shared for the execution of all the source so you can
set a local variable in one form then use it later in the source.
Typical values for env_or_context are:
null use the default environment
_environment use the environment of the call to execute_string.
<environment_of_call/>
Example:
<defmethod foo w>
<set x=5/>
"w.<plus x/>".<execute_string _environment/>
</defmethod>
<foo 7/> returns 12
The execution_kind argument determines how a string is to be executed.
"ek_code" (the default) the source for an argument is evaluated as code.
"ek_string" the source is not evaluated, nor parsed, it is just used as is, as a string
"ek_expression" the source is parsed and a parsed representation of the source is returns.
This will be one of the following kinds of objects:
string, number, boolean, null, character, ie the literals, and expr_call, expr_path.
"ek_data" the source is parsed and a very limited kind of evaluation is performed.
The types of objects returned will be:
string, number, boolean, null, character, i.e. the literals, and "data objects"
and data_paths.
No lookup of variables occurs and no calls are executed. However, literals
are created. Variables are turned into "symbols", i.e. objects that have
as their parent thing.symbol and have a name field of the string of the variable.
Calls are turned into water objects with a parent of a symbol of the call name
and fields corresponding to each field in the input whose values have
been executed with an execution kind of ek_data. This are "data objects".
Example: "<foo 2 color='red'/>".<execute_string execution_kind="ek_data"/>
returns an object whose parent is a symbol with name="foo" and
has two fields: 0=2 and color="red".
There are three special rules for calls.
1. If the name of the call is "char" then the appropriate character is created.
2. If the name of the call is "vector" then a vector is created with
vector fields of values that are the ek_data-executed results of their sources.
Example: "<vector foo bar 4/>".<execute_string execution_kind="ek_data"/> returns
an object <vector <symbol "foo"/> <symbol "bar"/> 4/>
3. If the name of the call is "thing", then an instance of thing is created.
For all other calls, the parent of the returned object is an instance of symbol
having a name of the symbol in the call.
Paths are turned into water object with a parent of thing.data_path
and vector fields of values of the ek_data executed results.
Example: "foo.bar.4".<execute_string execution_kind="ek_data"/> returns
and object <data_path 0=<symbol "foo"/> 1=<symbol bar/> 2=4/>
See also: execute_expr, execute_file<expr returns="first" />
In normal processing, Water takes a string of source code, parses the string
into a expression objects, then executes each expression to create
resulting value objects. Lisp has the notion of expressions and uses
a "reader" to create them before passing them to an evaluator.
Many other languages such as C, Java, and Javascript don't have the
concept of expressions.
In Water, rarely do you deal with expressions directly. They are an intermediate
data format that is created temporarily during the process of executing a string.
However, Water enables you to create expressions, pass them around, and eventually
execute them, perhaps multiple times.
Certain key primitive expressions are created by the Water parser and are
"self executing", that is, executing these expressions just returns the expression
themselves. These are: integers, floats, booleans, characters, strings and null.
Non self_executing expressions are: variables, calls, and paths.
Other data such as vectors and "records", regular objects are usually not
passed to the evaluator, but if they are, they are just returned as is, i.e.
they are "self executing".
Examples:
<expr>34</expr> returns 34
<expr>"some text"</> returns "some text"
<expr>foo</> returns a variable with the name "foo"
<expr>3.<plus 4/></> returns a path of two parts, the integer 3 and a call
expression to the method "plus".
If you have a string in a variable or some other code that, when executed,
results in a string and you want to parse that string into a variable use []
Examples:
<set foo="3.<plus 4/>"/>
<expr>[foo]</> returns a path of two parts, a 3 and a call to plus.
<expr><force_ek_code "foo".<concat "bar"/>/></> returns a variable expression of name "foobar".
A given string might contain the source for one or more expressions.
expr takes a parameter to tell it whether to return the first expression
in the string or a vector of all the expressions in the string.
returning the first expression is the default.
Examples:
<expr>23 45 67</> returns 23
<expr returns="first">23 45 67</> returns 23
<expr returns="all">23 45 67</> returns a vector of the three integers.<expr_to_uri_fields env=null />
path (or one thing)
for every thing in the path
convert the part
if literal path part
add literal to path
if field var
add name to path
if call path part,
if part is a get call, evaluate the arg source in local environment
and add to path
returns integer or string, otherwise error.
else
add name to path
execute each arg_source
add args to query or post-path to append.
else errorBackground
Objects are made up of fields.
Each field has a key and a value.
The key and the value may be any object though
usually the key is a string or an integer.
Meta_fields
Water has special machinery to attach "meta data" to
fields by creating "meta fields".
These meta fields are meant to hold data about a field,
which is not necessarily about the VALUE of the field but
has more to do about what kind of information may be in
the field. the Water system has meta fields for "type"
and "doc" to help users and sytem software know about potential
values for fields. Developers may add their own meta fields
using names appropriate to the domain of their application.
Meta fields must be named by a string.
Syntax
Meta fields are actually just regular fields that have
a key that is a string composed of the key of the field,
the string "_f_" and the meta key itself.
Example: "weight_f_type".
You can create meta fields in a number of ways.
The most common is when defining a method's parameter that
has a type:
vehicle.<defmethod drive speed=65=integer> </defmethod>
makes a meta field in vehicle of speed_f_type
whose value is integer.
vehicle.drive.speed_f_type returns integer.
You can also directly set a meta field via:
thing.<set foo_f_bar=23/>
thing.foo_f_bar returns 23
You can avoid knowing the details of the metafield infix "_f_"
by using the method field_key to make the key:
<field_key "foo" "bar"/> returns "foo_f_bar"
thing.<set_value <field_key "foo" "bar"/> 23/>
thing.<get <field_key "foo" "bar"/>/> returns 23
Restrictions
The meta_key itself, ie "type" must be a string and cannot
start with underscore.
You also can't have a meta_key of "key", "value", or "container".
Field Objects
Most of the time the above knowledge is all you'll need to know
about meta fields. But for more advanced work, you may find it
convenient to think about a field as an actual object
with keys of the meta-keys of the field.
In order to make a field object, use the "field" class to
make a field instance. Each field object must have a key
and may have either a container or some other meta-key fields.
Field Objects with a Container
Examples:
thing.<set weight=48=integer/>
thing.weight returns 48
thing.weight_f_type returns integer
<set my_field=<field "weight" container=thing/>/>
my_field.type returns integer
my_field.value returns 48 (Note: "value" is the default meta_key.
It stands for the regular field value.)
my_field.<set doc="how heavy it is"/>
my_field.doc returns "how heavy it is"
thing.weight_f_doc returns "how heavy it is"
When a field object has a container, it becomes a "proxy" for the
field within its containing object.
A field object with a container specifies a location as an object
and the key within the object. This can be used to get, set and test
if the field exists within the object.
Field Objects without a Container
A field object without a container can be used to "build up" a field
with all its meta-fields and their values. Then, using the
method "install_field", the field can be stuck into an object.
Once this is done, the field object cannot be used to
refer to the values in the installed field, though it can be used
to install a similar field in another object.
Examples:
<set your_field=<field key="material" value="steel" price=89 density=21/>/>
your_field.<install_field thing/>
thing.material returns "steel"
thing.material_f_price returns 89
thing.<get <field_key "material" "density"/>/> returns 21
<set stuff=<thing/>/>
your_field.<install_field stuff/>
stuff.material returns "steel"
thing.<set "material"="wood"/>
thing.material returns "wood"
stuff.material returns "steel"
Despite the fact that both thing.material and stuff.material were
originally created using the same field object, they share no
memory in common.
Implementation
Field objects have special definitions for the methods:
has, get, set_value, and set to achieve their behavior.
See also: field_key, install_field<field_key key=required a_meta_key="value" />
Given a field key and a meta_key, makes up a string that lets you access that meta_key of the field. Example: <field_key "weight" "type"/> returns "weight_f_type". The "meta_key" for the main value of a field is "value". "value" is the default value for the meta_key paramter. <field_key "weight" "value"/> returns "weight" <field_key "weight"/> returns "weight" If key is a string (the usual case) or if meta_key is not "value" (also usual), field_key returns a string, even if either or both of its arguments are not strings. Before building the return value, field_key calls to_concise_xml on both of its arguments and uses the results.
Creates a file resource from a path. <Example> <file "C:/temp/foo.txt"/> <file> C:/temp/<do "foo.txt"/> </> </> To retrieve the content of a file: <Example a_file.content /> To set the content of a file: <Example a_file.<set content="some text"/> />
<filesystem
a_uri=required=
No actual instances of local are created.
If you attempt to create one, it will be converted to a
file or folder resource depending on the uri used.
See: file and folderfilesystem.<exists />
Returns true if the file or folder in '_subject' actually exists
on disk, otherwise returns false.filesystem.<file.append rest=required />
Extends the content of the file with the rest args.
If an arg is not already a string, it is conveted to one
using to_concise_xml before it is written to the file.
returns _subject.filesystem.<file.copy_file new_file=null=filesystem.file />
Takes the original file as '_subject' and one argument,
the new file as a file object.
The new file might or might not actually exist on disk.
If it does, it's content is overwritten with the content
of '_subject', otherwise a new file is created and
its content will be the same as the content of '_subject'.
The new file object is returned.filesystem.<file.execute env_or_context=null execution_kind="ek_code" returns="last" />
Executes the code in the content of the file in "_subject".
Example: <file "C:/foo/bar.h2o"/>.<execute/>
While a file is being executed, it's string name is in thing.loading_file.
"returns" is similar to the execute_string "returns".
"first" return the value of the first expression in the file. Do not execute the other expressions.
"last" [the default] says return the last value in the file.
"all" says return a vector of all the values in the file.
env_or_context parameter behaves just as it does for execute_string and execute_expr.
Example:
The content of the file "junk.h2o" is: x.<plus y/>
<defmethod foo x>
<set y=8/>
<file "junk.h2o"/>.<execute _environment/>
</defmethod>
<foo 7/> returns 15
execution_kind is similar to the execution_kind paramter in execute_string.
See also: execute_stringfilesystem.<file.file_name />
Returns the string of the file name without its folder or
type.
Example:
<resource.local.file "C:/foo/bar.txt"/>.<file_name/>
returns "bar"filesystem.<file.insert at_key="end" rest=required />
Works similar to insert on strings, inserting the rest args into the content of the file in the _subject. The file is returned.
filesystem.<file.print_file title=null=string with_dialog=false=boolean />
Makes a hardcopy of a file. The title argument is a string that is printed at the top of each page along with the date and a page number. The default value is null meaning use the full file name as the title. To give your pages no title, pass in the empty string. The with_dialog argument determines whether a dialog to choose file printing preferences is presented to the user or not. The default is false meaning just print the file with the current settings. For that to work, the default printer must be accessible to your computer. You can see the default printer by choosing the Steam IDE's "File" menu item "Print...". Note that if you change the printer in the dialog, it does not change the default printer. The next time the dialog comes up the printer will be the same as the first time it came up. Setting the default printer is operating system dependent. On the Windows operating system choose Start/settings/printers. In the dialog that comes up, select the icon of the printer you'd like to be the default printer, and choose the File menu item of "Set as Default". print_file only works if the Steam IDE is loaded. Example: filesystem.<file "logical://user/scratch_1.h2o"/>.<print_file "My Junk"/>
filesystem.<file.set _encoded_set_keycontent=null />
set with a '_subject' of a file can only take one argument which must be
the content whose value must be a string.
the content of the file will be set to the string.
Note that you must use:
a_file.<set content="some value"/>
ie you must use the key "content".
If the new content is not a string, then to_concise_xml is called
on it and the resulting string is written to the file.filesystem.<file.subvector start=0=number.integer end=optional=number.integer />
Works similar to subvector on strings, returning a substring of the content of the file.
To write the content of a file, use the syntax:
a_file.<set content="new content"/>
Note that if the new content is a string it writes out the string.
If the new content is a hypertext object, then the to_html
method is automatically called on it to convert it to a string
before writing to the file.
If the new content is another kind of object, then the
to_concise_xml method is called on it to convert it to a string
before writing to the file.filesystem.<file.write_zip_file manifest_content=null rest=true />
Creates a jar or zip file whose name is specified by '_subject' which
should have an extension of .zip or .jar .
The rest args are input files.
whose content will be included in the output file.
These can be strings, files or folders. If it is a string ending in a slash
or a folder, the files in the folder, and the files in any subfolders,
recursively on down will be added to the output file.
jar files should have a manifest file included in them.
If manifest_content is null (the default) and the extension of the
output file is not ".jar", no manifest file is
included in the written file.
If manifest_content is null and the extension of the
output file is ".jar", a default manifest file is
included in the written file.
If the manifest_content is a string, then that string is used as the content
for the manifest file in the output file.
Example:
<filesystem.file
<uri "file:///C:/My Documents/waterdev/deploy/water_full.jar"/>/>.
<write_zip_file
<filesystem.folder "file:///C:/My Documents/waterdev/water/ide/lib/"/>/>
_subject creates a new file named water_full.jar which includes all
the files under the ...ide/lib/ folder.Returns a vector of the files in '_subject', its subfolders and
recursively all the way down.
The returned vector will also contain any files already in 'result'.
If 'result' is passed, it is returned with the found files added.
If 'result' is not passed, (the usual case), a new empty vector is made.A folder represents a diretory of files and subfolders.
asking for the content field of a folder returns a vector of file and folder objects
of the files and folders within the folder.
A .zip or .jar file behaves very much like a folder. When creating one,
you should create it as a folder. Asking for its content will return a vector
of the files within the zip or jar file.
The full path for a file within a zip file is
the_zip_file_name/the_inner_file_name
Note that both the_zip_file_name and the_inner_file_name may themselves have
slashes in them.
Given a file object that is in a zip file, you can get its content field
to get the string of the content of the file just like regular files.
You can also execute such a file out of a zip file using the same syntax
as regular files.
Creating or writing zip files is not yet supported.<for_each include=regular_key returns="last" exclude=null />
for_each is the most useful looping construct of Water.
Example:
<set my_colors=<vector "red" "green" "blue"/> />
my_colors.<for_each> it.<set_value key value.<concat key/>/>
</for_each>
my_colors returns <vector "red0" "green1" "blue2"/>
The content of for_each is executed once for each element in "_subject".
During that execution,
"it" is bound to the object whose fields are being looped over
"key" is bound to the name of the field within "it" currently being looped over and
"value" is bound to the value of that field.
"_subject" is bound to "_subject" of the outer environment to the call.
Other local variables that are bound before the call to for_each,
but in the same lexical scope (such as the same method body) will still be
bound each time the body of the for_each is executed.
By default the object being looped over is treated as a vector and only its integer
fields are looped over starting with field 0 (zero).
The "include" argument is usually a method that determines exactly which fields to loop over:
The system provides several methods that were made expressly for the value of include:
vector_key (the default) Passes the integer-named fields in a vector.
This method is handled specially by for_each for performance and to
process only those integer fields from 0 to just under the length of the node.
system_key Passes fields such as "_parent". Rarely used.
meta_key Passes only field names that are strings that contain an _f_ substring.
string_key Passes all non_system, non_integer, non-meta_key named fields.
regular_key Passes all user fields and all integer-named fields that
are non-negative.
non_system_key Passes all non_system field keys, thus it passes string_keys,
vector_keys, meta_keys, and negative integer fields.
return_true Passes all fields.
You can write your own methods to include other fields than the above methods allow.
The method is called with each key as "_subject".
If the method returns false, the field will not be processed, otherwise it will be.
Examples: <defmethod is_user_or_integer_field>
_subject.<string_key/>.<or _subject.<is_a integer/> />
</defmethod>
<defmethod my_vehicles>
<vector "boat" "plane" "car"/>.<key_of _subject/>
</defmethod>
If the value of "include" is NOT a method, then it is considered to be a vector of
the valid field names to loop over.
Examples:
<vector 100 101 102 103/>.<for_each include=<vector 0 3/> returns="all">
value
</for_each>
returns <vector 100 103/>
<thing color1="red" color2="white" color3="blue"/>.
<for_each include=<vector "color1" "color3"/> returns="all">
value
</for_each>
returns <vector "red" "blue"/>
The exclude parameter, like the include parameter can take a method or a vector.
If a field name passed the include test, then it is tested against the exclude parameter.
If the field name is either in the exclude vector or the exclude method is called
and returns true, then the field name is excluded and not looped over.
Example:
<vector 100 101 102 103 104/>.
<for_each returns="all" exclude=<vector 1 3/>> key </>
returns <vector 0 2 4/>
Early Return:
You can force for_each to exit the loop and return a value by calling
<return some_value "for_each"/> within the content of for_each.
If you call <return some_value "the name of the current method"/>
then the for_each loop will be exited and so will the
containing defmethod, which will return "some_value".
Normal Return:
If for_each does not hit an early return, what it returns depends on the value of the "returns" arguments.
"last" (the default) returns the value of the last expression in its content that was executed.
"all" returns a vector of the values of all the last expressions from each iteration.
"all_except_null" like "all" except nulls are not included in the returned vector.
Example:
<vector 9 8 7/>.<for_each returns="all"> value.<plus 1/> </for_each>
returns <vector 10 9 8/>
<vector 33 null 32 null 31/>.<for_each returns="all_except_null"> value </for_each>
returns <vector 33 32 31/>
Beware: Do not loop over the fields of an object that you are changing
in the code of the content of a call to for_each. You need to get all
of the keys first, then interate through them and change the object
that they came from. You can get the keys via the 'keys' method.
Note in the examploes below pretend that the call to 'echo' is
really code that modifies mything.
example:
<thing color="red" weight=2/>.<keys/>.<for_each> <echo value/> </for_each>
but that leaves you with 'value' inside of the for_each bound to the
key that you're after. You use this value to get the real value from
the object via 'get' like so:
<thing color="red" weight=2/>.<keys/>
<set mything=<thing color="red" weight=2/>>
mything.<keys/>.<for_each>
<echo value mything.<get value/> />
</for_each>
</set>
A more elegant way to accomplish the task is to use the 'include'
parameter of for_each and they the key and value variables will be bound
as you would expect.
<set mything=<thing color="red" weight=2/>>
mything.<for_each include=mything.<keys/>>
<echo key value/>
</for_each>
</set><force_ek_code obj=required />
Most parameters to methods have execution kind of "ek-code". This means that the source code for the argument in the call will be executed and the result of that execution will be passed in to the method as the value for that parameter. You can change this default behavior by indicating another execution_kind for the parameter when defining the method. See documentation on "execution_kinds" for the possibilities. Occasionally a caller to a method will want to execute the argument source code even though the method definition specifies not to. You can override the method specification by wrapping the source code for the argument in a call to "force_ek_code". Example: <defmethod foo acolor="red"=string="ek_string"> acolor </> <foo blue/> returns "blue". In the call you don't have to wrap double-quotes around blue. But if we want to compute the color instead, we must force_ek_code like so: <foo <force_ek_code "blue".<concat "green"/>/>/> returns "bluegreen". Using force_ek_code makes sense only for non-content arguments and only for arguments that are of execution_kind ek_string and ek_expression. You can use it for ek_code and ek_hypertext arguments and it will behave as if you didn't wrap the arg source in it. Using force_ek_code on ek_data arguments will NOT cause an evaluation since ek_data is used when you want to read in some data but not permit general execution during the loading of the data structure.
You can "print" an object to a string using a wide variety of methods in Water.
These methods take a Water object as the subject and return a string
representation of that object. Some of these methods make representations
of an object that can be executed to re-create the object. This is useful for
"serializing" the object to send it over the net, or "persistence" to
save it in a file. Since the higher level formatters can represent not just
the object that is passed to the formatter but objects in its field values
recursively on down, large, complex, self_referential structures can be printed
using these methods.
Understanding the functionality of each formatter is crucial to selecting
the right tool for your job.
- to_string is the crudest of formatters, returning the result of calling
Java's toString method on the subject. For all but the very simplest
literals, the result of to_string cannot be executed to re-create the object.
- to_literal For literals, returns a string that can be read back in.
For non literals, returns false.
- to_path For literals, does with to_literal does. For defclasses,
defmethods and cached instances, returns a path to the object.
For other objects, returns false.
- to_concise_xml Returns a concise_xml representation of the object
which is a literal, a path or, in the case of an instance, a representation
of the whole object including values for all its fields.
- to_h2o The most complex printer, capable of printing out whole classes
including their subclasses and cached instances. to_h2o can take an argument
that causes only cached instances to be printed, not the classes themselves.
- to_html formats objects to be presented in web browsers. The hypertext objects
and objects that contain them print out as html tags. Other objects
print out as empty strings. Water has some clever ways to make forms
out of methods.
- to_xml formats objects not as Concise XML but as XML 1.0 syntax wherein all
attribute values are strings and full ending tags are printed, unlike
to_concise_xml.
Besides these formatters there are a number of other methods that are useful
in making string representations of objects.
- concat concatenates the to_html representations of all its arguments.
- echo prints out objects to the Java console using to_string.
If you'd like to use another formatter just use it like so:
<thing weight=234/>.<to_concise_xml/>.<echo/>
- string methods such as to_uppercase and to_lowercase help transform
strings to a desired format.
- integer.to_hex_string is useful to convert integers to hexidecimal format.
- file.<print_file/> will make a hardcopy of a file. If you want to print a
random string, first write it out to a file then print the file.
See also: to_string, to_literal, to path, to_concise_xml, to_h2o,
cache_instance, to_html, to_xml,
concat, echo, string.to_lowercase, string.to_uppercase,
integer.to_hex_string, filesystem.file.print_file<from obj=required make=false />
'from' attempts to turn an object into another kind of object.
It is a 'data-converter' and in some cases an alternative
way to construct an object from the usual
<some_class/> way of making an instance.
'from' uses a whole bunch of heuristics to do conversion.
If it can't make a reasonable conversion, it errors.
The syntax is: some_type.<from some_object/>
'from' generally accepts many differnt types for some_object.
If some_object is already an instance of some_type, then
some_object is just returned. Otherwise, an attempt is made
to use some_object as a description of an instance of some_type.
If successful, that instance is returned, otherwise error.
There are a lot of details to 'from'. If you're confused about
what it may do in a certain situation, just try it.
In general 'from' does a good job and converting between literals.
It also converts to vectors and even record objects.
boolean
False, the integers 0 and -1, the chars 0fFnN,
and the strings "false" "null" "no" "" "0" "-1" (of any case)
are all converted to false.
Everythng else is convertred to true.
boolean.<from 0/> returns false
boolean.<from "NO"/> returns false
integer
null and false are converted to 0.
true is converted to 1.
integers convert to theemselves.
floats are converted to the integer immediately above it or below it
depending on the 'direction' argument which may be:
"nearest" "towards_zero" "up" "down".
chars are converted to their ascii equivalent.
strings are read as a string of digits (with optional leading minus sign)
Everything else errors.
integer.<from false/> returns 0
integer.<from "123"/> returns 123
integer.<from <char "a"/>/> returns 97
integer.<from 12.3 direction="up"/> returns 124
integer.from can also take a 'radix' parameter to provide a base
for conversion of strings.
integer.<from "A" radix=16/> returns 10
float
integers convert to the float of the same numerical value.
floats convert to themselves
strings are read as a floating point number, usually with a decimal point in them.
float.<from 23/> returns 23.0
float.<from "23.4"/> returns 23.4
float.<from "17"/> returns 17.0
number
floats or integers convert to themselves
chars convert to their ascii equivalent integer
strings are converted to an integer if they have no decimal point in them,
and a float if they do.
number.<from <char "a"/>/> returns 97
number.<from "34"/> returns the integer 34
number.<from "3.4"/> returns the float 3.4
number.from takes a radix argument just like integer.from.
char
An integer is used as the ascii value to find the corresponding char.
A string has its first char returned. If the string is empty, error
char.<from 97/> returns <char "a"/>
char.<from "a"/> returnd <char "a"/>
string
to_concise_xml is called on the argument and the resulting string is returned.
string.<from 123/> returns "123"
If you have a vector of chars and you want to convert it to a string,
you can't use 'from'. Do this instead:
<vector <char "a"/> <char "b"/>/>.<char_vector_to_string /> returns "ab"
vector
A strings are converted into a vector of chars.
Supervectors, ie records that contain vector-keys, are converted into
a straight vector, losing the information in non-vector keys.
vectors are just returned.
For other types of objects an empty vector is returned since they have
a length of zero.
vector.<from "ab"/> returns <vector <char "a"/> <char "b"/>/>
vector.<from <thing 0="red" 1="blue"/>/> returns <vector "red" "blue"/>
literal
Strings are converted into a literal just as normal exection does.
literal.<from "123"/> retruns 123
literal.<from "true"/> returns true
A string that doesn't represent a literal is just returned.
literal.<from "junk"/> returns "junk"
Other literals passed in are just returned as is.
literal.<from 123/> returns 123
datetime
Particular strings are converted into a datetime.
The strings must follow a special syntax, but this can still make entry of dates easier.
Each string argument contains one, two or three integers
separated by a dash, slash, comma, period or space.
The first integer represents the year [use 4 digits], the 2nd the month [1=jan]
the third is the day of the month [1 through 31].
Exception: If you give only two integers and the first integer is less than 13,
then the first integer is considered to be the month and the 2nd integer is the
day of the month with the year defaulting to the current year.
datetime.<from "12-25"/> returns a date of Christmas of the current year
datetime.<from "2003/12/25"/> returns Christmas in 2003.
thing
thing.<from some_obj/> usually just returns 'some_obj' since, after all,
everything is a thing so some_obj is already a thing.
However there's one exception.
If some_obj is a vector, then a new object is made which is an instance
of the subject of thing that will contain non-negative consective
integer keyed fields with their corresponding values from the vector.
Example: thing.<from <vector 4 5/>/> returns <thing 0=4 1=5/>
See also: char_vector_to_string, to_string, to_concise_xml, to_html, to_identifier,
to_plain_text<get key=required lookup=false=boolean returns="first" if_missing="return" default=false />
Get provides a way to access values of fields via a method call.
Most of the time you access a field you can do simply:
boat.color
If the field name is in a variable and you want it to be dynamically computed,
you can do something like:
boat.<get "co".<concat "lor"/>/>
which is equivalent to:
boat.<get "color"/>
Note that all the arguments to 'get' are of execution_kind ek_code.
Normally, a call to 'get' looks for the field only in the subject
and if it doesn't find it in the subject, returns false.
But you can have 'get' do a 'lookup' into the ancestors of the subject
by supplying an argument of lookup=true like so:
boat.<get "color" lookup=true/> in which case the parent of 'boat', and
its parent, etc. will also be searched. The closest ancestor to the subject
that has the passed in field key will supply the value of the call to 'get'.
The above call to 'get' behaves just like:
boat.color
The default value of the lookup argument is false.
The _subject to 'get' defaults to the local environment:
Example:
<set aaa=333> <get "aaa"/> </> returns 333
If you want to get a vector of ALL the values of a particular field in all the
ancestors, call get with returns="all" like so:
<<thing color="red"/> color="white"/>.<get "color" returns="all"/>
Here we are creating a parent object with a color of "red" and a child object
of that parent with a color of white.
The returned vector is <vector "white" "red"/> where the order of the elements is
the "closest value to "_subject" is first", in this case "white".
If you use returns="all" and lookup="false" then you will get a
vector of one value, the value of the field in "_subject".
Get has two other optional arguments to specify the behavior in case the field being
looked for is not present.
if_missing make take on two possible values:
"return" (the default) means we are going to return the value of the default argument
"error" means error
default The value to return when if_missing is "return" or
an error message (string) if if_missing is "error".
The default value for 'default' is false.Returns an object representing the fields of the email message indicated by index that is on the host in the user's account. The default value for index is 0, meaning get the oldest one. An index of 'latest' means get the newest one. If index is 'all' then return a vector of email messages. If delete is true, delete the email from the server after retrieving it, otherwise just leave it on the server. Returned email messages are objects of type 'email.inbound'. They have the fields that are present in the email which typically are: To, From, Subject, Message, Date, Message-Id, Received, Status and usually afew more. All field values are strings. The body of the email message is put into the "Message" field. Example: my_email.<get_email index=2 delete=true/> If index is an integer and get_email fails, false will be returned. If index is 'all', get_email returns a vector of those email messages it was able to get. When index is 'all' and delete is true, only those email messages actually returned will be deleted from the host.
Returns the number of email messages on the host for the user. If it is unable to determine the number of email messages, returns null.
<get_java_class />
Returns the java class of _subject. Example: <set mydate=<<get_java_method "java.util.Date" "new" "int" "int" "int"/> 99 2 24/> /> mydate.<get_java_class/> returns the class object for java.util.Date If you want to get the Java Class Object given the name of the class use: <<get_java_method "Class" "forName" "String"/> "java.util.Date"/>
<get_java_class_field_value class_name=required key=required />
Returns the value of a static field in the indicated class. Example: <get_java_class_field_value "java.lang.foo" "bar"/>
<get_java_method rest=required />
Returns the java method indicated by the arguments.
You pass the class of the method, followed by the method name, followed by
the class of each of its arguments.
Example:
<get_java_method "Bob" "get_java_class_field_value" "String" "String"/>
There are abbreviations for some common classes like String and Integer, but
others you must pass by their full name (prefixed with a package).
Details:
The first argument is class as a java class, or a string of the class name, or a
Java instance from which we extract the class.
Warning: If the "instance" that you're passing in as an argument happens to be a string,
i.e. you want to get a method on the class java.lang.String, then you should
instead pass in exactly "String" .
2nd argument is method name, (a string) ,
and the rest of arguments are the class-names of the parameters to the method you want to be returned.
Class names in the java.lang package can be abbreviated from "java.lang.Math" to just "Math" if you like.
All the java primitives, i.e. int, char, boolean can be spelled "int", "char", "boolean", etc.
Example: <get_java_method "Math" "min" "int" "int"/>
The formal, obscure java "java.lang.Integer.TYPE" also works, but "int" is a lot clearer.
Constructors
You can get constructors using the method name of "new".
Example: <get_java_method "java.lang.StringBuffer" "new" "String"/>
Calling Static Java Methods
In a Water call, the name of the element is executed to get the method to call.
The result of that execution can be either a Water method or a Java method.
So for instance we can call the java "min" method like so:
Example: <<get_java_method "Math" "min" "int" "int"/> 89 47 />
Note that even though Water has no ints, i.e. all integers are represented as java Integers,
you can still call many java methods that take primitives.
In the above example 89 and 47 are turned into Integers in Water but when passed to java's min method,
they will behave as ints.
Calling Constructors
To make an instance of a StringBuffer initialized to "abc" you can do this:
<<get_java_method "java.lang.StringBuffer" "new" "String"/> "abc"/>
Here's an example of creating a java Date object initializing it to March 24th, 1999.
(Note the month 2 in Java is March, not February as months are zero based.)
Example: <<get_java_method "java.util.Date" "new" "int" "int" "int"/> 99 2 24/>
Calling Instance Methods
If you call a static method, the "_subject" of the call is ignored.
But calling an instance method it isn't, so for example:
Create a date:
<set mydate=<<get_java_method "java.util.Date" "new" "int" "int" "int"/> 99 2 24/> />
Then get the year:
mydate.<<get_java_method "java.util.Date" "getYear"/>/> returns 99<get_type key=required />
Returns the type of a field, infering a type if none explcitly available. The argument 'key' is the name of the field which is looked up in _subject. If the field has a meta_key of "type" then the value of that meta_key is returned. Otherwise, if the field is found return the parent of the value of the field. Otherwise, return thing.
<get_type_checking />
Returns a string of the value of the type_checking flag. See set_type_checking documentation for the possible strings.
<get_value key=required />
Low level way to get the value of a field in an object. Does not perform "active value" gets. Cannot get fluid values. Most developer calls for getting a field's value should use the dot syntax or the method "get". See also: get
<get_with_value a_key="name" a_value=required returns="first" />
get_with_value finds objects within _subject that have a field of the given key
whose value is the given value.
get_with_value walks the fields of _subject in a depth-first order.
If the 'returns' argument is:
- "first" (the default) then the first object which has the key with the proper value
will be returned. If no such object is found, null is returned.
- "last" then the last object which has the key with the proper value
will be returned. If no such object is found, null is returned.
- "all" then a vector of all the objects which have the key with the proper value
will be returned.
Note that the _subject itself is the first object checked and if it matches, it
will be included in the result.
Examples:
<thing deep=<thing weight=135/>/>.<get_with_value "weight" 135/> returns:
<thing weight=135/>
<vector <thing material="cloth"/>
<thing weight=135 material="cotton"/>
<thing deep=<thing deeper=<vector 31
<thing weight=135 material="silver"/>
<thing weight=135 material="gold"/> />/>/>/>.
<get_with_value "weight" 135 returns="all"/>
returns:
<vector <thing material="cotton" weight=135/>
<thing material="silver" weight=135/>
<thing material="gold" weight=135/> />OPERATING SYSTEM SET-UP
We have found that using a mouse pointer that shows "trails"
or "shadows" causes trouble in the Steam editor.
On Windows platforms, you can turn these mouse trails off by
going to Start/Settings/Control Panel/Mouse/Motion/Cursor Trails
and unchecking the "enabled" checkbox.
STEAM SET-UP
When you launch the IDE, a whole bunch of Water files are loaded
to give you the standard Water functionality. You can extend that by
creating a file named init.h2o and sticking it in the water_user_folder.
This is also the folder where your own Water files will be saved.
If an init.h2o file exists in that folder, it will be executed when
you launch the IDE so you can customize your initial functionality
just by putting code in that file.
Two files which give additional functionality that some, but not all
users will want. can be loaded with the following syntax:
"logical://system/lib_extras/hypertext_html.h2o".<execute_file/>
defines old html tags that were in HTML 3 & 4 but not in XHTML.
This is useful when you're executing a random web page that is likely
to have some non-XHTML HTML on it.
"logical://system/lib_extras/colors.h2o".<execute_file/>
defines the standard set of HTML color names which, after
loading, you can access via: color.of.violet
You can see the full list via: color.of.<inspect/>
WINDOWS OF THE DEVELOPMENT ENVIRONMENT
The Steam IDE is a development environment for the Water Language.
It has two major windows:
- The window titled "Steam IDE for the Water Language" contains a large
editor pane for entering Water source code, and two smaller panes
on the right for viewing the result of executing source code.
- The window titled "Water Inspector" lets you view the details of
Water objects. Since the on-line documentation is stored in Water
objects, it is used for reading documentation as well. If you're viewing
this document within the IDE, you're probably in the Water Inspector.
You can switch between these windows by the usual way to select different
windows on your operating system. In Windows OS, go to the Task Bar and
select the window you're interested in.
It will help to follow the directions below if you make both windows
visible at the same time. Drag the lower left corner of each
window to resize it to be short and wide.
Drag the title bar to positioning the Steam IDE window on top and the
Water Inspector window beneath it.
INSPECTOR WINDOW
The Inspector window contains two major panes, a "History list" that
shows each object you've recently inspected and a "Fields" list of
the object being inspected. When you are inspecting a string,
the Fields list will display "String" to its left.
When you are inspecting another kind of object, "Fields" will be
displayed on the left. Each row in the lower right pane represents
a field of the object being inspected. Clicking on a row will
inspect the value of its field.
The row you click on will be moved up to the History list
and the fields of that field's value will now be displayed in
the "Fields" pane. You can keep clicking on rows in the lower
pane to descend deeper into the object hierarchy.
By clicking on an object in the History list, you go back to a
previously inspected object.
Experiment with the Inspector by inspecting 'thing', the root object.
In the Inspector window, under the 'Tools' menu, choose 'Inspect thing'.
Click in the lower pane on any row of interest. You can get back to
this document either by the Help menu item 'Getting Started' or
clicking on Getting Started in the History pane.
When you are viewing fields in the Inspector, the most important
methods and some other objects have a meta_field of "doc".
These field names end in "_f_doc". You can filter for these using the check boxes
at the top of the inspector. For other methods and objects, inspecting them will
tell you what parameters/fields are available.
INSPECTOR HELP
The Inspector window's Help menu has items for:
- "Help Topics" which shows the fields of the thing.reference_manual object
which serve as a Table of Contents to the Reference Manual.
- "Help on" which shows help for the selected word.
- "Inspector Help" for additional information on using the Inspector
- "Getting Started" for viewing this text.
The items in the Table of Contents represent only the top level of
the on-line Reference Manual.
Once you've played with Water a bit, we recommend reading the chapters in order.
All introduce important topics.
Even if you *think* you aren't interested in formal testing near
the beginning of your experience with Water, take a look at the
"testing" chapter as it describes a methodology for coding that
takes advantage of the strengths of Water and the Steam development environment.
STEAM IDE WINDOW
In the Steam IDE window, the Help menu also has "Help Topics" and "Getting Started".
Notice the item: 'Help on ...' This lets you get specific help on a method,
class or field in Water.
If you have a selection in the editor buffer before choosing this item,
you will be shown documentation on it. If you have no selection,
a dialog will pop up asking you to enter a word to get documentation on.
PROGRAMMING IN WATER
It is time to write a little code.
First write Hello World by typing in "Hello World" in the editor,
including the double quotes.
You can run this program by double clicking before the opening double quote
to select it, and clicking on the "Execute" button.
You'll see "Hello World" (including the double quotes) in the upper right pane
showing you the actual string that the code evaluated to.
(Strings are self-evaluating.)
In the lower right pane you'll see the string rendered in HTML, where you'll find
"Hello World" without the double quotes. Both right panes show a view of the result.
The upper shows the value represented in Concise XML, whereas the lower is a
rendering of an HTML version of the resulting object. You'll find the upper pane
most useful when looking at intermediate results and the lower most useful
when making web pages for users.
Second, move the insertion point to some whitespace in the editor buffer and
click right to bring up a menu of insertions.
(If right-clicking doesn't bring up a menu, you can use the "Insert" menu
in the menu bar of the Steam IDE window which contains the same items.)
Choose "Hello World Web Page" and you'll see some HTML inserted into the editor buffer.
If you double-click at the beginning or ending of a Water expression, say just before
the open angle bracket of a call, the complete expression will be highlighted.
(If the expression is syntactically incorrect, it won't be and you'll see an
error message in the lower right pane.)
If you double_click in the middle of a method name or class name, it will not
only select the whole name but also give you the parameters to calling the
method or class in the lower right pane. You can click on each item in the
lower right pane for more information.
Double_click just in front of the first open angle bracket and click on Execute.
Now you'll see a more nicely formatted Hello World in the lower right pane
and a printed representation of the object that was returned by the execution
in the upper right pane.
You can inspect the object by clicking right on the upper right pane then selecting
"Inspect This Object" from the menu that pops up.
Another way to do this is to go to the Steam IDE window's "Tools" menu
and choose "Inspect latest result".
(Note if you do this, you'll have to click on "Getting Started" in the History
list of the inspector to get back to this text.)
You can look at the HTML representation for this object by right-clicking in the
lower right pane of the Steam IDE window and choosing "Inspect HTML Source".
Next, try changing the font size from: 6 to: 1.<plus 2/>
Don't wrap double quotes around the value for the size attribute and it
will be executed as code.
Click on the Execute button to see a smaller Hello World.
You can stick code in as the value for any
html attribute and have its value dynamically created.
There's LOTS more to Water and Steam.
- If you're adventurous, dive in by clicking right in the editor pane
and choosing some more expressions to insert and execute.
- Choose "Help Topics" from the Help menu to keep warm while you get wet.
- Find out about the latest on Water by visiting http://www.waterlanguage.org/
where you can read articles, ask questions and order the latest book
about Water.<has key=required lookup=false />
Returns true if "_subject" has a key named 'key'. If 'lookup' is true (the default is false), then it will also return true if any of the ancestors of '_subject' has a field with the given key, otherwise returns false. If _subject is 'fluid' then the lookup arg is ignored and the first binding of the key in the fluids is returned. If there is no subject, 'has' looks up the key in the local environment. In that case, the value of lookup is immaterial. It always checks all frames of the current local environment.
<has_subject />
Returns true if their is a binding of the local variable "_subject" in the environment that the call to has_subject is made, otherwise returns false. Examples: <defmethod foo> <has_subject/> </defmethod> <foo/> returns false 3.<foo/> returns true <foo _subject=99/> returns true <defmethod foo _subject=246> <has_subject/> </defmethod> <foo/> returns true <has_subject/> is functionally equivalent to <has "_subject"/> See also: has
<hypertext
id=optional class=optional style=style title=title=string lang=optional xml:lang=optional dir="ltr"=
Water defines every XHTML tag as a subclass of the hypertrext class
under thing. Thus thing.hypertext.b is a class for the 'bold' tag.
When you make a call to an html tag, i.e. <b>hi</b> ,
an instance of that tag's class is made containing the content and
attributes specified as fields in the new instance.
XHTML specifies that each tag's attributes must be named and must
have values of strings. Water permits that but also allows you to
have by-position arguments and non-strings as values, just like
other Water calls. Most XHTML attributes are of execution kind "ek_code".
XHTML specifies that all tag names and attribute names are lower case.
Water defines lower case tags as well as an upper case version of
each tag for compatibility with a common practice in html of
upper casing tags. HTML tags that have upper case attribute names
have their attribute names automatically converted to lower case
equivalents upon object creation for compatibility with XHTML. Thus:
<A HREF="abc.com">click</>.href returns "abc.com" but
<A HREF="abc.com">click</>.HREF errors since there is no
key in the a tag instance that is spelled "HREF".
<a href="abc.com">click</> is a synonym for the above and the
preferred XHTML syntax.
To explicitly see the HTML formatting of a tag, call the to_html method
on the object: <b> hi </>.<to_html/>
You can also see the HRML by clicking right in the lower right pane and
choosing to inspect the HTML source.
Use html_to_xhtml to clean up old html code before executing it
in Water.
Caveats as of Feb 1, 2003:
- The lower right browser pane in the development environment can't render
every tag, at least in the way that modern browsers do.
Use the tools menu "Browse Latest Result" to see it in a real browser.
- Older, non-XHTML tags are not supported right now though we
will provide a mechanism for them to work in a future release.
See also: html_to_xhtml<a charset=optional type=optional name=optional href=optional hreflang=optional rel=optional rev=optional shape="rect" coords=optional />
href attr for 'a' the tag is relative to page_object.
<form action=required method="get" enctype="application/x-www-form-urlencoded" onsubmit=optional onreset=optional accept=optional accept-charset=optional />
The action attribute for the 'form' tag is relative to page_object.
<input type="text" name=optional value=optional checked=false disabled=false readonly=false size=optional maxlength=optional src=optional alt=optional usemap=optional onselect=optional onchange=optional accept=optional />
The name attribute for the 'input' tag needs to be a field in form_object
<select name=optional size=optional multiple=optional disabled=optional tabindex=optional onfocus=optional=script onblur=optional=script onchange=optional=script />
The normal syntax for select is:
<select> <option>red</option> <option>green</option> <option>blue</option></select>
In addition, Water let's you use:
<select "red" "green" "blue"/> where each rest arg is executed before it is
used as an option.
If you've got your options in a vector:
<set vec <vector "red" "green" "blue"/>>
<select rest=vec/>
</set>
And since a call to one_of makes a supervector:
<select rest=<type.one_of "red" "green" "blue"/>/>
also makes a menu of three colors.<ide />
The ide class contains methods for programmatically finding out
about and modifying the development environment.
(IDE stands for Integrated Development Environment.)
These methods are useful for:
- Creating a special development environment for a scripting language
built on top of the Steam IDE with very little effort
- Modifying the development environment to make teaching easier
by removing unneeded items and perhaps adding a menu or two
of commands needed for the current lesson.
- Customizing the Steam IDE for your own personal use.
ide contains methods for:
- adding user interface controls (menus, checkboxes,
a repositional toolbar, etc.) using the method 'add_item'.
This method lets you add new items
to existing menus, create new submenus on existing menus,
or add whole new top level menus as well as make buttons,
checkboxes, radio buttons and text fields at top level.
- removing items via 'remove_item'
- getting and setting the 'value' of controls such as
checkbox state or text in a textfield using the methods:
get_item_value and set_item_value.
- programmatically invoking a control via 'do_click'
- load files into the ide or make a hidden buffer current
via 'open_file'
- various methods for manipulating the text in the current buffer
including insertion of text via insert_around_selection
as well as getting and setting the current selection.
A few common methods are on the 'Insert' menu under the
'Development Enviornment' submenu.
Inserting and executing the "Code Examples" on that menu is probably
the fastest way to get started with customizing the development environment.
See the documentation for the methods in thing.ide for details, especially add_item.
ide.<add_item
labels=required=vector index=-1=number.integer item_kind="item"=
Creates and adds a new user interface control to the IDE.
If there is an existing control with the same name in the
same container, that control is removed before adding the
new control.
Takes parameters:
- labels a vector of strings that specifies the location and
label of the new item.
The first element of the vector is either
- "menubar" specifying the IDE menu bar or
- "toolbar" specifying another bar just below the main menu bar.
Usually and by default this bar will be a "toolbar".
That happens when you do one of the following when there is no toolbar:
ide.<add_item <vector "toolbar"/>/> warning: nothing shows up until you have
an actual item in the toolbar
ide.<add_item <vector "toolbar" "mybutton"/>/>
ide.<add_item <vector "toolbar"/> item_kind="toolbar"/>
If the item in the location "toolbar" is in fact of item_kind "toolbar",
then you can drag it (by click down on any unused space and drag) to
any of the 4 sides surrounding the rectangle that encloses the
editor pane and the two output panes on the right.
When the dragging outline turns red, that means you can drop it
and it will "doc" to that side.
If you let up on the button when the toolbar is NOT over one of those edges,
a new window will be created to hold the items in the toolbar.
You can position this window wherever you like by dragging the title bar.
When you click the close-box of the window, the toolbar will go back
into its original location.
You can add just one row of items to an item of kind "toolbar".
If you add lots of items they will get all scrunched up.
In that case you can usually get more items on the toolbar if
you drag it to the left or right side.
Another solution is to create the item in the toolbar location
via ide.<add_item <vector "toolbar"/> item_kind="menubar"/>
This makes a menubar that, when you fill up the first row, a
second row will automatically be created. You can make a rather large
toolbar this way, but it cannot be dragged to another edge nor made
into its own window.
The last element of labels is the label for the new item.
The middle elements of Labels specify the hierarchy
of menus that will contain the new item.
Labels must have at least one element.
- index an integer specifying where in the container of the new
item that the new item will be placed. An index of 0 will make
the new item the first item in its container, i.e. at the
top of a menu or on the left of a menu bar.
An index of -1 will make the new item be the last item in
its container. The default value is -1.
If the index is greater than the number of items already in the
container, the new item will become the new last item.
If the index is negative and specifies an item before the
first item, the new item will become the new first item
in its container.
- item_kind Specified what kind of new item to make. The default value is "item".
- "item" means if its container, i.e. the 2nd to last item in labels,
is a menu, make a menu item, otherwise make a button.
"item" is the default item_kind.
- "checkbox" makes a checkbox item.
- "combobox" makes a combobox that displays one of its elements and lets
the user choose any of the elements.
- "editable_combobox" is like a combination of combobox and textfield.
The user can choose an existing element or type in a new one.
- "label" makes an inactive label,
used only in menu bars, not in menus.
- "menu" makes a new submenu if its container is a menu or a
new top level "pull-down" menu if its container is a menu bar.
- "radiobutton" Creates a radio button. All radio buttons within a container, i.e. a menu
or a menu bar are considered to be part of the same radio button group.
when you select one in the group, any previously selected radio button becomes
unselected. Special conveniences in get_item_value and set_item_value
make radiobuttons particularly easy to deal with.
- "separator" If the container is a menu, puts a horizontal line
separator in that menu. If the container is a menu bar, puts a
vertical line in the menu bar.
Note that like textfield, combobox and editable_combobox,
you still must give a label to this item even though that
label is not displayed.
- "textfield" makes a one-line text entry field,
used only in menu bars, not in menus.
- make_menus_if_not_found a boolean specifying whether or not to create
intermediate menus if they don't exist.
The default value is true. A value of false will cause an error
if the intermediate menus are not found.
The default value is true.
- tooltip A string specifying the tool tip text that is displayed when the
mouse is on the item and still for a few seconds.
The default value of "" causes no tooltip to be created.
- initial_value This is the 'value of the item to be created.
For item_kind of:
- "checkbox" true or false indicating checked or unchecked.
- "combobox" and editable_combobox A vector of objects making up the
possible options to choose. Usually these are literals but can be
other objects as well.
- "radionbutton" a value of 'true' will select this radiobutton within its container.
all other initial_values are ignored.
- "textfield" The string to appear in the textfield initially.
For other item_kinds, initial_value is ignored.
- The content is Water code that is executed when the item is activated.
Activated means for item kind of:
- "item" when clicked on or chosen
- "checkbox" when clicked on
- "combobox" when you select an item.
- "editable_combobox" when you select an item or type 'enter' or 'return'
in the text field.
- "label" can not be activated
- "radiobutton" when clicked on
- "separator" can not be activated
- "textfield" when you type 'enter' or 'return' in the text field.
While the Water code in the content is being executed,
the variable 'item_value' is bound to the just-selected value of the item.
Examples:
ide.<add_item <vector "menubar" "greetings" "english" "hi"/>
0 "item" true "short for hello">
<echo 'hi folks'/>
</add_item>
This makes a new menu on the right of the menubar named "greetings".
It will have a submenu of "english" that contains one item named "hi".
When you hover over "hi" you will see a tooltip of "short for hello".
When you choose the new menu item, 'hi folks' will be printed
in the console.
ide.<add_item labels=<vector "toolbar" "colors"/>
item_kind="combobox"
initial_value=<vector "green" "yellow" "red"/>>
<if> item_value.<is "green"/> <echo "go"/>
item_value.<is "yellow"/> <echo "slow down"/>
else <echo "stop"/>
</if>
</add_item>
This creates the toolbar if it didn't already exist and adds a combo box
to it at the end. Choosing an item will print "go", "slow down" or "stop"
depending on the value chosen.ide.<do_click labels=required=vector />
Programmatically performs a user mouse-click on the item specified by the first argument of a vector of labels. For checkbox and radiobutton, it not only selects the item (as you can do with set_item_value), but it also invokes the associated action for clicking on that item. For menus, it just pops down the menu and leaves it down. For combobox and editable_combobox, does nothing.
ide.<exists labels=required=vector />
Takes a labels vector, returns true if the specified item exists, false otherwise.
ide.<full_text />
Returns a string of all of the text in the current buffer.
ide.<full_text_length />
Returns the integer of the length of the full text in the current buffer.
ide.<get_item_value labels=required=vector />
Takes one argument of a vector of strings that identifies the control.
If the control is a:
checkbox, returns true or false
combobox or editable_combobox, returns the string that is selected.
menu or a menubar, returns the label of the first sub item that is a
radiobutton that is selected. If that's not found,
returns null.
radiobutton returns true if it is selected and false otherwise
textfield, returns the string in the textfield
non-existent, errors.
otherwise returns null.
You can get and set the value of three special toip level text panes:
"sourcepane" (the editor pane)
"resultpane" (the upper right result pane)
"browsepane" (the lower right html browser pane)
Example:
ide.<get_item_value <vector "browsepane"/> />
ide.<set_item_value <vector "browsepane"/> "<i>you</>"/>
Warning: this method calls might not do what you think if you execute them
by selecting the source in the source pane and hitting execute.
They are more likey to do what you'd expect if you are calling them
from a button or menu item click.ide.<insert_around_selection before_string=""=string after_string=""=string selection_start=optional=number.integer selection_end=optional=number.integer />
Inserts text into the current editor buffer.
Parameters:
- before_string A string of text to insert before the
current selection, or, if no selection, the insertion point.
Defaults to "".
- after_string A string of text to insert after the
current selection, or, if no selection, the insertion point.
Defaults to "".
- selection_start a non-negative integer.
If you would like to leave the buffer with a selection,
pass in selection_start and selection_end
which will select a substring of the buffer with
0 being the first character of the before_string.
- selection_end If you don't pass this but do pass
in selection_start, the insertion point will be left
at the positon designated in selection_start.ide.<open_file file=required />
Makes the given file be the current buffer in the editor. Takes a string file name as an argument. The name can be in format "file:///C:/myfile" or "C:/myfile". If the file is already in a buffer and the buffer is the current buffer, does nothing and returns "already current buffer". If the file is already in a buffer that is not the current buffer, saves out the current buffer if it needs it and auto-save is on, then makes the buffer containing the specified file be the current buffer and returns "made existing buffer current". If the file is not in a buffer but the file is on disk, saves out the current buffer if it needs it and auto-save is on, then makes a new buffer containing the contents of the specified file, makes the new buffer the current buffer and returns "opened existing file" If the file is not in a buffer and the file is not on disk, saves out the current buffer if it needs it and auto-save is on, then makes a new empty file on disk, creates a new buffer containing the contents of the new empty file, makes the new buffer the current buffer and returns "created file".
ide.<remove_item labels=required=vector />
Removes the item specified by the first argument vector of labels.
ide.<selection_end />
Returns the position of the end of the selection in the current buffer. If there is no selection, returns the position of the insertion point.
ide.<selection_start />
Returns the position of the start of the selection in the current buffer. If there is no selection, returns the position of the insertion point.
ide.<selection_text />
Returns a string of the text in the selection in the current buffer.
ide.<set_item_value labels=required=vector new_value=required />
Takes an argument of a vector of strings that identifies the control and
a new_value. The new_value must be appropriate for the control kind.
If the control is a:
checkbox, new_value must be true or value
combobox new_value must be an item in the combobox
editable_combobox, new_value can be anything but usually is a literal and often
is an item in the combobox.
menu or a menubar new_value is the label of a radiobutton within the menu to select.
If no such radiobutton is found, error.
radiobutton new_value can only be true.
textfield, must be a string
non-existent, errors.
otherwise errors.
See also get_item_value especially for "sourcepane", "resultpane", "browsepane".ide.<set_selection start=0=number.integer end=optional=number.integer />
Sets the selection in the current buffer to the start and end arguments. start defaults to zero, the beginning of the buffer. If you do not pass in the end argument, it defaults to the same as the start argument, in which case this method just repositions the insertion point. Thus to set the insertion point at the beginning of the buffer: ide.<set_selection/> To select all the text in the current buffer: ide.<set_selection 0 ide.<full_text_length/>/> To remove the text in the current selection: ide.<do_click <vector "menubar" "Edit" "Cut"/>/> Warning: If you select the above call in an editor buffer, executing it will cause it to delete itself!
<if continue=false returns="last" />
Example: <if> x.<less 10/> "got a digit"
true "got more than a digit"
</if>
IF takes a content with an even number of expressions.
If the first expression of a pair executes to true,
then the 2nd expression of the pair is executed.
If the 2nd expression executes to "repeat", then
IF starts over again.
If the 2nd expression executes to "continue" then
the next clause in the IF is processed.
Otherwise, the call to IF returns with the value
of the 2nd expression.
The "repeat" value lets you use IF like a multi-conditional loop.
The "continue" value lets you use IF like a "switch" statement where
you must explicitly state that you want to "fall through" to the next clause.
Having neither of these special control indicators causes the IF to
terminate.
If can be used as a "while" loop like so:
Example:
<set count=0/>
<if> count.<is 10/> "we're done"
true <do> <echo "on count: " count/>
<set count=count.<plus 1/> />
"repeat"
</do>
</if>
This example prints out a line upon each iteration and returns the string "we're done".
'if' has two optional attributes:
continue default value: false. If true, then each action clause acts as if it has
a "continue" as its last value. Thus whenever a clause hits, its action is executed
and the next clause is tried.
returns default value: "last" other possible value: "all"
If the value of returns is "last", then the value of the last action that is
executed will be returned. If the value of returns is "all", then
a vector of the values of all the actions that were executed is returned.
This is similar to the "returns" attribute of "for_each".<iip pause=false='ek_expression' label="iip"=string />
iip is used to debug applications by showing you the fields of intermediate
data encountered in executing some code. A call to iip brings up the inspector.
iip inspects its _subject and returns that _subject so it can be inserted
in the middle of a path without affecting the semantics of the path execution.
If you give iip a first argument of p, execution will pause when the call to iip is
encountered. You may continue from the pause by hitting the Execute button in the development
environment.
You may also give iip a label to help distinguish this particular inspect from
some other call to inspect.
Example:
thing.number.<iip p/>.integer
Will display the number object in the inspector and pause. Upon continuing,
integer will be executed.
If you don't care about pausing or passing a label just use the active value ii like so:
thing.number.ii.integer
which will inspect number and immediately proceed on to executing integer.
If you call iip without a subject, it will inspect the environment of the call to iip.
Example:
<defmethod foo a=2> <iip p/> </defmethod>
<foo/> execution will pause at the call to iip and the inspector will come up
inspecting the environment, one of whose items will be a=2.
See also inspect, ii
<increment
a_key=required step=1 if_missing="error"=
Sets _subject.a_key to a value of one higher than the previous value of _subject.a_key. Beware the new value will always be set in _subject, even if the original value was inherited by _subject. Examples: thing.<set weight=6/> thing.<increment "weight"/> returns 7 thing.weight returns 7 thing.<increment "weight" 2/> returns 9 thing.weight returns 9 _subject defaults to the local environment. Example: <set bbb=4> <increment "bbb"/> bbb </> returns 5 increment takes an arg 'if_missing' that determines what to do if the key is not present. The default value, 'error' causes increment to error. 'create' causes the key to be created with a value of zero. It will then be incremented by the value of the 'step' argument as usual. Example: <increment "foo"/>
<inherit_field_order />
When you create a subclass, you may want to be able to create instances
of it using the by_position argument order of the parent of the class
with the new fields of the subclass on the end.
Example:
<defclass boat weight=200 hull_length=16>
<defclass canoe number_of_seats=2/>
</defclass>
<boat.canoe 4/>.number_of_seats returns 4
<boat.canoe 4/>.weight returns 200 but can't be initialized to another number via
by position arguments to the constructor.
<defclass boat weight=200 hull_length=16>
<defclass canoe number_of_seats=2>
_new_object.<inherit_field_order/>
</defclass>
</defclass>
<boat.canoe 350 18 4/>.weight returns 350
<boat.canoe 350 18 4/>.hull_length returns 18
<boat.canoe 350 18 4/>.number_of_seats returns 4<init />
If you want all of the KIDS of a class to have an init method run on them when
they are created, then define an init method in the body like so:
par.<defclass kid color="red" >
<defmethod init>
<do_stuff />
_new_object
</defmethod>
</defclass>
The init method takes no arguments. While the code in the init method is being executing,
the local variable "_new_object" will be bound to an object whose parent is the
defclass object and whose fields are the arguments passed in to the constuction call.
For example: in the call <boat hull_color="blue"/>,
while the body of the init method for boat is being run, "_new_object" will
be bound to an object whose parent is boat that has one additional field,
"hull_color" whose value is "blue".
A defclass needn't have an init method but if there is one,
then it will be called and the value of the last form in it will be returned.
So for the above example, <kid/> will cause the execution of <do_stuff />
and will return a new object who's parent is the "kid" object.
Usually the init method is called automatically as a consequence of calling
the constructor of a class, ie <kid/> will cause kind.init to be called.
However, sometimes you need to call an init method explicitly, such as when
an init method for a subclass wants to call the init method for a superclass.
When calling the init method explicitly, you must pass in a value for _new_object
so that the _new_object local variable will be bound within the explicitly-called
init method.
Example:
par.<defclass kid color="red" >
<defmethod init>
par.<init _new_object=_new_object/>
_new_object
</defmethod>
</defclass>
Normally the contained init method is not run on the object being created in a call to defclass.
However, if you want the init method called on the new object being created with the defclass,
as well as each subobject of kid,
then you must explicitly call the init method after you define it like so:
par.<defclass kid color="red" >
<defmethod init>
<do_stuff />
_new_object
</defmethod>
_new_object.<init _new_object=_new_object/>
</defclass>
Within the body of the init, you can modify the new object however you want.
Here's an example of adding a field to the new object with a key of "weight" and
a value of 37.
_new_object.<set weight=97/>
The value returned from defclass will be the new object being defined,
which is not necessarily the value of the last expression in the body of a defclass call.
However when we are creating a child of an object made with defclass,
and the defclass has an init method, the value of a call like <kid/>
will be the value returned by the init method.
In the above example, since "_new_object" is the last expression in the init method,
(as is the usual case) the new object is returned. But we can actually return
anything we want from an init method.
An init method can actually return whatever you choose so that "instances"
of an object need not bear any relationship to the object. This is rarely done,
but possible.
Within the init method, _subject will be bound only if there is a left-hand subject
to the call to the constructor:
Examples:
<defclass boat> <defmethod init> _subject </> </defclass>
975.<<do boat/>/> returns 975
<defclass boat> <defmethod init> _subject </> </defclass>
<boat/> Errors because _subject within the init method body is unbound.
If there is no init method for a class, then the new object is returned from a call like <kid/>
There are several utility methods that are often called from within init.
- parent_init to call the init method of the class that is the parent of
the class being defined.
- cache_instance to cache the instance inside the 'of' field of the class
- copy_down to copy fields from the class into the instance.
See also: thing.defclass, "subject and new_object"
parent_init, cache_instance, copy_down.<insert at_key="end" rest=required />
Inserts one or more elements into the vector of "_subject" at at_key. Returns the subject, or in the case that the subject is a string, returns a new string with the inserted chars. Example: <vector 10 11 12/>.<insert at_key=1 88/> returns 1 <vector 10 11 12/>.<insert at_key=1 88 99 /> returns 1 <vector 10 11 12/>.<insert at_key=1 rest=<vector 88 99/> /> returns 1 Giving insert an explicit rest argument effectively "appends" the rest vector onto the end of "_subject". If at_key is "end", add the new elements at the end of the vector, i.e. the "push" operation. at_key is optional and insert takes rest args so at_key must be explicitly named if used. If at_key is not used, it defaults to "end". Example: <set a=<vector 10 11 12/>> a.<insert 13/> a </set> returns <vector 10 11 12 13/> If _subject is a string then the rest args are expected to be chars or strings. A new string is made containing the subject chars with the rest chars inserted at the proper location: Examples: "abc".<insert "def"/> returns "abcdef" "abc".<insert "def" "gh"/> returns "abcdefgh" "abc".<insert "def" "gh" at_key=1/> returns "adefghbc" "abc".<insert <char "d"/>/> returns "abcd" "abc".<insert rest=<vector <char "d"/> <char "e"/> />/> returns "abcde" You can also have a subject of a file and give string args to be inserted into the content of the file at the at_key position.
<inspect label="Starting Datum"=string window_title="Water Inspector"=string />
The Inspector lets you:
Browse documentation
Browse the object hierarchy
Browse every field of every object associated with the hierarchy recursively
Browse temporary objects not connected to the hierarchy
Search for field keys and documentation containing a particular string
See a stack report of called methods
THE FIELDS PANE
Each line of text in the lower (largest) pane represents a field of
the object being inspected.
When you click on a field, its short representation will move to the
"history" pane above, and the main pane will contain the fields of the object which was
the value of the field you clicked on. If the object being inspected is a string,
just the string will be shown. The left-hand label for the pane will change from
"Fields" to "String". You can inspect the individual characters of the string
by clicking right for a menu of operations.
THE HISTORY PANE
The upper pane shows a list of recently inspected objects. One of them will be selected
to show which object in the histor pane current has its fields shown in the fields pane.
You can select any object in the history pane to re-inspect it.
FILTERING
The inspector contains a number of check boxes at the top to filter in (or out)
various kinds of objects.
To browse just the object hierarchy, uncheck all check boxes except "defclass".
You will see only those objects that have an object ID (_id) whose value
is the same as the name of a field in their first parent whose value is the object.
The "containing" type-in control at the top of the Inspector let's you see only those
field keys or strings that contain the typed-in text. For example,
if you want to find all the documentation about "_new_object",
type in: _new_object into the control and hit return. You can further restrict what
is displayed by unchecking some of the "Show" checkboxes.
DOCUMENTATION
The inspector is used for reading documentation since documentation is stored
in fields of objects just like all other values.
Reference documentation for many objects and methods is stored in a field meta_field
of "_f_doc". Check the "doc" checkbox to show these field meta_fields.
Browse thing.reference_manual for a list of the most important documentation.
Users can write their own documentation using the method "doc_field".
CALLING INSPECT
You can call the 'inspect' method from code which is particularly effective for inspecting
intermediate data.
Inspect pops up a window and allows you to navigate down the various field values
of "_subject". From any inspect window you can inspect thing and therefore every
object connected to the tree. inspect returns "_subject" so that you can take an
existing path such as:
foo.bar.baz
and insert into it:
foo.bar.<inspect/>.baz and it will return exactly the same thing with the side-effect
of popping up an inspect window on the value of bar.
HELP
The Help menu is similar to the help menu in the Steam IDE window.
The "Help on" item behaves just slightly differently. If you are displaying
a string in the Fields pane, select a word that you want help on before choosing
"Help on". If there is no selection in the lower pane, as is always the case
when you are showing fields instead of a string, then the selection will be
derived from the selected item in the history pane.
To see the stack report of the stack at the time of the call to inspect, just
look in the previous item in the inspector history, which is labeled "Stack Report".
See also ii, iip<is rest=required= />
Returns true if _view and all the rest args are the same object. Returns false otherwise.
<is_a ancestor_maybe=required same=false=boolean lookup=true=boolean />
If "_subject" has a parent that is the value of the ancestor_maybe argument, true is returned. If the "same" argument is true, then true is also returned if _subject is the same object as ancestor_maybe. The default value for "same" is false. If the "lookup" argument is true, then true is also returned if "_subject" has an ancestor that is the same as ancestor_maybe. The default value for "lookup" is true. If is_a doesn't return true, it returns false. Examples: 3.<is_a number/> returns true 3.<is_a 3/> returns false 3.<is_a 3 same=true/> returns true
<is_content_a_vector_of_instances />
heuristic: returns true if element looks like it
contains a vector of items
Treat the content as a vector of objects if:
1. content='ek_code' (automatic)
2. has attribute type="array"
3. the tagname matches the vector_of type: <vector_of field/>, or
5. If the elements all have the same tag name, or
4. there are two elements with the same tag name
6. the container tagname is plural (fields)<is_not object=required />
Returns true if _view and all rest args are not all the same object. Returns false otherwise.
<is_settable key=required />
Returns true if the key given can be set in "_subject", returns false otherwise.
<is_sorted predicate=object_less />
If the vector fields of "_subject" are ordered according to the predicate of the first argument,
then the call to is_sorted returns true, otherwise it returns false.
If a vector is unordered, it can be ordered using "sort".
is_sorted just tests to see if the vector actually is sorted.
It is much faster than sort.
The sorting predicate defaults to object_less.
Examples:
<vector 15 16 17/>.<is_sorted/> returns true
<vector 94 16 17/>.<is_sorted/> returns false
<vector 94 93 92/>.<is_sorted number.more/> returns true
4.<is_sorted/> returns true because 4 is of zero length and any zero length object
is considered to be sorted regardless of predicate.
See also: sort, combine<java_env />
You can execute java source code using java_env which provides a
water interface to the Java Bean Shell.
Examples:
<java_env/> makes an instance of a Java Bean Shell
<java_env a=2 b=3.<plus 4/> /> make an instance of a Java Bean Shell
and initialize some local variables to values computed by Water code.
<java_env/>.<set a=2 b=3/> similar to the above except that
set can add vars to an existing instance of java_env.
<java_env/>.<set_value "foo" 22/> Similar to set except that
this allows you to set only one var. However, unlike set,
the name of that var may be computed by arbitrary Water code.
<java_env/>.<unset_vars "foo" "bar"/> Remove the bindings of
the given vars, each of which must be a string.
<java_env/>.<unset_vars/> If no arguments are passed to unset_vars,
then ALL the vars in the javs_shell instance are removed.
All of the above calls return the java shell instance being operated on.
This allows you to make paths with several of these operations like so:
<set js=<java_env/>/>
js.<unset_vars/>.<set a=4 b=17/>
Above you can reuse a java-shell but clear out its previous local
variables and add some new ones.
<java_env/>.<eval> 3 + 4;</> returns 7
<java_env a=3 b=4/>.<eval> a + b;</> returns 7
<java_env/>.<set a=3 b=4/>.<eval> a + b</> returns 7
If you want to compute the java source string to evaluate,
<java_env/>.<eval content=<force_ek_code "3".<concat " + 4"/>/>/> returns 7
Note that this syntax of using square brackets will change in
an upcoming release of Water.From Water you can access a lot of the functionality of Java.
Methods and Constructors
You can get a java method or constructor using get_java_method.
See its extensive documentation for not just getting a method or constructor,
but calling it as well.
Get
You can get the value of a field in a Java instance using the
same syntax as Water (and Java in this case)
some_object.a_field
If a field is not in the java instance, null will be returned as is the convention
in Water. This will enable searching the parent of the java object
(which is a Water object named thing.java_object) so that methods that operate
on all objects (Water or Java) can be found. You can explicitly check to see if
a Java object has a field using the method 'has'.
See also: get
Set Field Value
You can use the method "set" to set field values of Java objects, just like
you use it for Water object.
The method "set" works on both Java and Water objects as well.
Java Classes
Use get_java_class to get the class of an object.
To get a Java class from its name, use:
<<get_java_method "Class" "forName" "String"/> "java.util.Date"/>
To get the value of a static field within a class, use get_java_class_field_value
You can use the java_env object to execute an arbitrary string of java source code.
See also: get_java_method, get_java_class, get_java_class_field_value, set, get<join separator=" " />
Create a string by concatenating the elements of '_subject' which is expected to be a vector or supervector. Elements of the vector are printed using to_html and are separated by the "separator" parameter which defaults to ", ". A zero length "_subject" will return "". A one length "_subject" will have just the one item in it with no separator. Example: <vector "hey" "baby"/>.<join/> returns "hey, baby" <vector 4 5 6/>.<join separator=":"/> returns "4:5:6"
<key_of item=required case_sensitive=true start=0 end=null include=vector_key returns="first" />
This functionality is like Java's indexOf method but can work on non-vectors as well as vectors,
returning the key of a field that has a given value.
Unlike Java's indexOf method, key_of uses "==" comparison instead of "equals" comparison.
That means the matched values must be THE same object, not just have the same parts.
Returns the integer position of item in the vector of "_subject",
or false if item is not in "_subject".
Example:
<vector 97 98 99/>.<key_of 98/> returns 1
<vector 97 98 99/>.<key_of 96/> returns false
key_of can be used to perform the "member" operation, i.e.
if the argument is a member of the vector of "_subject", then non-false will
be returned, otherwise false will be returned.
You can limit the section of '_subject' searched by supplying a 'start' and an 'end' index.
'start' defaults to 0 and 'end' defaults to null which means the length of '_subject'.
'start' is inclusive, 'end' is exclusive.
If 'end' is more than the length of '_subject' then the length of '_subject' is used for 'end'.
The 'include' parameter determines which fields of '_subject' are looked at for value matches.
It is similar to the 'include' parameter in 'for_each'.
Its default value is vector_key which means that just the non-negative integer
fields are looked at.
If you give an include of 'string_key' you can look at the user fields:
<thing bcolor="red" weight=235/>.<key_of "red" include=string_key/> returns "bcolor"
<thing bcolor="red" weight=235/>.<key_of "weight" include=string_key/> returns "weight"
See for_each for additional documentation on using 'include'.
The 'returns' parameter determines the order of the search and what values are returned.
There are three legal values to this parameter:
'first' return the key of the first field that you find that matches the item value.
'last' return the key of the last field that you find that matches the item value.
This may be used only when include=vector_key. It starts the search from the
highest index field. The highest index field name that matches is returned.
'all' return a vector of all the fields that match. When '_subject' is a vector,
the returned vector will contain ascending integers.
If there are no matches, an empty vector will be returned.
The case_sensitive parameter determines how the comparison between a field value and
the item search for is made. If case_sensitive is false, the comparison between
two strings is made in a case_insensitive way. The default is true.
Examples:
<vector "a" "b" "a"/>.<key_of "a" returns="last"/> returns 2
<thing bcolor="red" fcolor="Red" acolor="green"/>.
<key_of "red" include=string_key returns="all"/> returns <vector "bcolor"/>
<thing bcolor="red" fcolor="Red" acolor="green"/>.
<key_of "red" include=string_key returns="all" case_sensitive=false/>
returns <vector "fcolor" "bcolor"/>
See also string.key_of, for_each<keys include=regular_key />
Returns a vector of the names of the fields in "_subject". If "_subject" is a java object, only the names of public class & instance variables are returned but it contains all the field names including those inherited from other classes. The actual fields returned will be filtered by the method that is the value of the include argument. The include method is called with the potential "key" as the _subject. If that call returns true, then the key is included in the returned vector. The returned keys are filtered by the "include" argument. It is called with each key as the subject. If the call returns true, the key is included in the output vector. If the returned keys include vector_keys, those keys will be at the front of the returned vector in numerical order.
<last index_from_end=1=number.integer returns="first"=string />
"_subject" is expected to be a java vector, a supervector, or a string. If it is not, error. If the "_subject" has zero size, error. Otherwise, With no argument passed, it returns the last element of "_subject". With an argument of 2 it returns the 2nd to the last element. With an argument of 3 it returns the 2nd to the last element, etc. The default value for the first argument is 1. If the "returns" argument is "all", then the subvector of the last n items in the _subject are returned. The default value for "returns" is "first" meaning just return the one item indicated by the first argument. Out of range value of index_from_end causes an error. Examples: <vector 100 200 300/>.<last/> returns 300 <vector 100 200 300/>.<last 2/> returns 200 "abcdef".<last 3 returns="all"/> "def"
<length />
Returns an integer of the size of the object. For primitives (booleans, characters, numbers) returns 0. For Strings and java vectors, returns the length. For Records, returns a non-negative number that's the lowest integer for which there's no key of that integer. Usually when you've got a record and some integer named fields, you'll have consecutive integers up from zero like so: 0, 1, 2, 3 in which case length would return 4. But if you had integer fields of: 0, 1, 3, 4, length would return 2. See also remove.
<lookup_meta_field key=required meta_field_name=required find_in_field_object_only=false=boolean if_missing="error" default=null />
Returns the meta_field in object "_subject" on field of name "key" with meta_field name of "meta_field_name". If find_in_field_object_only is true (the default is false), then Find the first object of "_subject" and up through its ancestors that contains a field named "key". If THAT object has an meta_field on the field of "meta_field_name" then return the value of the meta_field, otherwise return false. This feature is used when you want to make sure that the meta_field you're getting is on the very field you're looking up and not inherited from some other object. If no field of the given name is found, the not_found value is returned.
If the folder already exists, just return true,
otherwise an attempt to create the folder on disk is made
and if successful returns true, else returns false.
Note that parent folders of the folder being made will be
created as needed.
To "make" a file , you do a_file.<set content="initial contents"/><make_fields_from_content new_key_source_field="_element_name" existing_field_policy="keep"=string multiple_values_policy="first"=string />
This method is useful in turning the content of an XML object into
easily accessed named fields within the object.
make_fields_from_content creates new fields in "_subject" whose values are the elements of the vector
that is the value of the content field of "_subject".
The name of each field is dependent on the value of the argument
new_key_source_field
If the argument is "_element_name" (the default) then the name of each new field is
the name of the parent of the value of the new field.
If the argument is non-null, then the name of the new field will be the
value of the attribute of that name within the element of content being processed.
If there is no such attribute then that element is ignored. So if you only want to
make as proper fields those content elements that have a "name" attribute,
then use "name" as the new_key_source_field and the others will be ignored.
"_subject" is returned, after it has been modified.
Example:
<thing><plane name="chapter11"/><boat name="mygirl"/></thing>.
<make_fields_from_content/>
Returns "_subject" which now looks like:
<thing plane=<plane name="chapter11"/> boat=<boat name="mygirl"/> >
<plane name="chapter11"/>
<boat name="mygirl"/>
</thing>
The content field is left in tact, though often user code will want to
remove it as it will now carry redundant information.
Example:
<thing><plane name="chapter11"/><boat name="mygirl"/></thing>.
<make_fields_from_content/>.<remove "content"/>
Using the default for new_key_source_field presumes that there is only
one object of each type in the content of "_subject". If there is more than one, the last one
will be the one with the field_value. The others will be lost.
You may, however, name the new fields by the value of a designated field
within each element of content.
Example:
<thing><boat name="chapter11"/><boat name="mygirl"/></thing>.
<make_fields_from_content "name"/>
Returns "_subject" which now looks like:
<thing chapter11=<plane name="chapter11"/> mygirl=<boat name="mygirl"/> >
<boat name="chapter11"/>
<boat name="mygirl"/>
</thing>
Note that just because you are using a non-null new_key_source_field
does not mean that all the elements of content must be of the same type.
If an element does NOT have a field of the designated name, then it is
ignored and not made into a field of "_subject".
The two parameters existing_field_policy and multiple_values_policy interact to
give the caller lots of flexibility over handling unusual situations.
existing_field_policy (one of "keep", "replace", "error")
and multiple_values_policy (one of "first", "last", "all")
If you have a situation such as:
<thing color="red">
<color value="blue"/>
<color value="gray"/>
</>.<make_fields_from_content/>
Then when make_fields_from_content is about to make a field
named color to hold <color value="blue"/>, there is a conflict with
the color field already in the object holding "red". When there is an existing
field of the same name, the value of existing_field_policy determines what happens.
Its behavior, however, is modified by the multiple_values_policy, which describes
what to do when there are more than one elements in the content that are to be made
into the same field.
"keep" (the default existing_field_policy)
Generally keep the existing value but modify that with the multiple_values_policy
described below:
"first" (the default multiple_values_policy)
The value of the existing field will remain as "red".
Since "first" is the default multiple_values_policy,
"keep" "first" is the default policy.
"last" The new value is <color value="gray"/>
"all" The new value is <vector "red" <color value="blue"/> <color value="gray"/> />
"keep" "all" preserves all values, with the existing value (if any) becoming the
first item of the vector.
"replace" Set the value of the existing field to the new value, getting rid of the old value,
but exactly which new value will depend on the value of multiple_values_policy
"first" The new value is <color value="blue"/>
"last" The new value is <color value="gray"/>
Note that "last" behaves the same for
existing_field_policy of "keep" and "replace"
"all" The new value is <vector <color value="blue"/> <color value="gray"/> />
"error" Throw an error if there is an existing field named the same as a field from the content.
Otherwise, for multiple_values_policy of:
"first" set the field to the first value from the content.
"last" set the field to the last value from the content.
"all" set the field to a vector of all the values from the content.
Note that if there is no existing field and there is only one field in the content with
a given field name then the value in the content will be made into the new value
in the field. The only difference the policies make is that if the multiple_values_policy
is "all", the value in the field will be a vector whose only element is the value from the content
whereas if the multiple_values_policy is not "all", the value from the content will be the
value in the new field.<merge_down_into original=required include=return_true=defmethod limit=optional include_limit=true />
Very similar to copy except that a new object is not made. The fields of the argument 'original' and its ancestors are copied into '_subject'. Thus '_subject' might have a different parent than original. '_subject' is returned.
Any field in any object may have any number of "meta_fields". A meta_field is meant to contain meta_data about the field. The system uses meta_fields for storing documentation, field types, and execution kinds amongst other things. Users can stick any kind of data they like in a meta_field. You can set a meta_field on a field like so: Example: thing.<set my_favorite_color_f_why="because green is the color of oxygen producing organisms."/> We can get back the meta_field via: thing.my_favorite_color_f_why Here presumably there's a field on the thing object named my_favorite_color whose value is "green". But its value could really be anything or in fact the field could not exist at all. The meta_field system does not check these constraints. Usually the field name being annotated is a string and the meta_field name is a string too. In such cases the meta_field is stored in the object with a field name of key + "_f_" + meta_field_name. But you can also annotate fields of any type and use a meta_field name of any type. These values can also be computed if you like. In such cases use the methods: set_field and get. To create a field key referencing a meta field, use, for example: <field_key "acolor" "doc"/> See also field_key, lookup_meta_field field
<meta_key />
Returns true if _subject is a meta key, ie a key that contains meta information about
another key. Otherwise returns false. These keys are strings of the format:
acolor_f_transparent
starting with the name of the key being described, "_f_", and ending with
the meta-info name.<datetime 2002 3 24/>.<mmm_d_yyyy/> returns "Mar 24, 2002"
Returns false for a subject that is a meta key and true for everything else. See also: meta_key
<non_regular_key />
Returns false for a subject that is a regular_key and true for everything else. See also: regular_key
<non_string_key />
Returns false for string_keys and true for everything else. See also: string_key
<non_system_key />
Returns true for all '_subject' that are not system field keys. such as non-system strings, and keys that are not strings. See also: system_key
<non_vector_key />
Returns false if _subject is a vector key and true otherwise. See also: vector_key
<normalize instance=optional namespace=optional />
Takes a data object in any XML 1.0 encoding style and transforms it to ConciseXML data, removing any ambiguities in the process. Normalize uses a set of rules and heuristics for the transformation. Normalize is called on instance data (ek_data or symbols) or a vector of instance data. Converting XML data into instances of Water classes: A common scenario would be to convert an incoming string in some XML 1.0 format style, and transform it to unambiguous Water objects. <Example '<person first="Mike"/>'.<execute <defclass person first/> /> <person first="Mike"/> /> Assumptions: o The XML data represents instance data, not logic or method calls o When the content argument is used, it generally represents fields of the object o Only works for pure data -- no mixed content, for example, hypertext. o Different encoding styles can be used for different tags o Attributes are converted into objects if possible.
<not object=optional />
If not is passed an argument:
If the argument is false, return true, otherwise return false.
If not is not passed an argument,
If "_subject" is false, return true, otherwise return false.
Examples:
false.<not/> returns true
true.<not/> returns false
2.<not/> returns false
<not true/> returns false
<not false/> returns true
true.<not false/> returns true because if an argument is present,
"_subject" is ignored.Unlike many languages, Water has distinct values for:
null represented as null, used to mean "empty"
If you execute my_boat.color and you don't have a color for my_boat,
but you don't want it inherit the default color from the parent of my_boat,
assign my_ boat a color of null, and that's what you'll get when
you execute my_boat.color.
false represented as false. A boolean whose opposite is true.
When the result of a condition in a clause to IF executes to false,
the clause will fail. If the clause executes to anything else
that value will be treated as true.
AND and OR have equal behavior.
the empty string represented as "" A string of zero length.
an empty vector represented as <vector/> A vector of zero length.
Unlike the empty string, there can be many different empty vectors.
zero represented as 0, The least non-negative integer.
This is NOT equivalent to false.
if_missing methods that access field values directly,
"get" takes an "if_missing"
optional argument that specific to either error, or return a
default value. See get.number.<divide arg1=optional=number arg2=optional=number />
Divide can be passed Integers and Floats. It always returns a Float. 12.<divide 3/> returns 4.0 <divide 12 3/> returns 4.0 If divide is only passed one number, it returns its reciprocal, i.e. one divided by the number passed in. <divide 4/> returns 0.25
number.<float.is_nan />
if argument is a "NaN", i.e. it is the "not a number error value" then return true. empty text INPUT is a NaN rather than what it should be, the empty string.
number.<float.is_nan />
if argument is a "NaN", i.e. it is the "not a number error value" then return true. empty text INPUT is a NaN rather than what it should be, the empty string.
number.<float.random_number min=0=number include_min=true=boolean include_max=false=boolean />
Example: 5.0<random_number 1.0/> returns a float between 1.0 and 5.0 excluding 5.0
5.<random_number include_min=true include_max=true/>
min defaults to 0.0, so this will return a float between
0.0 and 5.0 inclusive.number.<float.random_number min=0=number include_min=true=boolean include_max=false=boolean />
Example: 5.0<random_number 1.0/> returns a float between 1.0 and 5.0 excluding 5.0
5.<random_number include_min=true include_max=true/>
min defaults to 0.0, so this will return a float between
0.0 and 5.0 inclusive.number.<integer.random_instance />
If subject is 'integer', returns 0 or 1 with equal probability.
else if subject is an integer, returns a random integer less than the
subject and greater than or equal to zero.
Example: integer.<random_instance/> returns 0 or 1
3.<random_instance/> returns 0, 1, or 2
See also: integer.random_number boolean.random_instancenumber.<integer.random_instance />
If subject is 'integer', returns 0 or 1 with equal probability.
else if subject is an integer, returns a random integer less than the
subject and greater than or equal to zero.
Example: integer.<random_instance/> returns 0 or 1
3.<random_instance/> returns 0, 1, or 2
See also: integer.random_number boolean.random_instancenumber.<integer.random_number min=0=number include_min=true=boolean include_max=false=boolean />
Example: 5.<random_number 1/> returns 1, 2, 3, or 4
because include_max defaults to false and
include_min defaults to true
5.<random_number include_min=true include_max=true/>
min defaults to 0, so this will return 0, 1, 2, 3, 4 or 5.
See also: float.random_numbernumber.<integer.random_number min=0=number include_min=true=boolean include_max=false=boolean />
Example: 5.<random_number 1/> returns 1, 2, 3, or 4
because include_max defaults to false and
include_min defaults to true
5.<random_number include_min=true include_max=true/>
min defaults to 0, so this will return 0, 1, 2, 3, 4 or 5.
See also: float.random_numbernumber.<integer.to_hex_string min_char_count=1 />
returns a string of the hexidecimal representation of '_subject' which must be an integer. The returned string will have at least min_char_count characters padded on the left with zeros if need be. 13.<to_hex_string/> returns "D"
number.<integer.to_hex_string min_char_count=1 />
returns a string of the hexidecimal representation of '_subject' which must be an integer. The returned string will have at least min_char_count characters padded on the left with zeros if need be. 13.<to_hex_string/> returns "D"
number.<less rest=required=number />
Returns true if _subject is less than the argument. Example: 2.<less 3/> returns true.
number.<less_or_equal rest=required=number />
Returns true if _subject is less than or equal to the argument. Example: 2.<less_or_equal 3/> returns true.
number.<maximum rest=required />
Return the argument having the greatest numerical value.
Example:
5.<maximum 2 7 3/> returns 7
<set scores=<vector 650 500 800/>>
0.<maximum rest=scores/>
</set> returns 800number.<minimum rest=required />
Return the argument having the least numerical value.
Example:
5.<minimum 2 7 3/> returns 2
<set scores=<vector 650 500 800/>>
1000.<minimum rest=scores/>
</set> returns 500number.<minus arg1=optional=number arg2=optional=number />
Examples: 5.<minus 2/> returns 3 5.6.<minus 0.2/> returns 5.4 <minus 5 3/> returns 2 If minus is passed only one number it negates it. <minus 3/> returns -3 <minus -2/> returns 2
number.<more rest=required=number />
Returns true if _subject is more than the argument. Example: 3.<more 2/> returns true.
number.<more_or_equal rest=required=number />
Returns true if _subject is more than or equal to the argument. Example: 3.<less_or_equal 2/> returns true.
number.<plus rest=required=number />
Plus can add up any number of arguments: 1.<plus 2 3/> returns 6 1.2.<plus 0.3/> returns 1.5 <set foo=<vector 2 3 4/> /> 0.<plus rest=foo/> returns 9 Plus has a default subject of 0 <plus 2 3/> returns 5
number.<random_number_normal standard_deviation=required=number />
Produces a gaussian distributed series of floats.
The subject is the mean, i.e. the average number.
The standard-deviation specifies how different the result is likely to
be from the mean.
If you have a mean of 100 and a standard deviation of 10, then
The average of the produced numbers will be 100.
68% of the produced numbers will be between 90 and 110.
95% of the produced numbers will be between 80 and 120.
99% of the produced numbers will be between 70 and 130.
Example: 100.<random_number_normal 10/> will return a
float between 90 and 110 about 68% of the time.number.<remainder rest=required=number />
Returns the remainder of dividing the integer in _subject by the integers in rest. Example: 7.<remainder 2/> returns 1
number.<times rest=required=number />
Examples: 2.<times 3/> returns 6 times can multiply any number of arguments: 2.<times 3 4/> returns 24 0.5.<times 2/> returns 1.0 <times 3 4/> returns 12 Times has a default subject of 1 <times 2 3/> returns 6 <times rest=<vector 2 3 4/>/> returns 24
<object_less obj=required= a_context=null />
returns true if - Both "_subject" and obj are numbers and "_subject" is less than obj or if - "_subject" is a number and obj isn't or if - printing both "_subject" and obj using to_html produces strings such that the string for "_subject" is alphabetically before the string for obj. otherwise returns false. 'ascending' is another name for object_less. See also object_more, sort
<object_more obj=required= a_context=null />
returns true if - Both "_subject" and obj are numbers and "_subject" is more than obj or if - "obj" is a number and obj isn't or if - printing both "_subject" and obj using to_html produces strings such that the string for "obj" is alphabetically before the string for "_subject". otherwise returns false. 'descending' is another name for object_less. See also object_less, sort
Water has a simple but powerful object system. If you are familiar with
other object systems you are advised to read the text below especially carefully
since Water's object system differs from and is much more flexible than
object systems of other popular languages.
A Water object is a collection of fields, each of which has a key and a value.
The value may be any type of object, though you can restrict this in
certain ways. The key can be any type of object as well. Most keys are
strings naming the field. For example:
<thing weight=125 color="blond"/> makes an object with two fields whose
keys are "weight" and "color" with respective values of the integer 125
and the string "blond".
If you give an object keys of consecutive integers starting
from zero, you implement a one dimensional array.
For example <thing 0="Monday" 1="Tuesday" 3="Wednesday"/> makes an
object with three fields keyed with 0, 1 and 2.
You can use integers just like any other keys and in fact can have
an object that has both integer keys and string keys. This is often
useful for making vectors that have "extra data" attached to them.
For example: <thing 0="Monday" 1="Tuesday" weather="rain"/>
Keys may also be other objects so a Water object
can be used as a conventional record or structure with named parts,
a vector with numbered parts, or a hash table that holds a mapping between
pairs of arbitrary objects.
Water has strings, but they can be treated like any other object.
Think of a string as a vector of characters. So the field 'keys' of a string
are the integers 0 through one less than the size of the string, and
the field values of a string are its characters.
One particularly important field is the '_parent' field.
All objects except 'thing', the root object, have a parent field.
When a lookup for a field within an object occurs, if the field key
is not in the object looked up, the system looks into the value of
the _parent field for the key being looked up. If the key is not found
in the parent, the parent's parent is looked in, and so on upward.
This is called inheritance.
Most object systems are "class-instance" object systems where there's
a big difference between a class and an instance. In Water there isn't.
Water does has a construct called defclass, but it does little more
than create an object. There's really not much of a difference between a class
and an instance. In fact you can use any object as a "class" simply by making
that object be the parent of another object. In effect, an object becomes a
class for a particular instance if it is the parent of that instance.
"Classness" does not have to do with the representation of the object itself,
but rather in the role that it is used in. A single object can be used in various places
and serve different roles if that's desirable.
Examples:
thing a variable that has the value of the root object
<thing/> returns an object that has only one field, _parent, which
has the value of thing. The returned object is an instance of thing.
<thing color="red" weight=123/> returns an object with a _parent of thing,
a color field of the string "red"
and a weight field of the integer 123
<thing 0="red" 1="white" 2="blue"/> returns an object
that acts as a vector of three strings.
<vector "red" "white" "blue"/> similar to above but easier to type.
Also the parent of the returned object is a special object named
"vector" which can only have integer keyed fields
that are consecutive starting from zero.
<thing color="red" 0="white"/> returns an object with a _parent of thing,
a color of "red" and a field with a key of zero and a value of "white".
<thing color="red" 0="white"/>.color returns "red"
<thing color="red" 0="white"/>.0 returns "white"
<thing color="red" 0="white"/>._parent returns thing.
We can make an object with another object as its parent like so:
<<thing weight=42 material="wood"/> weight=99/>.weight returns 99 because
the lower object has a weight field so no need to look in the parent for
its value of weight. weight in the lower object "shadows" the value
of weight in the parent object.
<<thing weight=42 material="wood"/> weight=99/>.material returns "wood" because
the lower object does not have a material field so we have to get the
value from the parent object.
When lookup goes all the way up to 'thing' and still doesn't find
the key, then lookup looks in a couple more places. One is the
hypertext object, so that all HTML tags are available without qualifying their
names with a special subject.
The other is the "promoted_environment", an object that contains
keys and values that are universally available. A developer
can add an object to the promoted_environment by calling the
'promote_object' method.
Fields may be added (or existing fields modified), using 'set
and fields may be removed using 'remove'.
Note: the ability to add and remove field from objects after they are created
makes Water objects more dynamic than in most other object systems.
You can also make a field have an 'active_value' whereby code of
your choice is executed when the field is referenced.
Methods are also objects. They are typically stored in fields of their
"class" or anywhere else you like and may be passed as arguments
as well as created dynamically during the running of your program.
The primitive objects in Water are:
boolean, integer, float, char, null.
Numerous higher level objects like string, vector, uri, server, etc.
add a great deal of functionality, yet obey the same basic rules.
We call Water's object system a "Multi-Role Object System" because
the same object may be used for different purposes. For example,
an object can serve as an instance, a class, a type, etc.
Furthermore, objects are used for all of the language's data including
methods, vectors, strings, integers and
numerous other data structures.
The same syntax for creating objects,
referencing fields and setting fields is used regardless of the type of object.
Many languages that have object systems don't use objects for everything.
Java is half-object oriented for example. Smalltalk uses objects for everything,
but it has a class-instance object system so you can't use an "instance"
as the "parent" of another object.
Once an object is created, it remains 'alive' as long as you can reference it
through some variable or field of an object that is accessible. If an object
is no longer accessible, the garbage collector will reclaim its storage.
You never explicitly de-allocate objects, though if you remove the last field
that's pointing to an object or set the last field to some other value,
the old value of the field will be garbage collected. Water is no different
than Java or Lisp in this regard.
See also: syntax, defclass, defmethod, thing, promote_object,
get, set, remove, active_valueCreates a regex string that indicates that a match of any of the arguments
will be a match. This is the "or" functionality.
Returns a string of each argument separated by a vertical bar.
You can pass any number or arguments either as unnamed attributes or as
expressions in the content. All are evaluated and expected to result in strings.Say you've got a method <defmethod foo a=2 b=3> x </defmethod>
If you want to call this method with just the "a" argument and let "b" default,
it is easy: <foo 22/>
But what if you want to call this method with just the "b" argument and let "a" default?
You can pass by key i.e. <foo b=33/> .
Another way to do it where you don't have to specify parameter names is:
<foo optional 33/>
The "optional" says use the default value for the first argument, and
apply 3 to the 2nd argument.
optional is just a field in thing whose value is a unique value, the "optional" value.
If you define a method like so:
<defmethod foo a=optional> </> then a will be an optional parameter and if it is not
passed in, its value will be the "optional" value.
You can test that like so
<defmethod foo a=optional> <if> a.<is optional/> do some stuff </if> </defmethod>
When you don't have a good default value for a parameter, use optional.
usually it is the case the if the value of a parameter is 'optional' within
the method, then it wasn't passed in, however, if we've got
a foo defined like above and a call of <foo optional/> you can't tell
whether the arg was passed or not.
We can pass a variable whose value is optional to another method, say:
<defmethod foo a=optional> <bar a/> </>
<defmethod bar b=3> b </>
<foo 4/> returns 4 as is the normal case.
<foo/> returns 3 since bar was called with a value for b of 'optional'.
<foo optional/> returns 3 since a is optional and
bar was called with a value for b of 'optional'.
Say you have <defmethod bar a> a </> where a is a required arg.
Calling <bar/> errors since the required argument is not passed.
<bar optional/> binds a to the 'optional' value.
This is what allows tests like x.<is optional/> to work because the argument
to 'is' is required.
For the purposes of automatic type checking, 'optional' is considered to be of any type.
When explicitly calling is_type_for, however, the 'optional' value does not pass
automatically.<output target="_not_supplied" tag="_not_supplied" attr="_not_supplied" preposition="_not_supplied" printer=to_html />
_subject.<output target tag attr preposition/> In the normal case, the value of the last expression is output to the screen, completely replacing the previous page. However, sometimes you need to update only a section of the page, or create a new window. This is what 'output' is for. The data to be displayed to the screen is the '_subject' in a call to output. The location where the data is displayed is specified using four arguments: 1. target: the name of the window (or frame) for displaying the output. target="_self" by default target="all" for outputting to all windows. if no window of the given name is found, a new window is created. "target" is the same as the "target" attribute in HTML. 2. tag: the name/id of the tag, or the tagname, to send the output. tag="BODY" by default First looks for a tag with an id (or name) attribute with a value of tag. If it doesn't find it, look for a tag with a tagname of the value of tag. If neither is found, don't update anything. tag="multiple" Let's say you have a registration form displayed on the page that has fields for first_name, last_name, city, and state. You have a registration object that also has fields of the same names. You want to put the values from your registration object into the corresponding fields on the registration form without doing a screen refresh. tag="multiple" will do an output for every field of the '_subject' object. <registration first_name="Mike" last_name="Plusch"/>.<output tag="multiple"/> 3. attr: the name of the attribute of the above tag to which to send the output. attr="content" by default which will replace the content area of the tag with the new value. If attr="all" then the new data goes to a place related to the entire tag rather than some place within the tag. Thus if preposition="before" then the new data goes before the entire tag, whereas if preposition="replace" then the new data replaces the entire tag. 4. preposition: the relative location for sending the output. Specifies where the new value should go relative to the specified target, tag, and attribute. preposition="replace" by default preposition=<one_of "replace" "before" "after"/> Examples: Replace the content of the current window: <h1>hello</>.<output/> Note this is the same as not using a call to 'output' at all, i.e. just executing <h1>hello</> Put in a window named "remote_control". Create a new window if one doesn't already exist. <h1>hello</>.<output "remote_control"/> Set the contents of the tag with id "price" to "the_price". the_price.<output tag="price"/> Replace the entire tag with 'the_price' the_price.<output tag="price" attr="all"/> Merge the data of customer_A into the current page. customer_A.<output tag="multiple"/> Put the_price at the top of the current page. the_price.<output preposition="before"/> Since the default tag is "BODY" and the default attr is "content", the value of 'the_price' is inserted at the top of the content within the BODY tag. <b>new</>.<output tag="price" preposition="before"/> <h1 id="price">some content</> returns <h1 id="price"><b>new</>some content</> <b>new</>.<output tag="price" preposition="after"/> <h1 id="price">some content</> returns <h1 id="price">some content<b>new</></> Prepositions not yet supported: ontop, underneath, left, right, above, below, and around. Not yet implemented: attr="content" and preposition=integer Inserts value in the content at location of the preposition. 0 is same as "before". To replace the item in the content, use attr="content_replace".
<pad_digit />
assumes result of calling to_html is 1 or 2 digits. If its only 1, then
an extra zero is added on to the front.<parent_init />
Calls the init method on the parent class. Typically called at the top of an init method. Useful when you want the instance to be initialized according to the more general init method before running the local init method. Example: boat.<defmethod init> _new_object.<parent_init/> </> This calls the init method of boat's parent, probably something like vehicle.init Implementation: ._parent._parent.<init _new_object=_subject/> See also: defclass, cache_instance
Returns _subject to the exponent power. _subject can be either an integer or a float. exponent can be either an integer or a float. If '_subject' is an integer and the 'exponent' is a non-negative integer, an integer is returned, otherwise a float is returned. Examples: 2.<power 3/> returns 8 2.<power 0.5/> returns 1.4142135
<print />
Deprecated
Prints _subject on the java console window.
_subject can execute to any object.
The lowest level printing method is used here, similar to to_string.
Example:
123.<print/>
If you'd like to print _subject readably, use:
my_obj.<to_concise_xml/>.<print/>
The value of _subject is returned.<promote_object key=null />
Binds the subject of the call to the supplied key in the object that is the value of thing.promoted_environment making it inheritable from any object as well as available as a 'local' variable. If key is not supplied, then a key is looked for in the _id or _method_name field of the _subject. If neither of those two fields exist, error. Lookup of a symbol proceeds like this: First it is looked up in the local environment. This is where arguments to a method appear as well as variables set by calls to 'set' that have no subject, i.e. <set foo=2/> If it is not found there, it is looked up in 'thing'. If it is not found there, it is looked up in the 'hypertext' object, so that all HTML tags are available. If it is not found there, it is looked up in the promoted_environment. Finally if it is not found there, error. Water initialises the promoted_environment to have a few very common objects that naturally live somewhere below thing but are useful to have available without having to specify where they live. float, integer, plus, minus, times, divide are some of them. Inspect thing.promoted_environment to see the complete list. See also: _if_missing_method
<push_onto_field the_key=required rest=required />
Pushes the values in rest onto the vector that's expected to be in "_subject".<get the_key/> If "_subject" has no such field, it is created and set to a new vector of the items in rest. If "_subject" has such a field and the field contains a value other than a vector or a record, then it can't be pushed onto and an error is thrown. Returns the modified vector.
If you want a subpattern to appear in the source string just once, don't
wrap the pattern in a quantity tag, otherwise do.
Quantity takes a min and max number of times for the quantity to appear.
max must be equal to or more than min.
When min and max are the same it means match that exact number of times only.
If max is the string "infinity", then the number of times matched is
min or more.
The subpattern to match is indicated in the content of a call to quantity.
Example:
"abcabcabc".<matches <pattern> <pattern.quantity 2 4> "ab" "c" </> </> />
Returns true because there are 3 "abc"s in the source and the pattern specifies
that if we have 2, 3 or 4 "abc"s, there will be a match.
When greedy is false, only min-max values of:
0 1,
0 "infinity",
1 "infinity"
are supported
Quantity can take subpatterns either as rest args, in the content, or both.
See also zero_or_one, zero_or_more, one_or_more<random_field_key include=regular_key />
Returns a field key in the subject. Example: <vector "yes" "no"/>.<random_field_key/> returns 0 or 1 See also: random_field_value
<random_field_value include=regular_key />
Returns a field value in the subject. Example: <vector "yes" "no"/>.<random_field_value/> returns "yes" or "no". See also: random_field_key
<random_instance />
Tries hard to create a random instance of the subject. Create a new object whose parent is the subject. If the subject is a record object, the new object will have the same field keys as the subject. The value of each field will be the value of calling random_instance on the type of each field. If the field does not have a declared type, 'string' will be used instead.
<regular_key />
Returns true for a key that is a string_key or a vector_key
and false for everything else, i.e. system_key and meta_key.
regular_keys are the normal keys, i.e. the non-negative integer
keys of a vector or supervector, as well as the keys that are strings
and not system keys ie the normal keys you make in an object.
See also: non_regular_key, string_key, vector_key, system_key, meta_key,
and all the corresponding "non_" methods.<remove include=return_false shift=true if_missing="error" default=null rest=required />
Removes the fields designated by the rest arguments and the "include" argument
from "_subject" and returns the
value of the last field removed.
If the field cannot be removed, such as when it doesn't exist or is
inaccessible, the behavior is controlled by the "if_missing" arg.
If it is "error", the default, then remove errors with a message
containing the string in the "default" arg.
If it is "return" then the value of the default arg is returned.
Note that you cannot remove any fields from primitive objects such as:
boolean, integer, float, char, string.
If shift is true, (the default), then if key is an integer
of less than the object size and more than or equal to 0, then not only is
the field removed but the higher integer-named fields are all moved down by one.
In this case even though the remove was successful,
there may exist a field of the given name after this operation because
higher integer fields will be moved down.
If the _subject is a vector, the shift argument must be true.
Removing vector_key fields is tricky. If you remove several as in
<thing 0=100 1=200 2=200/>.<remove 2 1 0/>
make sure that you remove the HIGHEST key first so that it won't
shift the others down, OR do:
<thing 0=100 1=200 2=200/>.<remove shift=false 0 1 2/> but beware
that may leave gaps in the vector.
If you do:
<thing 0=100 1=200 2=200/>.<remove include=vector_key shift=false/>
make sure to shift=false or the shifting problem will cause an error
of attempting to remove non-existent fields.
If you do not pass a field name to remove, and you leave include at its default
of "return_false", then the field at the index of
one less than the length of the object will be removed and is returned,
thus performing the "pop" functionality.
Example: <set foo=<vector 3 4 5/>/>
foo.<remove/> returns 5 and now foo's value is <vector 3 4/>
See also: insert for the "push" functionality<rename other_named_args=true />
Like rename_field but allows for renaming multiple fields. Example: thing.<rename newfoo=oldfoo newbaz=oldbaz/> If an old field name does not exist, rename will error.
<rename_field old_key=required new_key=required />
Rename_field will change the name of the key of an object. It takes an object as '_subject' and two arguments: the old key and the new key. The value in the old key will now be in the field with the new key and the field with old_key will no longer exist. It returns the modified object, i.e. '_subject'. If the field is listed in _field_order, the name will be changed there as well.
<replace old_value=required new_value=required copy=false />
"_subject" is a string, a vector or a record.
Replaces all occurrences of old_elt at vector fields with new_elt.
If "_subject" is a string, then old_elt and new_elt must either both be strings or
both be chars.
If the mutable argument is false then a new object is created and returned.
If the mutable argument is true then "_subject" is returned UNLESS
"_subject" is a string, in which case a new string is returned EXCEPT
if no replacements are actually made, in which case the original "_subject" is returned.
Examples: "abcdeabcd".<replace "bc" "x"/> returns "axdaxd"
"abcdabcd".<replace "ab" ""/> returns "cdcd"
<vector 1 2 3 1 2 3/>.<replace 1 9/> returns <vector 9 2 3 9 2 3/>
"foo\"bar".<replace "\"" "\\\""/>
The input string has 7 chars, f, o, o, double-quote, b a, r
The output string has 8 chars, f, o, o, \, double-quote, b, a, r<result_set a_sql=required=string a_db_resource=required=db_resource result_set="output" />
Returns low-level result_set. See execute_query.
Executes the query in query_string upon the given database.
Returns an instance of java.sql.resultset.
The full query string is formed by concatenating the query_string argument
with the content. Content is of type hypertext so you can intermix pure text with
tags which will be evaluated as hypertext content normally is.
The values of the tags in content should be of type:
string, number, character, boolean, null.
See also execute_queryresult_set.<column_name result_set=required column_index=required=number.integer />
Returns the name of the column in the specifed result_set with the column index of 'column'.
'column' must be an integer from 0 up to the result_set_column_count.result_set.<column_names result_set=required />
Returns a vector of the name of each column in the given result set.
result_set.<get_row key=required=number.integer class= />
key is an integer from zero up to the result_set_row_count.
An object is returned that represents that row with a parent of 'object_parent'.
It contains a field for each column in the result_set which has a
key of the column name and a value from the corresponding row.result_set.<to_objects class= start_row=0 end_row=null />
Returns a vector of Water objects corresponding to the specified rows in the
specified result_set.
start_row defaults to 0.
end_row is the index of the highest row NOT included in the result.
It defaults to the row_count in the specified result_set.
Thus using the defaults a vector of the row count in the result_set will be returned.
Beware that if you have a large result set, this will be a large vector.<return value=null from=null />
When a call to return is executed, the execution of the sequence of instructions is
stopped and returned from. The value returned is the first argument of the return call.
It defaults to null.
Usually there will be a nested set of sequences of instructions. The 2nd argument
to return, "a_method_name", determines how far up the stack to halt the nested sequences
of instructions. If "a_method_name" is not passed, or if it is null, the current enclosing
expression is returned from. If "a_method_name" is the name of a method, then the
innermost method call of that name is returned from. If there is no
method by that name on the stack, then all methods on the stack are returned
from. A convenient way to return from all methods is to use a value for "a_method_name"
of "all". In that case, the value returned from, say a top level call to execute_expr,
will be the return object itself, which will have fields of "value" and
"a_method_name".
Examples:
<defmethod foo> <return 543/> 555 </> returns 543
<defmethod foo> <return 541 "baz" /> 559 </>
<defmethod bar> <foo/> 669 </>
<defmethod baz> <foo/> 779 </>
<baz/> returns 541
<defmethod foo> <return 540 "all" /> 559 </>
<defmethod bar> <foo/> 669 </>
<defmethod baz> <foo/> 779 </>
<baz/>.value returns 540
<defmethod foo> <return/> </> <foo/> returns null.<return_false rest="all" other_named_args=true />
Always returns false regardless of the _subject or arguments. Any arguments can be passed to this. return_false is useful as an argument to methods that expect a method as an argument which, when called, you always want it to return false. See also: return_true
<return_subject rest="all" other_named_args=true />
This method returns "_subject". It can be passed any arguments. It is primarily useful as passing to a method that takes a method as an argument where you want the trivial to happen.
<return_true rest="all" other_named_args=true />
Always returns true regardless of the _subject or arguments. Any arguments can be passed to this. return_true is useful as an argument to methods that expect a method as an argument which, when called, you always want it to return true. See also: return_false
<reverse />
If length of "_subject" is 0, return "_subject", else return a new java vector, Bob or string (whatever "_subject" is) with its elements reversed.
<same_vector_elements rest=required />
tests to see if two vectors/supervectors have the same elements in them. _subject can be either a vector or a supervector. rest can be either a vector or supervector. If the two are the same length, and each has at least one copy of the elements of the other, then return true, else return false. Examples: <vector 11 22 33/>.<same_vector_elements 22 33 11/> returns true <thing 0=11 1=22 2=33/>.<same_vector_elements rest=<vector 33 11 22/>/> <vector 1 1 2 3/>.<same_vector_elements rest=<vector 3 3 1 2/>/> returns true In the last example, the vectors are the same length but they duplicate a different element. That's ok for sameness.
Example:
<set my_email=<email out_host="mail.yourcompany.com"
email_address="you@yourcompany.com"/> />
my_email.<send email.message.<out
to="your_field@yourcompany.com"
subject="what's up?"
body="long time no see!"
/>
/>
Returns true if the send was successful, otherwise returns false.
The value of the 'to' parameter may be a string of one address, or a vector of
multiple email addresses.
Note that the reply-to and message-id parameters have a dash instead of
an underscore as is the convention in Water.
This is because the field name in SMTP has a dash.
<server
root_object=required port=80 root_folder=null server_base_uri=null=
A call to server creates an http server on the given port (default 80)
that serves out the object given as the first argument, the 'root_object'.
Example: <server root_object="Hello World" port=8080/>
Once a server is running you can call it from water like so:
<web "http://localhost:8080"/>.content to get back real XML including a header or
Or call it from a web browser like so:
<open_browser_window "http://localhost:8080"/>
We can serve out literal values like so
<server <thing temp=76 humidity=51/>/>
<web "http://localhost/temp"/>.result returns the integer 76.
<web "http://localhost/humidity"/>.result
A more useful thing to do is to serve a method like so:
<server plus/>
<web "http://localhost/?0=4&1=5"/>.result returns 9 <!-- call from Water -->
<open_browser_window "http://localhost/?0=4&1=5"/> <!-- call from browser -->
The question mark in the url indicates that we are calling a method.
We are passing 4 as the value of the 0 parameter and
we are passing 5 as the value of the 1 parameter.
Since plus takes rest args, we can pass as many as we like:
<web "http://localhost/?0=4&1=5&2=6"/>.result returns 15
We can also make our web service look like a local method like so:
thing.<set remote_plus=<web "http://localhost"/>/>
<remote_plus 0=3 1=4/> returns 7
<remote_plus 3 4/> also returns 7
Now let's extend our server to serve out two methods:
<server <thing add=plus multiply=times/>/>
<web "http://localhost/add?0=4&1=5"/>.result {warning this errors.}
Its time to build an interactive web page and a server that can read user input.
First we define a class that's going to have one method for each of the two pages
we are going to serve. Each method returns a hypertext object.
The server will call to_html on this object and deliver the resulting string
to the browser.
<defclass my_first_app> <!-- define the app -->
<defmethod start>
<FORM action="/simple_action">
Type in some text:<INPUT name="a_value"/>
<INPUT type="submit" value="Do It"/>
</FORM>
</defmethod>
<defmethod simple_action a_value>
<H1> You entered: <do a_value/> </H1>
</defmethod>
</defclass>
my_first_app.<simple_action a_value="hi ben"/> <!-- test the 2nd page method. -->
<server my_first_app port=9090/> <!-- launch the server -->
<open_browser_window "http://localhost:9090"/> <!-- use the app -->
When we call the server with no path in the url as we have done above,
the server looks for a method in the
server root_object named 'start' and if it finds one, calls it.
So the page we see in the browser contains one text input field and
one submit button named "Do it".
The user then types in some text and clicks on the button.
Notice the value of the 'action' attribute to the FORM object in the 'start' method.
That is the method that the server will call in response to the user clicking
on the submit button. In this case its called "simple_action".
Note that in the form action, it must be preceded by a slash.
The arguments passed to the method will be from the
controls, i.e. input tags in the content of the FORM call.
The mapping between the method parameters and the controls in the FORM is:
- For each parameter in the method, look for a corresponding control of that name.
If it finds one, use the value of that control as the value to pass in to the
the method. Above you'll see the input attribute of name="a_value" and note
that the simple_action method has a corresponding parameter named "a_value".
The browser passes only strings from the web page to the server,
but the Water server converts strings into data by calling 'data'
so that strings that look like numbers or booleans are converted into numbers
or booleans before being passed to the method.
- If the method has a required argument that is not supplied by the browser, error.
- If the method has an optional argument that is not supplied by the browser,
its value is simply the default value of the parameter like normal method calls.
- If the browser supplies an argument for which there is no corresponding name
in the method, just don't pass it.
- If the form has a control with no name, nothing will be sent to the server
The Water server can pass values from all HTML controls to Water methods including
checkboxes, radio buttons, password fields, text areas and select tags.
Checkboxes are particularly tricky because browsers do not pass back anything for
a checkbox that is unchecked. To deal with such situations, when you are defining
a method that will take the value of a checkbox, give it a default value of
false, and/or declare it to be of type boolean. The server will then makes
sure it gets passed a true or false value.
Here's an example with many different control types:
<defclass lotsa_controls>
<defmethod start>
<form action="/register_user">
Your first name: <input type="text" name="first_name" value="Joe"/> <br/>
Enter your password: <input type="password" name="a_password"/> <br/>
<input type="checkbox" name="likes_ice_cream" checked=false/>
Do you like ice cream? <br/>
<input type="radio" name="flavor" checked=false value="ya"/> chocolate <br/>
<input type="radio" name="flavor" checked=true value="nah"/> vanilla <br/>
Sport of choice? <select name="sport" size=1> <br/>
<option>baseball</>
<option>basketball</>
<option>knitting</>
</select> <br/>
Who do you admire?<textarea name="admire" cols=40 rows=3>Jimmy Page</> <br/>
<input type="hidden" name="user_id" value="user_143"/>
<INPUT type="submit" name="registration" value="Register Me"/>
<INPUT type="submit" name="registration" value="Do Not Register Me"/>
</form>
</defmethod>
<defmethod register_user first_name a_password likes_ice_cream=false=boolean
flavor sport admire user_id registration>
<vector first_name " " a_password " " likes_ice_cream " " flavor
" " sport " " admire " " user_id " " registration/>
</>
</defclass>
<server lotsa_controls/>
<open_browser_window "http://localhost"/>
The browser will show a page with:
- A one line text input field whose initial value is "Joe".
- A blank password field. Typing into this field will disguise
the characters you type.
- A checkbox whose initial state is unchecked.
- Two radio buttons, the second of which is selected.
- A drop down list of three sports. Since none are indicated as selected, the
first one will be selected by default.
- A 3 line text area with initial contents of "Jimmy Page".
- The hidden input field will not be shown on the page but will supply a
value to the server when the user chooses submit
- Two buttons.
If the user clicks the "Register Me" button without changing any of the controls,
the second page will have on it:
Joe false nah baseball Jimmy Page user_143 Register Me
Clicking the checkbox, choosing basketball, replacing Jimmy Page with Jeff Beck
and clicking on the Do Not Register Me button will show:
Joe true nah basketball Jeff Beck user_143 Do Not Register Me
Remember that each method that generates a hypertext object for a server
must return that object. In most cases this means that the object must be
made by the LAST expression in the body of the method.<set other_named_args=true />
Set is the main way to make an assignment, i.e. to assign a value to a local variable or field.
Set is similar to set_value but it can set multiple variables using the key=value syntax.
Example:
thing.<set color="red" weight=2.<plus 3/> />
set with a regular object as '_subject' cannot have a content.
set with no _subject can have a content. The vars will be local vars and
will be bound lexically during the execution of the code in the body of the set.
Example:
<set a=1 b=2> a.<plus b/> </set> returns 3
If '_subject' is 'fluid' then the vars bound will be fluid vars and there must be a content.
During the dynamic extend of the execution of the content, (that means all the lexical code,
plus anything that it calls, recursively on down) the variable will be bound to the values
set. To reference them you must prefix them with fluid.
Example:
<defmethod adjust factor> fluid.x.<times factor/> </>
fluid.<set x=5>
fluid.x.<plus <adjust 10/> />
</set>
returns 55 which is the addition of fluid.x (5) and 5 times 10.
The secrete is that fluid.x in the method executes to 5.
Set returns '_subject' ie the container which has the variable being set
except:
<set a=2 b=3/> returns null, i.e. just setting local vars.
<set a=2 b=3> b a </> returns 2, i.e. the value of the last form in the content.
fluid.<set a=2 b=3> b a </> returns 2, i.e. the value of the last form in the content.
See also: set_value<set_field key=required new_value=required />
Low level way to set the field of an object. This is not to be shadowed. Use set_value unless you are defining a new set_value. set_value is meant to be shadowed by developers. See also set, set_value
<set_type_checking new_value=required />
This affects whether or not the system does run-time type checking on
arguments passed to methods and whether "assert" actually
does its checking or not.
new_value should be one of:
"off" meaning no type checking
"error" meaning type check and if a mismatch is found, error
"warning" meaning type check and if a mismatch is found, print a
warning message.<set_value place=required new_value=required />
Note that normally 'set' is used instead of set_value.
Use set_value only when you want the key to be set to be computed.
The first argument is the place to set, the second is the new value.
Both arguments are executed.
Example: <set_value place new_value/>
Local variables: <set_value "foo" 1.<plus 2/> />
foo will be bound until the end of the defmethod body that its in.
If we've called execute_string on a string that has several top level
expressions, then foo will be bound throughout, i.e. one local environment
for the entire string.
Field Variables:
thing.<set_value "foo" 2/>
thing.foo.bar.<set_value "baz" 2/> this is legal too.
Below here are advanced uses of set not needed for simple programming.
Computing Place
Example:
thing.<set_value "my".<concat "place"/> "red"/>
thing.myplace returns "red"
Fluid Variables:
Fluid variables can be set by calling set with a "_subject" of fluid.
Unlike local variables, they have DYNAMIC extent.
Fluid variables shadow previously set stack variables.
In the example below, we set up two (nested) fluid variables each named test7.
For the execution of the BODY of the inner set, the inner $test7 i.e. the one
with value 77, shadows the one with value 777.
When the inner set is called, first test7 and 77 are pushed onto the fluid variable "stack",
then the content of the set is executed. First we call the method test_meth2
which causes test_meth to be called, which executes the fluid variable test7,
whose value is looked up on the stack to get 77 which is returned by
both methods and ultimately by the inner set then finally the outer set.
Example:
<defmethod test_meth2> <test_meth/> </>
<defmethod test_meth> fluid.test7</>
fluid.<set_value "test7" 777>
fluid.<set_value "test7" 77>
<test_meth2/>
</set_value>
</set_value> returns 77
You can compute the name of a fluid to set. Here's a rather tricky example:
<set myvar="foo97">
fluid.<set_value myvar 4>
fluid.<get myvar/>
</set_value>
</set> returns 4
First the local variable myvar is bound to "foo97".
Next in our call to set_value we use the value of myvar as the name of the fluid variable
to set to 4.
Finally within the content of set_value we execute the expression fluid.<get myvar/>
which is effectively fluid.foo97, whose value is 4.
Custom Set:
You can write a custom method to be called whenever a set of a particular field
is called.
thing.<defmethod junk_f_set place new_value>
</defmethod>
thing.<set junk 123/> does nothing because the above definition is used and it has
an empty body. This makes a field "read only" as long as "set" is the only method
called to change its value.
thing.<defmethod junk_f_set place new_value>
thing.<set_value "junk" 1.<plus new_value/> />
</defmethod>
thing.<set junk=3/>
thing.junk returns 4 Always sets thing.junk to one higher than the new-value argument passed to set.
thing.<defmethod junk_f_set place new_value>
_subject.place.<set_value _subject.place.name 1.<plus new_value/> />
</defmethod>
Similar to previous example but uses "_subject" and place.name to refer to thing and "junk".
Active Values:
You can set a variable such that instead of just returning
the value in the field, it will execute arbitrary code instead.
For example:
<set thing.test_av
<thing head_weight=200
tail_weight=300
weight=<active_value> thing.test_av.head_weight.<plus thing.test_av.tail_weight/>
</active_value>
/> />
thing.test_av.head_weight returns 200
thing.test_av.tail_weight returns 300
thing.test_av.weight returns 500 <!-- 200 + 300 -->
<set thing.test_av.head_weight 222/>
thing.test_av.weight returns 522 <!-- 222 + 300 -->
Besides initializing a field variable with an active value, we can also use set like so:
<set thing.test_av.weight <active_value>
thing.test_av.head_weight.<plus thing.test_av.tail_weight/>
</active_value>
/>
You can also set local and stack variables to active values.
When a call to active_value is executed, a special object is created that captures both the
expressions in the content of the call as well as the local environment that the call was
made in. So the content of active_value can contain references to local variables
in the environment of the call.
When a references to a variable that contains an active value is made, the
expressions in the content of the creating make-active_value are executed in
their original local environment.
We can use active_value and defmethod foo_f_set in conjunction to set up
a "alias" like so:
<set thing.test_av.orig 27/>
thing.test_av.orig returns 27
<set thing.test_av.clone <active_value> thing.test_av.orig</active_value> />
thing.test_av.clone returns 27
<set thing.test_av.orig 28/>
thing.test_av.orig returns 28
thing.test_av.clone returns 28
thing.<defmethod test_av.clone_f_set place new_value>
<set thing.test_av.orig new_value/>
</defmethod>
<set thing.test_av.clone 29/>
thing.test_av.clone returns 29
thing.test_av.orig returns 29
regardless of which one(s) are set to what, both will have the same value.
Set is used for its side-effect but it returns the value of its 2nd argument
which can be used in other operations. However, if the 2nd argument is
<active_value> code </active_value> then null is returned.
Within the body of active_value, "_subject" refers to the object that
was called with the make active value.
For example:
<defclass boat hull_weight=10 sail_weight=20
total_weight=<active_value>
_new_object.hull_weight.<plus _subject.sail_weight/>
</active_value>
/>
<boat sail_weight=40/>.total_weight returns 50
First a kid of boat is created, shadowing the sail_weight from boat of 20 with 40.
Then we ask for the total_weight where we get the hull_weight from boat because it
isn't shadowed and the sail_weight from the kid for 10 + 40 = 50
Free local variables in the content of a call to active_value will execute to the
values that they had when the call to active_value was made, just like a closure.Water Shell: Using Water from the command line Water expressions can be called from the command line or script files. Calling Water assumes you have a running Water server. <Example <server root_object=thing port=8080/> /> You will need a program for calling a Water Server over HTTP. There is a program called cURL that lets you easily make an HTTP request from the command line on multiple platforms. The cURL program is available here: http://curl.haxx.se Steps: 1. Install cURL 2. Create a Water server: <server thing/> 3. Create a xwater.bat file that calls cURL with arguments to a particular Water Server: <Example name="contents of xwater.bat file for accessing local server"> @echo off D:/curl-7.9.1-win32-nossl/curl http://localhost:8080/%* </Example> <Example result="2003-6-14 21:18:44"> C:/xwater datetime/current.txt </> 4. Optionally add path to "xwater" to AUTOEXEC.BAT (or equivalent) SET xwater=D:/curl-7.9.1-win32-nossl/xwater.bat 4. Test it: <Example name="Command-line to get the current date-time from Water" result="2003-6-14 21:18:44" > xwater datetime/current.txt </> <Example name="Command-line to create a vector in XML format" result=<vector> 5 abe </vector> > xwater "vector.xml?5&abe" </> <Example name="Command-line to create a vector in CSV format" result="\n5\nabe" > xwater "vector.csv?5&abe" </>
<sort predicate=object_less />
Expects "_subject" to be a vector (Bob or java).
Elements are sorted according to predicate (a method that returns true or false).
"_subject" is modified and returned with elements in the sorted order.
predicate is optional. It is a method that compares '_subject' and its first argument
returning true if '_subject' should be before the first argument in the sorted order.
The default value is object_less, also called ascending
which sorts all numbers first in ascending order, then
all other objects in alphabetical order when they are printed using to_html.
Example:
<vector "aab" 347 "aaa" 346/>.<sort/> returns <vector 346 347 "aaa" "aab"/>
Another common method to pass sort is 'descending' which will produce a
sequence in the opositve order from the method 'ascending'.
If you write your own method for the sort predicate, it should take a subject
and one argument. It should return true if the subject is to come before
the argument in the resulting order. Note that the predicate should return
false if its subject and argument are considered to be "equal" for the sorting order.
Sort can be used to sort by more than one key by making a sort method that
looks at more than one key. Here's an example:
<vector <thing a="f" x=0/> <thing a="f" x=1/>
<thing a="g" x=1/> <thing a="g" x=0/>
<thing a="g" x=3/> <thing a="g" x=2/>
/>.
<sort
<defmethod sort_by_a_then_x obj>
<if> .a.<equal obj.a/>
.x.<object_less obj.x/> <!-- sort by 2nd key -->
else
.a.<object_less obj.a/> <!-- sort by primary key -->
</if>
</defmethod>
/>
The above code returns:
<vector <thing x=0 a="f"/>
<thing x=1 a="f"/>
<thing x=0 a="g"/>
<thing x=1 a="g"/>
<thing x=2 a="g"/>
<thing x=3 a="g"/>
/>
See also is_sorted.Returns a vector of substrings found in '_subject' separated by
a_pattern. If a_pattern is on the very end of '_subject', then
the last element in the returned vector will be an additional
empty string.
Example:
"aaa/bbb/ccc".<split separator=<pattern> <pattern.char_set "/"/></>/>
Returns a vector of 3 strings, "aaa", "bbb" and "ccc"
separator may also be just a string
"aaa/bbb/ccc".<split "/"/> returns the same thing as the above example.<stack_report />
Returns a string of the method calls currently on the stack.
By convention, when a class is displayed as HTML, it looks for a 'start' method and calls it. If a Water server has a root_object that is a defclass, then if the request URI has no path, then the 'start' method will be called. If you are familiar with the concept of an 'index.html' page in a folder, the 'start' method is similar in concept. The 'start' method should either be the home page for an application, or call the home page. The 'start' method returns an object to display. The 'start' method can also be explicitly called with arguments.
Steam is the Clear Methods development environment for Water.
It supplies a GUI for creating, saving, running, testing, inspecting
debugging and documenting water programs.
Steam takes pains to make its functionality obvious so try all the menu
items to familiarize yourself with the tools. A few things are not obvious:
- A right click in the editor pane will pop up a menu of operations.
- Double-clicking on the start, middle or end of an expression will
highlight that expression. This makes it easy to find matching
angle brackets.
- Double-clicking in the middle of a method name or class name, it will not
only select the whole name but also give you the parameters to calling the
method or class in the lower right pane. Actually all method and class names that
contain the string you selected will be shown with exact matches
presented in a bold font at the top of the list.
You can click on each such item in the lower right pane to inspect the
method or class and any documentation that's available for it.
- The result of clicking the Execute button is shown in a location dependent
on the value of the 'Show Result in Browser' menu item checkbox in the 'Options'
menu. When this checkbox is off, the result goes in the right-hand panes
of the ide, whose width is controlled by a draggable splitter bar.
- Clicking in the upper right pane will bring up a menu.
Choosing "Inspect This Object" brings up the inspector on the
result of the last execution. You can also do this by choosing the
'Tools' menu item of 'Inspect latest result'.
- Clicking in the lower right pane gives you a menu that
lets you view the html that was generated
by calling the to_html method on the result of the last execution.
See also the reference manual chapters getting_started, inspect and testing.The stepper is a kind of evaluator which lets you incrementally step through
each expressing that you are executing to see the intermediate values and
control flow that your program actually uses. In cases where your model
of what you *think* your source code is saying and how it actually executes
differ, the stepper is exceedingly useful.
To step through some code, select the source of the code in the editor pane
and click on the 'Step' button at the bottom of the window.
Here's a trivial example:
Paste the following code into the editor pane:
<defmethod foo aaa bbb> aaa.<plus bbb/> </>
<foo 111 222/>
Select the call to defmethod and click on the Execute button.
Select the call to foo and click on the Step button.
Continually click on the Step button and watch various portions of the
code within the foo method get executed. Note that the value of the
current execution appears in the panes on the right of the screen.
The stepper remembers previous values so after you have stepped through an
expression you can double_click on it to
see what its value was the last time it was stepped through.
If you want the value of a variable, double-click in the middle of the variable.
If you want the value of a call or a path, double-click on the beginning of the path.
The value, if any was stored, appears in the lower_right pane.
You can click on that to inspect it.
Stepping is slow and you may not care about the details of some expression
so you can step over it by clicking on the 'Over' button, or even
step through the siblings of the current expression by clicking on 'Up' for
even faster stepping. If you step via these accelerated 'Over' or 'Up' commands,
intermediate values that you stepped over are still remembered so you can
still see what expressions executed to using the 'Value' button.
For example, in the call to foo above,
Change the args to 444 and 555.
Now select the call to foo and click on 'Step'.
Click on 'Over' to complete the stepping.
Now select 'bbb' and click on the 'Value' button.
You'll see 555 in the right panes.
There's another way to speed up stepping. Here's how:
Execute the call to defmethod foo above.
Select the call to foo.
Click on 'Step'
Click the mouse in the middle of bbb to position the insertion cursor.
Click on 'Step to pos'.
Stepping jumps to bbb
You can use select earlier expressions and use the 'Value' button to see
previous intermediate values.
During stepping you can click the 'Cancel' button at any time to just quit stepping.
During stepping you can click the 'Execute' button at any time to complete the
execution. Doing so will not cause values to be remembered in that portion of your code.
Whether you step all the way through a complete expression, press Execute in the middle
or just Execute the whole expression, it still returns the same value. The only
difference is in speed and interactivity.
(Well ,ok you could write some time-dependent code but baring that stepping and executing
should have exactly the same side-effects and result.)
Stepping depends on having the definition in the buffer being exactly where they
were when the definition were defined. So don't, for example, insert some whitespace
in the middle of a defmethod, then attempt to step through a call to that method.
If you modify ANYTHING in the source of a call to defmethod or defclass, execute it
before stepping through it.
See also: debugging<string />
String literals are modeled after Java. They are immutable. You can not for example,
take a string and set the first character to something else.
You can make string literals by surrounding characters with double_quotes.
Example: "a string"
The usual escape sequences apply such as:
"a\nstring" to make a newline between "a" and "string".
"a\"b" makes a string of three characters, a, double_quote, and b.
"a \\ backslash" gets one backslash in the string.
The complete list of chars following a backslash are:
b for backspace
f for formfeed
n for newline
r for return
t for tab
u for unicode character. Following the u you must have 4 hexidecimal digits,
ie 0 through 9 or A, B, C, or D
The double quote character
The single quote character, though it is unnecessary to put a backslash before a single quote
you might need to do it in some weird cases involving Javascript strings.
(a backslash) for backslash
Although double_quotes are the preferred way to delimit string literals, you can also
delimit code for attribute values with single quotes as is specified by XML.
Do not use single quotes to delimit strings that are top level expressions within the content
of a tag, or to delimit strings that contain angle brackets.
If you want to create a string literal with a lot of double_quotes in it, you may well find it easier
to use:
<string>a "string" <p/></string>
Note that in the above, no "p" object is created. The <p/> is just the ending chars of the string.
We could have done exactly the same thing with:
"a \"string\" <p/>"
The XML syntax for CDATA can also be used.
Example: <![CDATA[some "'<string]]> returns "some \"\'<string"string.<equal_whitespace_insensitive string1=required=string />
Returns true if "_subject" has the same non-whitespace chars in it and in the same order as string1. Examples: The following expressions all return true. "abc".<equal_whitespace_insensitive "abc"/> " a b c ".<equal_whitespace_insensitive "abc"/> " ".<equal_whitespace_insensitive ""/> "abc".<equal_whitespace_insensitive "abcd"/>.<not/>
string.<execute_file env_or_context=null execution_kind="ek_code" returns="last" />
Executes the code in the content of the file name in "_subject".
The current directory starts out as the dir that the Water class files,
core.h2o, etc live.
i.e. "foo/bar.h2o".<execute_file/> actually executes something like:
D:/something/glueworks/water/foo/bar.h2o
While a file is being executed, its string name is in thing.loading_file.
"returns" is similar to the for_each "returns".
"last" (the default) says return the last value in the file.
"all" says return a vector of all the values in the file.
"all_except_null" is like "all" but null values are excluded from the returned vector.
env_or_context parameter behaves just as it does for execute_string and execute_expr.
Example:
The content of the file "junk.h2o" is: x.<plus y/>
<defmethod foo x>
<set y=8/>
"junk.h2o".<execute_file _environment/>
</defmethod>
<foo 7/> returns 15
The execution_kind and returns parameters perform the same functionality as those
parameters in execute_string.
See also: execute_stringstring.<get_url_property property_name=required />
given "_subject" of "http://www.glueworks.com/glueworks?model=foo&user_name=fred" and property_name of "user_name", returns "fred". If property_name not found, returns null
string.<html_to_xhtml add_heading=false />
html_to_xhtml returns a cleaned-up, xhtml-ized version of its input string. Improper syntax like unbalanced ending tags, improper nesting, and a bunch of other syntactically broken constructs are fixed. If add_heading is true, the output will be enclosed with <html> <body> ... </body> </html>. Otherwise no extra outer tags will be added to the input. If the input happens to already contain an 'html' tag, add_heading will have no effect and the original html tag will be preserved. add_heading has a default of false. This method uses the W3C's 'tidy' program in its implementation. See also: hypertext
string.<key_of item=required case_sensitive=true start=0 end=null returns="first" />
key_of searches through "_subject" (a string) for a given substring. If substring is not in "_subject", then return false, else return the index of the first occurrence of substring within "_subject". Example: "abcde".<key_of "cd"/> returns 2 Example: "abcde".<key_of "z"/> returns false Although the substring argument is usually a string, you may also pass in a character and the position of that character in "_subject" will be returned or false if not found. If substring is anything but a String or a char, false is returned because strings can only contain substrings or chars. See also thing.key_of for documentation on the returns, start, and end arguments.
string.<less a_string=required=string />
string.less returns true if "_subject" is less than (alphabetically) a_string otherwise returns false. Example: "abc".<less "def"/> returns true
string.<less_or_equal a_string=required />
Returns true if _subject is less than or equal to the argument otherwise returns false.
string.<more a_string=required=string />
string.more returns true if "_subject" is more than (alphabetically) a_string otherwise returns false. Example: "abc".<more "def"/> returns false
string.<more_or_equal a_string=required />
Returns true if _subject is more than or equal to the argument otherwise returns false.
string.<random_instance max_length=20 common_letters=<one_of "b" "c" "d" "f" "l" "m" "n" "r" "s" "t"/> vowels=<one_of " " "a" "e" "i" " " "o" "u"/> uncommon_letters=<one_of "g" "h" "j" "k" "p" "q" "v" "w" "x" "y" "z"/> common_two_letter=<one_of "th" "st" "fl" "tr"/> />
Returns a string of a bunch of characters. The length of the string will not exceed max_length, which defaults to 20. Example: string.<random_instance/> returns something like: "s necorif fomo"
string.<replace_angles />
Example: "<foo.<bar/>/>".<replace_angles/> returns "<foo.<bar/>/>"
string.<replace_html_entities />
Example: "<foo.<bar/>/>".<replace_html_entities/> returns "<foo.<bar/>/>"
string.<split separator="\n" />
_subject is a string to split up into substrings separated by the passed-in "separator" string. Frequently the separator string is just a one character string of a comma, a space, a slash or a newline (which is the default). The separator string is BETWEEN the substrings in the output vector. The separator string will not be part of any output string. If the separator is at the beginning and/or end of the _subject string, then there will be an empty output string and the beginning and/or end of the output vector. Examples: "foo\nbar".<split/> returns <vector "foo" "bar"/> "foo/bar/baz".<split "/"/> returns <vector "foo" "bar" "baz"/> "/foo/bar/baz/".<split "/"/> returns <vector "" "foo" "bar" "baz" ""/> "foo--bar--".<split "--"/> returns <vector "foo" "bar" ""/> "".<split/> returns <vector/> "/".<split "/"/> returns <vector "" ""/> See also: pattern.split for a more sophisticated string-splitter.
string.<starts_with a_string=required case_sensitive=true at_key=0=number.integer />
returns true if string starts with with a_string, otherwise returns false. If case_sensitive is false, the case of the strings doesn't matter. The comparison starts at the 'at_key' position within '_subject'. at_key defaults to 0. Example: "abcdefg".<starts_with "cd" at_key=2/> returns true.
string.<string_to_char_vector />
Converts a string into a vector of chars (a char_vector). Note that many operations, such as length, and getting a char at a particular index, will perform analogously on either a string or a char_vector. However, strings are immutable so if you want to effectively have a mutable string, first convert your string to a char vector, perform your mutating operations, then convert the char vector back to a string with char_vector_to_string. Since a char_vector IS a vector, all the usual vector operations can be applied to a char_vector such as insert and remove. Example: "wer".<string_to_char_vector/> returns <vector <char "w"/> <char "e"/> <char "r"/>/> See also: char_vector_to_string, from
string.<to_lowercase />
Returns a string with all the letters lower cased and the non-letters the same as in "_subject". If no characters needed conversion, then "_subject" is returned. See also: string.to_uppercase, char.to_lowercase
string.<to_uppercase />
Returns a string with all the letters upper cased and the non-letters the same as in "_subject". If no characters needed conversion, then "_subject" is returned. See also: string.to_lowercase, char.to_uppercase
<string_key />
Returns true for keys that are strings but not if they are a system_field. System_fields are strings but they begin with underscore. See also: regular_key, system_key
_subject and _new_object are local variables that are handled specially by the system.
_subject is bound to the "Subject" of a call, i.e. "foo" in foo.<bar/> is the subject.
_new_object is bound to the new object being created by a call to defclass or init.
Details on Subject
Most calls to methods look something like:
somesub.<foo/> in which case the local variable _subject is bound to somesub
during the exectuion of the body of foo when foo is called.
You can override that binding by supplying the subject as an argument in the call like so:
somesub.<foo _subject=369/> in which case _subject will be bound to 369.
If you do not supply either a "left_hand" subject or an explicit _subject arg,
then subject will be unbound and any reference to it will error.
However there's one exception to that rule: If you define the method to take
a parameter of _subject and give it a default value, that value will be used
for the value of _subject.
The rules are:
If there is an explicit subject attribute passed in the call, use that for the value of _subject,
else if there is a left_hand subject use that
else if the method was defined with a parameter of _subject with a default value,
use that value
else _subject will be unbound and any references to it will error.
Before the first reference to _subject in a method you can test to see
if it is bound or not with <has "_subject"/>
Examples:
<defmethod foo> _subject </>
thing.<foo/> returns thing
<foo _subject=369/> returns 369 because the subject was explicitly supplied
thing.<foo _subject=369/> returns 369 because _subject=369 trumps "thing" for
the value of _subject while the body of foo is being executed.
However, "thing" is still used as the object to look up "foo" in.
<foo/> errors because _subject is unbound.
Note that <defmethod foo /> sets a key in thing of "foo" to the new method
so it is a shortcut for thing.<defmethod foo />
<defmethod foo _subject=246> _subject </>
thing.<foo/> returns thing
<foo _subject=369/> returns 369
<foo/> returns 246 Had there been no default value for _subject in the definition of foo,
this call to foo would have errored.
Note that whitespace followed by .foo is a shortcut for _subject.foo
Details on _new_object
_new_object is bound to the new object being created within the body of a defclass
and an init method. Otherwise it is unbound.
Example:
vehicle.<defclass boat>
_subject <!-- evals to vehicle. -->
_new_object <!-- evals to boat, i.e. the new class -->
<defmethod init>
_subject <!-- in a call like vehicle.<boat/>, evals to vehicle
in a call like <boat/> it is unbound -->
_new_object <!-- evals to the new instance of boat being created -->
</defmethod>
<defmethod launch>
_subject <!-- in a call like: my_boat.<launch/>, evals to my_boat
in a call like <launch/>, it is unbound -->
_new_object <!-- unbound -->
</defmethod>
</defclass>
See also: defmethod, init<subvector start=0=number.integer end=optional=number.integer />
"_subject" can be a java_vector, a string or a Bob. Returns an object of the same type as "_subject" with a subset of the fields of "_subject". The included fields are the integer-named fields equal to or greater than start but less than end. Start defaults to 0. End defaults to the size of "_subject". If end is longer than the length of "_subject", subvector acts as if it is the length of "_subject". It does not error. Examples: <vector 10 11 12 13/>.<subvector 1 3/> returns <vector 11 12/> <vector 10 11 12 13/>.<subvector/> returns <vector 10 11 12 13/>
<subvectors rest=required />
_subject is cut up into subvectors each of which is placed in a vector and that vector of vectors is returned. Rest is an even number of integers, each pair representing the start (inclusive) and end (exclusive) of a subvector. Within each pair, the first integer should be less than or equal to the second integer, but pairs need not bear and such relationship to each other. Pairs may even specify overlapping subvectors. Example: "abcdefgi".<subvectors 1 3 5 7/> returns <vector "bc" "fg"/> If the number of integers passed is odd, then a new integer is added to the end of the list that is equal to the length of "_subject".
Valid variable names can contain the chars:
letters, digits, underscore, dash, colon.
Names may start with a letter, or underscore.
Names are case sensitive.
There are local variables, field variables and fluid variables but all the names
follow the above rules.
Integers start with a -, + or a digit.
Floats start with a -, + or a digit, have a bunch more digits, then a dot then some more digits.
Literal strings start with a double quote, may contain single quotes, backslashed double quotes
or other characters and end with a double quote.
Alternatively a literal string may start with a single quote, contain double quotes or
backslashed single quotes, or other characters and end with a single quote.
See the documentation for "string" for a more detailed description of string literals.
Calls may have the formats:
<foo a=1 b=2 />
<foo a=1 b=2 > ... </foo>
<foo a=1 b=2 > ... </>
By position args are also permitted whereby attributes don't have keys or equal signs.
Examples: <a href="www.sun.com">Click here for solar power</a>
<a href="www.sun.com">Click here for solar power</>
Note that the call syntax is used both for calling regular methods and 'calling' contructors.
See also: defmethod_f_doc, defclass_f_doc
Paths are made up of two or more of the above, each part separated by a dot.
If a path begins with two integers, those will be made into one float.
If two consecutive integers are in a path but do not begin the path, they
are considered to be two separate integer parts.
Paths of arbitrary length can be constructed.
Example: thing.bar returns the value of the bar field within thing
thing.bar.baz returns the value of the baz_field within thing.bar
thing.<foo 1 2/> the value of the foo field within thing is
called with arguments 1 and 2.
You can get elements of a vector using dot syntax as well:
Example: <vector 100 101 102/>.2 returns 102
Note this is equivalent in many more syntactically ideosyncratic languages as
some_array[2]
Since strings are essentially an array of characters:
"abcd".2 returns the character c.
There is no special syntax for characters. You just "construct" a character
like you to other classes with <char "a"/> to reference the character a.
You can save some typing by using "a".0 if you like but that's a bit sneaky.
If you want to COMPUTE the value of a field reference and use the computed value
to look up the value,
foo.<get 2.<plus 3/>/> is equivalent to foo.5
_f_ separates the name of a field from its meta_field name if any,
Example: foo_f_doc indicates a field that documents the field named "foo".
See also: meta_fields_f_doc<system_key />
Returns true for subjects that are strings beginning with underscore. See also: non_system_key
<test source=""='ek_string' result="true"='ek_string' pre_code=optional='ek_string' post_code=optional='ek_string' pre_doc=null name=null fails=false test_count=1=number.integer failures=<vector/> files_run=<vector/> syntactically_broken_files=<vector/> files_with_unexpected_failures=<vector/> expected_failure_count=0 success=true failed_source="system use" failed_result="system use" container=null containing_file=null of=<thing/> />
'test' creates an instance of 'test' that contains at least two strings of code. This code is executed and compared with 'equal'. In the case where both values are strings, they are compared ingnoring whitespace. If the values are equal, the success field of the test instance is set to true, otherwise its set to false. The test instance is returned. The to_html method for test prints "Passed Test" if the test succeeded and "Failed Test" plus details if it didn't. The second argument defaults to true so if evaluating your first argument is supposed to return true, you need only pass one argument to "test". Examples: <test 1.<plus 2/> 3/> Makes and runs a simple test <test source=1.<plus 2/> result=3/> Same as above <test result=3> 1.<plus 2/></> Same as above, good for long source argument. <test> 5.<is 5/> </> result defaults to 'true' so this is the same as: <test> 5.<is 5/> true </> You can use any expression of the language as arguments to test. If you would like a comparison method other than equal, Stick the call to the comparison method in the 'source' arg along with both expressions to compare and let the result arg default to true. You will find particularly useful calls to the methods: is, equal, equal_ignore_whitespace, not. You can give 'test' additional fields of: name a string to identify the test pre_doc a string to describe the test See also thing.testing_f_doc
test.<clear />
Initializes the test report to the empty state.
test.<report title="" />
thing.test.<report/> returns a string indicating the number of tests run, and of those, the number that failed as well as a description of each failure since the last time test.<clear/> was called. Example: test.<clear/> <test 2 2/> <test 3 4/> test.<report/> A large body of tests can be modularized by sticking them in their own file(s), or by placing calls right after the definitions that are being tested. To call them, first test.<clear/>, then load each file, and finally, call test.<report/>. Usually 'clear' and 'report' are not called explicitly, but rather invoked from the Test menu in the Development environment by 'Run Tests in Selection' or 'Run Tests in Files'. See also thing.testing_f_doc, test
test.<time_it times_to_execute=1 />
Executes the content and returns the number of milliseconds that the execution took. If you want to test read-time, then call execute_string in the content of time_it. times_to_execute specifies the number of times to execute the content. Note that times that are under 100 milliseconds or so are more highly variable than longer times for no apparent reason, they just seem to vary randomly, though its rare that two runs of any amount of time will be within 1% of each other. Calling time_it with a high times_to_execute produces a time that is slightly less than what you would expect from testing with lower times_to_execute. Example: <time_it times_to_execute=100> 2.<plus 3/> </time_it>
OVERVIEW
Water makes you more productive by making it easy to implement more functionality
per programming hour. But if that functionality isn't RELIABLE, then all that
'productivity' is useless. You must first fix the bugs.
The hardest part of bug fixing is finding out WHERE in your source code the bugs are.
Water frequently is able to highlight broken code but often where a bug shows up
is not the real source of the problem. To find bugs while they're easy to find, test
- early
- often
- exhaustively
When you have a working program and you add a small bit of code and then have a broken
program, you know that very likely the bug has something to do with the code
you just added.
So your localization problem is solved.
However, testing in small increments is usually so much of a burden on a programmers
that they simply don't do it.
Water has a lot of support for making testing quick and easy.
Using an incremental code and test methodology, the programmer can develop, extend
and maintain code that is reliable throughout its life cycle with a minimum of effort.
The remainder of this document helps you understand three kinds of correctness:
Syntactic Correctness
Execution Correctness
Semantic Correctness
as well as how to check for them using the tools in the Steam environment.
SYNTACTIC CORRECTNESS
Code that is syntactically correct will at least pass through the parser.
It is likely that you will have more syntactic bugs than anything else.
Fortunately they are easy to fix.
First, you can insert many common Water expressions by selecting them from the
right-click menu in the editor pane. These are guaranteed to be correct.
Second, for expressions you type yourself, you can double-click on the beginning
or end of the expression to highlight the entire expression. If only one character
is highlighted when you do this, the expression is not syntactically correct.
Double-click on smaller and smaller pieces of the expression to locate the bug.
EXECUTION CORRECTNESS
Code that executes without erroring has achieved the next level of correctness.
You can highlight any section of code and click the Execute button to execute it.
Double-click on an expression to highlight it and you'll at least be starting with
a syntactically correct expression.
Here's a maximally incremental way to verify a function call.
Let's incrementally build a call to plus, say 2.<plus 3/>
First type in the subject, 2, select it and execute it.
Next type in a dot and plus so you've got 2.plus
Double-click right before the 2 to highlight the whole expression
and execute it. What will be returned is the method object.
This verifies that 'plus' is a field that can be looked up for a value
from 2.
Next turn our expression into a call by adding angle brackets like so:
2.<plus/>
Again, double click before the 2 to verify the syntactic correctness,
then click the Execute button.
Only methods that take no required arguments will work here.
Since 'plus' does not take required arguments, it works and 2 is returned.
Next add an argument like so: 2.<plus 3/>
Select the 3 to execute it independently of the rest of the call and verify
that the execution of the first argument does not cause an error.
Finally, double_click before the 2 to select the entire expression and
execute it.
Performing all these steps for every method call, especially simple ones
is too tedious and frequently unnecessary. But as a method call gets more
complex, particularly for methods that you're not very familiar with,
each of the above steps may help. You can, for example, type in the entire
call and execute it. Suppose you get an error message that's incomprehensible.
You can then select individual parts and execute them.
By removing the open angle and selecting the subject and the method, you can
verify that the lookup of the method happens correctly.
Using the Stepper is yet another way to verify individual pieces of code
for execution correctness.
SEMANTIC CORRECTNESS
To verify that a function call not only does not error, but produces the
correct result you've got to look at the result and decide if it matches
your intent. Once you've done that for a particular call,
you don't have to do that work again, though you do want to be told when
the function no longer behaves that way. To encode your analysis of a
function call and its returned value you write a test case.
TEST
At its simplest level, a test is two pieces of source code that
both execute to the same thing with a wrapper around them.
Example: <test 2.<plus 3/> 5/>
Here the 2.<plus 3/> is our "source" and the 5 is the expected "result".
The easiest way to make a test is to select the source,
in this case 2.<plus 3/>, click right and choose "<test .../>" from the menu.
Doing so will tell the system that you have valid source code that functions
correctly. The source is executed to get a result, the result is printed out
after the selected source and the whole thing is wrapped in a call to 'test'.
When a call to test is executed, an instance of the test class is made, storing
the source and result strings. Then the strings are executed and their results are
compared using the 'equal' method. If equal returns true, the test instance is
marked a success, otherwise it is a failure. The instance is returned by the call to test.
to_html on a test returns:
- "Passed Test" if it passed or
- "Failed Test" with some details
which is what you'll see in the lower right browser pane after executing a call to test.
Test takes additional arguments to specify a name, documentation, set-up as well as
tear-down code. See the documentation on 'test' for details.
RUNNING TEST GROUPS
You can select multiple calls to 'test' and execute them but
this doesn't easily let you see the results.
The 'Test' menu items make it easy to run and report on multiple tests.
The Test Report summarizes all the tests that have been run since the
last "Clear Test Report" was run.
The Test menu item 'Run Tests in Selection' will
- Clear Test Report
- execute the code in the selection, or if no selection,
all the code in the current buffer.
- Show Test Report
The Test menu item 'Run Test Files' will
- Clear Test Report
- Execute the code in all the files selected.
If you select folders, the files that they contain that
end with "_f_test.h2o" will be selected and any similar files
in subdirectories, recursively on down.
- Show Test Report
The Test menu item Show Test Report summarizes the tests that
have been run since the last Clear Test Report.
The Test menu item 'Verbose Testing' prints out a line as each
test is executed in the Java Console. This helps verify which tests
were run and will help locate tests that break the test software itself.
The programmatic way to clear and generate the test report is to use the Water calls:
test.<clear/> and
test.<report/>
RUN TIME TYPE CHECKING
When you are defining a method or a class you can optionally declare the expected type
of each argument.
Example: <defmethod foo arg=0=integer/>
Without doing anything further, this type declaration is simply documentation.
You can call foo with an argument of a float or a string and, as long as
nothing in the body of the method cares, it will run fine.
However, you can choose to turn on run time type checking so that each argument
to each method that has type declarations will be tested at the time of the call.
This slows down execution but provides, in effect, a new set of run time tests
which can catch bugs early and improve reliability.
Use the Options menu's submenu of "Type Checking" to modify the system's behavior.
- Off tells the system to not do any type checking.
- Warning does the type checking and prints any conflicts out in the console,
but does not stop execution.
- Error does type checking and errors as soon as a mismatch is found.
We recommend declaring types and turning on type checking during development
but keep it off for deployment to improve performance.
See also: debugging, steppingthing is the top level object in the object system. It can be referred to in code
as thing. All objects have as an ancestor, thing, except for thing itself which has no parents.
If you want to make an object and you don't care what its parent is, use thing.
Example: <thing color="purple" size=12/>
This executes to an object whose parent is thing. It has two additional fields,
a field named "color" with a value of the string "purple" and
a field named "size" with the value of the integer 12.
Using <thing color="purple"/> we create an object that has a field
whose name is the string "color" and whose value is the string "purple".
But a field name can be any object. This object creating syntax permits
integers to be field names:
Example: <thing 0=10.<plus 123/>/>.0 returns 133
<thing 3=10.<plus 124/>/>.3 returns 134
Floats can also be names of fields.
Example: <thing 1.2=3.<plus 4/>/>.<get 1.2/> returns 7
Note that dot is used for both floating point numbers and getting the value of a field.
This is unfortunate since it makes dot confusing, but the alternatives weren't
very good either. This is the same as for Java and Javascript, by the way,
but neither of those can have fields with names of floats so we have to be careful.
We can't say foo.1.2 and expect to get the field named 1.2 within foo because
instead we'd be asking for the field named 1 in foo and then asking for
the field named 2 within THAT. However, we can use get to execute the
name of the field whose value we are asking for. Since numbers execute to themselves,
then foo.<get 1.2/> will get the field named 1.2 in the foo object.
Calling thing allows you to create fields of any name.
If you want to name the fields by consecutive integers starting with zero,
you can because thing accepts "rest" arguments. So a subobject of thing
(or most other objects) can behave like a vector:
Examples:
<thing 100 101 102/>.1 returns 101
<thing 100 101 102/>.<insert 103/>.3 returns 103
<thing color="orange" 11 22/>.color returns "orange"
<thing color="orange" 11 22/>.1 returns 22
See also vector.<time_in_seconds />
time_in_seconds returns the current time in seconds from midnight, January 1, 1970 in Universal Time Code. Example: <time_in_seconds/> returns an Integer more than 946080000 which is 30 years worth of seconds.
<to_concise_xml the_execution_kind="ek_code" />
Returns a string representing the object in "_subject" that can be read back in to
recreate the object.
If to_path returns a string when called with a subject, then that string is returned.
Otherwise, to_h2o is called to make a full representation of the object.
If to_concise_xml is passed an instance that has fields containing other instances,
they will all be printed out in full.
If an instance appears more than once in the nested object being printed out,
then a representation is printed that, upon being read back in,
will have just one object at both locations. This is sometimes refered to
as the ability to do "circular printing", since an object can be printed that
has itself as a value of a field.
Unlike to_h2o, to_concise_xml will make a path for the top level object if it can.
to_xml makes an XML 1.0 syntax of an object whereas
to_concise_xml makes a less verbose, more programmer friendly representation
that's still very similar to pure XML.
Examples: thing.number.<to_concise_xml/> returns "thing.number"
<thing weight=246/>.<to_concise_xml/> returns "<thing weight=246/>"<to_h2o only_print_instances=false />
to_h2o is similar to to_concise_xml except that when printing the object it
is called with, it tries to print a full representation of the object.
For instance,
- when given a method it will print out the full source code
of the method, not just a path to the method
- when given a cached instance, it will print out the full representation
of the object, i.e. all its fields. Values of the fields will be printed
with to_concise_xml so those may be printed as paths.
- when given a class, it will print out the source code of the class,
any methods in the class, any cached instances, and do the same for
any subclasses recursively on down.
to_h2o tries hard to print circular references a la to_concise_xml so that
an object that appears more than once in the tree will be represented by exactly
one object once the result of to_concise_xml is executed.
to_h2o has a parameter: only_print_instances whose default value is false.
If the value is true, then when to_h2o is called with a class, that class
will not be printed nor will any of its subclasses. However, the cached
instances of the class will be printed for the top class and any of its subclasses.
You will want to use only_print_instances=true when you have a program
that defines a bunch of classes when it is laoded. During the
running of the program a bunch of cached instances are created.
These are the data that you want to save using to_h2o, so you execute:
filesystem.<file "logical://user/datafile.h2o"/>.<set content=
top_class.<to_h2o only_print_instances=true/>/>
to save out the instances.
You can read back in and execute via
filesystem.<file "logical://user/datafile.h2o"/>.content.<execute/>
or use the shortcut:
filesystem.<file "logical://user/datafile.h2o"/>.<execute/>
Execute will return the value of the last expression in the file.
But you won't really care since executing the file will side-effect
the appropriate classes by adding the cached instances to them.
If your application is dynamically creating classes that you want to
save out then call to_h2o with only_print_instances=false which is the
default value.<to_html />
year:month:day hour:minute:second
<to_html_attr key="" />
to_html gets the string to use for each attribute value by calling to_html_attr. The default version of this simply calls to_html on the attribute value, but it may be customized for different value types. to_html_attr is expected to return a string. If the string starts and ends with a single quote or double quote it will be used as is. Otherwise it will automatically have a single or double quote wrapped around the string to make it proper XHTML.
<to_literal />
If the subject is a literal, returns a string representation of it that can be read back in by Water to produce that literal. If the subject is not a literal, returns false. Literals include: true, false, null, numbers, strings, and chars. Example: 123.<to_literal/> reutrns "123", a string containg just three digits. Example: "what's\n up doc?".<to_literal/> The returned string has a first and last character of double-quote and includes the character sequence backslash n so that the newline it represents will be encoded properly if this string is to be read back in.
<to_numbers />
Given a vector of objects (typically numbers or strings representing numbers)
return a vector of only numbers.
The method to_number is used to convert every value.
If to_number cannot convert a value that vallue will not be included in the resulting vector,
so the resulting vector may be shorter than 'this'.
<example <vector "10" "2.1" 30/>.<to_numbers/>.<combine number.plus/>
42.1 /><to_object />
Creates an object picking out parts of the "_subject" string with field_separator and calling maker with those parts as objects. field_separator can either be a pattern that indicates wehre to split the string (such as the newline_patter which is the default), or a vector of integer pair indecies into the string determining which characters to grab for each field. If their is an odd number of integers passed in, a new integer will be added of the length of the "_subject" string. See "subvectors" documentation. Maker is either a method or an object. If it is a method, it is called with arguments of the parts of the "_subject" string that are determined by field_separator. If it is not a method, then maker is the parent of a new object which is constructed by passing in the field values to constructor call for maker. subject_for_maker is the object used for "_subject" when maker is called. There are two special values for this argument. The default value for subject_for_maker is "_use_maker" which simply means use the value of maker for _subject. If the value is "_first_value" then the first field value from the "_subject" string is used as the "_subject" for the maker call. If trim_fields is true, then whitespace will be removed from each end of each field value before it is used in constucting the object. See also: subvectors, to_objects
Splits the "_subject" string into substrings each of which are then passed off to to_object to make into an object. A vector of the objects is returned. The default object separator is the newline pattern. The default field_separator is the comma pattern. The default maker is vector. Using all the defaults, to_objects splits a comma_separated_value (csv) string into a vector of vectors Each inner vector represents a line of the input string that has field values of the strings between the commas. If trim_subject is true (the default), the input string will have whitespace removed from its beginning and end before any other processing. If trim_fields is true (the default is false), then once '_subject' has been split into one string for each object, and each of those strings is split into indivdual field values, those field_value strings will have whitespace removed from their begginning and end before using them for field values. See to_object, subvectors, pattern
<to_path relative_to=null />
Returns a string of a Water source code path that, when executed, will return _subject. If the subject is a literal, then the result of calling to_literal on the subject is retuned. else if the subject is _subject is a defclass, a defmethod, or a cached instance, then a path to the object is returned. Otherwise, false is returned. Example: thing.number.<to_path/> returns "thing.number"
<to_plain_text print_key=true field_separator="\n" key_value_separator="=" />
to_plain_text is good for printing a human-readable version of an object to be sent as plain text in an email or .txt file. Returns a readable string with no embedded hypertext tags. It prints the strings in the content for hypertext objects. 'Thing' prints value of the string keys with a newline between each field. It flattens the object and therefore isn't good for printing nested objects to be read again. If you would like the key printed for fields of a 'thing', use print_key=true. See also to_html, to_concise_xml
<to_query_string />
Turns object into a query string format
<to_string />
Returns the result of calling java's toString on "_subject". This is the lowest level printer and is useful when you want an object representation that is short, fast to make and doesn't give much detail. Example: <thing weight=246/>.<to_string/> returns "<thing .../>" In most cases including the one above, the returned string cannot be read back in to Water.
<to_uri form_or_page_object=optional server_object=optional />
Takes any object and returns a URI that represents a path to the object. Takes an optional object that is the base object in which the path should be relative to. Won't yet calculate ".." references.
<to_xml namespace_record=null />
Returns a string representing "_subject". The string is pure xml. It has proper xml element names, all attribute values are strings, all ending tags are full_named ending tags. The resulting xml can be read back in and will create a Water object similar to "_subject". See also to_concise_xml, to_html.
When subject is a string,
returns a new string similar to "_subject" but with the whitespace removed from both ends.
Example: " abc ".<trim/> returns "abc"
When subject is a vector, returns a new vector with whose items are the same as
_subject except that the beginning and ending items that are equal to 'pattern' are removed.
pattern defaults to "".
Examples:
<vector "" "" "hey" "baby" "" "" ""/>.<trim/> returns <vector "hey" "baby"/>
<vector 2 2 2 3 4 5 2 2/>.<trim 2/> returns <vector 3 4 5/><try time_limit=null rest=required='ek_expression' />
Try executes its "rest" arguments and returns the value of the last one
unless there's an error in which case it executes its content and returns
the last value of the content.
Example: <try 234 <error "busted"/> 567 > "we had an error"</try>
First 234 is executed to get 234, then the cal to error is executed but this
will error because, well that's what a call to "error" does. Due to the error,
the content of the call to 'try' will be executed. This returns the
string "we had an error".
Example: <try 234 567 > "we had an error"</try> returns 567 because there
is no error. The content of the call to try is never executed.
When the content of a try is executed, a local variable named 'error_object'
is bound to the string of the error message that was created by executing
the attributes to try.
Example:
<try 234 <error "busted"/> 567> "This call had: ".<concat error_object/></try>
Returns the string: "This call had: Runtime error:\nbusted"
You can limit the amount of time that 'try' will try to execute its
attributes before calling the error code in the content.
Example:
<try time_limit=10 <defmethod infinite_loop> <infinite_loop/> </> <infinite_foo/>>
"it timed out." </try> returns "it timed out".
Since the method infinite_loop calls itself, normally it will not terminate until
your computer runs out of resources. However our time_limit argument specifies
that it will only run for 10 milliseconds until try itself terminates the
infinite loop and executes the code in the content of the call to 'try'.
If you want to protect against the content of a try call causing an error,
wrap another try statement all around the first one, with the first one
being the first argument to the new outer try statement and the content
of the new try statement being the code that's run if the inner
content execution causes an error.
See also "error" and "do".type.<all_of rest=required />
Specifies a type wherein the object being specified must have
all of the listed types to be of this type.
Examples:
type.<all_of number integer/>.<is_type_for 2468/> returns true
type.<all_of number integer/>.<is_type_for 24.68/>
returns false because lathough 24.68 is a number,
it is not an integer.type.<call_method_of a_method=required />
Specifies a type such that if the object in question is passed
as the subject to the method within call_method_of and that
call returns true, then the object is of that type.
Example:
<set starts_with_x_of=type.<call_method_of <defmethod>
_subject.<is_a string/>.<and
_subject.<starts_with "x"/>/>
</defmethod>/>/>
starts_with_x_of.<is_type_for "x_rated"/> returns true
starts_with_x_of.<is_type_for "y_rated"/> returns false
starts_with_x_of.<is_type_for 917/> returns false
call_method_of is the most flexible of types allowing you to write
arbitrary code to determine the 'typeness' of an object.type.<literal />
An object is a literal if it is: null, a number, a character, a boolean, or a string. Example: literal.<is_type_for 23/> returns true.
type.<not_of rest=required />
An object is of not_of type if it is not of any of the supplied types
to not_of.
Examples: All of the follwing expressions return true.
<type.not_of 0/>.<is_type_for 1/>
<type.not_of <type.one_of -1 0 1/>/>.<is_type_for 6/>
<type.not_of <type.one_of -1 0 1/>/>.<is_type_for -1/>.<not/>
<type.not_of string integer/>.<is_type_for 2.3/>
<type.not_of string integer/>.<is_type_for 2/>.<not/>type.<one_of case_sensitive=true=boolean include_same_objects=true=boolean include_sub_objects=true=boolean include_defclasss=false=boolean rest=required />
one_of is the most commonly used type.
Examples:
type.<one_of "red" "white" "blue"/>.<is_type_for "blue"/> returns true
type.<one_of "red" "white" "blue"/>.<is_type_for "pink"/> returns false
type.<one_of "red" "white" "blue"/>.<is_type_for "BLUE"/> returns false
type.<one_of "red" "white" "blue" case_sensitive=false/>.
<is_type_for "BLUE"/> returns true
The optional parameters include_same_object, include_sub_objects, and
include_defclasss provide precise control over matching.
The default settings let you treat objects created by defclasss as
'classes' For example:
type.<one_of number/>.<is_object_for 3/> returns true
type.<one_of number/>.<is_object_for integer/> returns false
type.<one_of number/>.<is_object_for number/> returns false
though non-classes in the type definition match other instances as in:
type.<one_of 3 5 7/>.<is_type_for 5/> returns true
Thus the default settings fulfill a large majority of uses.
However, if you want to do something else, pick different values for
these settings. Say you want to write a type that includes
the integer and boolean objects but NOT actual integer instances
and not true & false.
type.<one_of integer boolean include_defclasss=true
include_sub_objects=false/>
Here's a list of possibilities:
Use Cases: include_same_objects include_sub_objects include_defclasss
exact match only true false true
all below _subject but not _subject false true true
all below _subject and _subject true true true
only _subject excluding defclasss: true false false rare, needed only programatically
all below _subject but not _subject excluding defclasss false true false
all below _subject and _subject excluding defclasss true true false the default
exclude everything false false false/true
Examples:
type.<one_of string boolean/>.<is_type_for "blue"/> returns true
type.<one_of string boolean/>.<is_type_for false/> returns true
type.<one_of string boolean/>.<is_type_for string/> returns false
type.<one_of string boolean include_defclasss=true/>.<is_type_for string/> returns true
type.<one_of string boolean include_defclasss=true/>.<is_type_for "hi"/> returns true
type.<one_of string boolean include_same_objects=true include_sub_objects=false/>.
<is_type_for "hi"/> returns false
Note that:
type.<one_of integer include_same_objects=true include_defclasss=false/>.
<is_type_for integer/> returns false
because include_defclasss over rules a include_same_objects setting
of true.type.<one_of.random_instance />
First one of the values in the one_of is selected with equal probability.
If that item is a defclass in its container, then random_instance is
called on it and the result is returned.
Otherwise, the item from the one_of itself is returned.
Examples: <one_of 3 5 7 />.<random_instance/> returns 3, 5, or 7.
<one_of boat car/>.<random_instance/>
If boat and car are declasses in their container, then
an instance of one of those classes will be returned.type.<range_of min=null max=null include_min=true include_max=true number_type=number.integer />
An object is of type range_of if it is a number between min and max.
Examples:
<range_of min=0 max=10/>.<is_type_for 3/> returns true
<range_of min=0 max=10/>.<is_type_for 333/> returns false
Min and max default to null meaning they are unbounded.
include_min and include_max tell whether the range includes the
given min and max values. The default for both is true.
Number_type should be one of number, integer, or float.
It defaults to integer.type.<range_of.random_instance />
Creates a number between the range min and the range max,
excluding the max.
Example: type.<range_of 5 10/>.<random_instance/> returns 5, 6, 7, 8, or 9.
See also: integer.random_number, float.random_number
type.one_of.random_instance, thing.random_instance.type.<vector_of min_length=0 max_length=null rest=required />
An object is of vector_of if it is of length between min_length and
max_length inclusive and each vector_key of the object holds
a type that matches the types given in the rest arguments.
If the object has a length longer than the number of rest args supplied,
then the last rest arg is used as the type to test the remaining
elements in the vector.
If no rest args are passed when calling vector_of, it is the same
as if one rest arg of 'thing' was supplied, ie all elements will pass.
vector_of is quite flexible as it can be used to check that
the length of a vector is at least a certain amount but
no more than another amount as well as the type
of every element in the vector, each of which may be different or
all may be the same.
If max_length is null, that means that the maximum length of the vector is unlimited.
Examples: All of the following expressions return true.
<type.vector_of number/>.<is_type_for <vector 3 7/>/>
<type.vector_of number/>.<is_type_for <vector 3 "asd"/>/>.<not/>
<type.vector_of integer float/>.<is_type_for <vector 3 7.5/>/>
<type.vector_of integer float/>.<is_type_for <vector 3 7.5 3.4/>/>
<type.vector_of integer float/>.<is_type_for <vector 3 7.5 9/>/>.<not/>
<type.vector_of integer float max_length=2/>.
<is_type_for <vector 3 7.5 3.4/>/>.<not/>
<type.vector_of integer min_length=3/>.
<is_type_for <vector 88 89/> />.<not/>
<type.vector_of min_length=2 max_length=4/>.
<is_type_for <vector 111 222/>/>
<type.vector_of min_length=2 max_length=4/>.
<is_type_for <vector 111/>/>.<not/>A Water URI supports the URI specification from the W3C.
A URI is a uniform resource identifier and is used for
identifying resources on the Web. A URI can be created
in many different ways:
Parts of a URI encoded in a URI string:
<Example
<uri> http://www.clearmethods.com:8080/prod/buy?item=10 </uri>
/>
Parts of a URI specified as separate fields:
<Example
<uri port=8080 host="www.clearmethods.com" protocol="http"
query=<thing item=10/> path=<vector "" "prod" "buy"/>
/>
/>
URI path and query given as Water expression:
<Example
<uri <expr>prod.<buy item=10/></> > http://www.clearmethods.com:8080 </>
/>
Example of combining two URIs together:
<Example
<uri "http://www.clearmethods.com"/>.<uri> foo/bar </>
/>
A Water URI can have additional information such as the HTTP method
(GET, POST, etc.), HTTP header values, and body content.
<Example
<uri method="post"
Accept="*/*"
content_type="application/x-url-form-encoded"
body=<thing item=10/>
>
http://www.clearmethods.com
</uri>
/>
You can create relative URIs that do not have a protocol or host:
<Example
<uri> foo/bar </>
/>
URIs are intended to be read-only (immutable) data structures.
Once you create them, you should not modify them, but you can
create new URIs from existing URIs.
<Example
<set a_uri=
<uri "http://merlin:password@nitric.com:80/internal/foo?bar=2&baz=3#someplace"/>
/>
/>
<Example a_uri.protocol "http"/>
<Example a_uri.user_info "merlin:password"/>
<Example a_uri.host "nitric.com"/>
<Example a_uri.port 80/>
<Example a_uri.path <vector "" "internal" "foo"/> />
<Example a_uri.path_string "/internal/foo"/>
<Example a_uri.query_string "bar=2&baz=3"/>
<Example a_uri.query <thing bar=2 baz=3/> />
<Example a_uri.fragment "someplace"/>
<Example <uri>foo/bar?a=2&b=3</>.query_string "b=3&a=2" />
<Example <uri>foo/bar?a=2&b=xxx</>.query <thing a=2 b="xxx"/> />
<Example <uri>foo/bar?</>.query_string "" />
<Example <uri>foo/bar?</>.query <thing/> />
<Example <uri>foo/bar</>.query_string "" />
<Example <uri>foo/bar</>.query optional />
In file protocols user_info, host, port, and query are all irrelevent.
user_info, host and query are the empty string. Port is ignored.
Note that the "file" protocol is used for folders as well, though
Water does have both file and folder resource objects.<vector rest="unnamed" />
makes a java vector Example: <vector 2 4 3.<plus 3/> /> returns vector of 2, 4, 6
<vector_key />
Returns true if "_subject" is an integer, false otherwise. As an argument to for_each, etc for "include", _subject is processed specially to get just those integers that are more than or equal to 0 and less than the object length.
<warning message="a warning occured"=string />
Prints the string "WARNING: " followed by the message argument on the java console window. Message is usually a string but can be any object. See also: error
You can launch a Water Listener in a command prompt window on "Windows" operating systems by double_clicking on the file water/ide/water_listener.bat The listener lets you enter Water source code and see what it executes to. View the water_listener.bat file to see instructions on how to run any Water code upon launching the Water Listener. The listener displays help about its commands when you launch it.
<web a_request=required contract=null a_response=null />
A 'web' is a web resource that is similar in concept to a file resource.
It represents a connection and/or permission to access a remote web
resource. If a file resource requires a path to a file, the web
resource requires a URI to identify the location of the resource.
<Example
<web "http://www.clearmethods.com"/>
/>
To request the value of the resource as a string, use 'content':
<Example
<web "http://www.clearmethods.com"/>.content
/>
The following example creates a simple server to serve out
the number 42, and uses a 'web' to get the result as a number
using 'result'. 'result' will first get the contents as
a string, then execute the string to return a Water object.
<Example result=42>
<server 42/>
<web "http://localhost/"/>.result
</>
The following web resource represents a method:
<Example>
<server <defmethod get_quote arg> arg </> />
<set remote_get_quote=<web "http://localhost/"/> />
</Example>
Calling a remote web resource with arguments has exactly
the same structure as calling a local method.
<Example
<remote_get_quote arg=100/>
result=100
/>
Defining a web resource takes an optional contract. The
contract is a 'defclass' or 'defmethod' from Water Contract.
The contract is used to type-check the arguments before
making a remote request.
<Example>
<defmethod get_quote arg> arg </>
<server get_quote />
<set remote_get_quote=
<web "http://localhost/" contract=get_quote/>
/>
</Example>Executing the string of some random xml or executing a file of random xml will
likely error unless the element names in the xml have been defined as objects or methods.
For instance, while executing a call such as <boat />, if boat executes to null
such as when boat is not found, then the call will error.
However, Water provides a mechanism for catching such errors.
See "_if_missing_method".
You can define "_if_missing_method" to do anything you like.
If it is defined, it will be called when a looked up field is not found and whatever
value is returned by "_if_missing_method" is returned.
If we define _if_missing_method to call defclass with the name of the missing field,
then the field will no longer be missing, hence in our example above, foo will be
defined and a call to it won't error, it will just create a subobject of the new foo.
Example:
thing.<boat/> errors
<defmethod _if_missing_method the_key>
<defclass <force_ek_code the_key/>/>
</defmethod>
thing.<boat/> causes thing.boat to be a defclass and
creates a subobject of that defclass and returns it.
<boat/> Since now foo is a known field,
lookup finds boat and a subobject of it is created as usual with
a parent of boat.
This will get random xml into Water objects but we may not be completely happy with the results.
The reason is that one of xml's deficiencies is that you cannot put a non-string
as the value of an attribute.
So you'll see xml like:
<boat>
<anchor weight="500" material="lead"/>
</boat>
If we use our above mechanism and execute the call to boat, we'll get back
a subobject of boat:
<set my_boat=<string><boat> <anchor weight="500" material="lead"/> </boat></string> />.<execute_string/>
and we can access the anchor like so:
my_boat.content.0
But with a large number of elements within the content of boat which perhaps are in
any old order, just accessing them through the content field is not so clear.
You can write little functions to help you find the object in the content vector
whose parent is boat (using for example, "for_each" to go through the elements of the
content vector or "filter") but Water has another mechanism.
We can turn elements in the content of an object into regular fields of an
object with reasonable names using the method make_fields_from_content.
That method has its own documentation which you should read, but for a quick
example, using the my_boat of above,
my_boat.<make_fields_from_content/>
my_boat.anchor returns the anchor object, i.e. <anchor weight="500" material="lead"/>
Since we may want to perform this operation every time we create a boat,
we can define our boat as:
<defclass boat>
<defmethod init>
_new_object.<make_fields_from_content/>
</defmethod>
</defclass>
But suppose we want to handle all the never-before-seen objects within
our xml like this? We don't even know their names yet.
Extend our _if_missing_method method like so:
<defmethod _if_missing_method the_key>
<defclass <enforce_ek_code the_key/>>
<defmethod init>
_new_object.<make_fields_from_content/>
_new_object.<remove "content"/> <!-- now redundant -->
_new_object <!-- return the new object -->
</defmethod>
</defclass>
</defmethod>
Now every new defclass created by _if_missing_method will have an
init method that creates real named fields out of each element in the
content of our previously unknown element names. Creating subobjects of
these will permit easy access to their parts.
Example:
thing.<set
my_boat=<sailboat>
<sail color="white"/>
<hull color="blue">
<bow color="black"/>
<stern>
<rudder material="wood" surface="smooth"/>
</stern>
</hull>
</sailboat>
/>
thing.my_boat.sail.color returns "white"
Without doing the call to make_fields_from_content in the init method for
sailboat, we could have done thing.my_boat.content.0.color, though
we would have retrieved the hull color if the author of the xml had
reversed the order of the sail and hull elements in the content of the
sailboat element.
thing.my_boat.hull.bow.color returns "black"
thing.my_boat.hull.stern.rudder.material returns "wood"
If had control over the xml representing our boat, and had the flexibility
to code it in Water, we could have written:
thing.<set
my_boat=<sailboat
sail=<sail color="white"/>
hull=<hull color="blue"
bow=<bow color="black"/>
stern=<stern
rudder=<rudder material="wood" surface="smooth"/>
/>
/>
/>
/>
This syntax is considerably less ambiguous than the pure xml above because it allows us
to name our parts unambiguously. In xml as it is commonly used, an element name
such as "sail" stands both for the type of an element as well as the name
of a part within the container of the element. This doesn't permit us to name
our part differently than the type of the element, makes accessing the
part through traditional "DOM"s unnecessarily complex and, in general,
causes lots of confusion, especially for examples more complex than the above.
Sometimes XML authors will include a special attribute within a part to
name the part, i.e. <sail name="the_sail" color="white"/>
where the part name is embedded in the part value. This comes with
its own set of problems, such as when you want to move a part value to
be associated with a different part name and becomes impossible when
you want to have the same value be used for two different parts as is
common in normal object oriented programming.
The make_fields_from_content method takes an argument which lets you specify that
the part name will come not from the name of the parent of the element, but from
any attribute of the element you like, such as "name". See the make_fields_from_content.
By using make_fields_from_content you can make the best of the bad situation that
the ambiguous syntax of XML has caused. But you have quite a number of other options
including:
- Referencing XML "parts" via the content field of an object using integer indexes
- Referencing XML "parts" via the content field then using a Water filter to find a
given part based on the value(s) of its field(s)
- Recode the XML using Water's syntax for specifying elements as values of attributes
like in the example above, i.e. <sailboat sail=<sail color="white"/> />
Note that this is illegal in pure XML, a design flaw that's the source of
many problems with XML. When you use this solution or the one below, you
don't need to employ make_fields_from_content.
- Recode using Water's pure XML syntax for specifying fields with complex values, i.e.
<sailboat><attributes> sail=<sail color="white"/></attributes></sailboat>
- You can use a combination of the above techniques plus the full power of Water to
create your own domain-specific solutions. This may include using defclass to
define specific element names that you care about, giving each their own
init method tailored for the idiosyncrasies of how that element is used.
There are special defclass for ?xml and !doctype.
A call of <?xml version="1.0" standalone="yes" encoding="US-ASCI" ?>
will create an object with a parent of thing.?xml that has the corresponding 3 fields.
The fields standalone and encoding are optional.
A call of <!DOCTYPE some text> will create an object with a parent of thing.!doctype
that has one field named "attributes_string" that contains all the text between
!doctype and close angle. This text must not contain any close angle brackets so right now
the !doctype element can only be used for describing external dtds.