Vision Language Basics
Overview
The Vision language is designed around the concept of communicating objects. Objects interact with one another via a process known as "sending a message". A message is a request for an object to carry out one of its operations. In the example:
universe select: [ score > 10]the message select: is sent to the object named universe. Some messages require parameters. For example, to send the select: message, you provide a parameter that represents your selection criteria. In the example, the select: parameter is [score > 10].
All requests in Vision conform to this object/message pattern known as a Message Expression. Message expressions always produce an object as a result. In the preceding example, the expression produces a new object which represents the list of companies that satisfied the criteria.
The general form for a message expression is:
object message
A message expression includes a recipient object, a selector, and possibly some parameters. The Recipient is the object to which the message is sent. The Selector is the name of the message. A Parameter or Argument is an extra piece of information needed to execute the message. Messages can have any number of parameters (including none).
Messages
There are three types of messages:
- Unary Messages (no parameters)
- Keyword Messages (one or more parameters)
- Binary Messages (special form of single parameter message)
Unary Messages
Messages without arguments are called Unary Messages. These messages are called unary because only one object, the recipient, is involved in the expression. The general form for a unary message expression is:
recipient unaryMessageSelector
Examples of unary message expressions are:
- gm sales
- gm industry
- portfolio totalValue
- quantity sqrt
- myCompanyList count
- account7 manager
Keyword Messages
The general type of message with one or more parameters is the Keyword Message. The selector of a keyword message is composed of one or more Keywords, one preceding each parameter. A keyword is a name followed by the : character. Each keyword is followed by a parameter value. The general form for a keyword message is:
recipient keyword1: parameter1 keyword2: parameter2 ...Examples of single keyword message expressions are:
- universe select: [score > 20]
- mylist union: yourlist
- gm :sales changeLag: 1 years
- gm :earnings asOf: 8705
The parameter of the select: message is the criteria to be used to choose companies from your universe. The parameter of the union: message is the list you wish to combine with an initial list. The parameter of the changeLag: message is the offset you wish to use to compute the absolute change in value. The parameter of the asOf: message is the date for which you wish to retrieve data.
A message with two parameters will have a selector with two keywords. Each keyword is followed by a parameter value. Examples of expressions using double keyword messages are:
- value within: x percentOf: y
- :earnings asOf: 8705 put: 17.3
When the selector of a multiple keyword message is referred to independently, the keywords are concatenated; therefore, the names of the last two messages are within:percentOf:, and asOf:put:. There can be any number of keywords in a message. For example, the expression:
sales > 1000 ifTrue: [ "Large Sales" ] ifFalse: [ "Small Sales" ] else: [ "No Sales" ]uses a message containing three keywords. This message is referred to as the ifTrue:ifFalse:else: message.
Binary Messages
The Binary Message is a special type of message expression that takes a single parameter. The general form for a binary message is:
recipient binaryMessage parameterBinary messages differ from other messages in that there is a pre-defined, fixed set of these messages that are built into the system.
The valid binary messages are:
+ addition - subtraction * multiply / divide = equal == identical to < less than <= less than or equal to > greater than >= greater than or equal to != not equal to !== not identical to && and || or , append <- left assignment -> right assignment
As with single parameter keyword messages, the binary messages work with two objects, the recipient and a single parameter. The binary messages do not require a ':' character to separate the selector from the parameter. Examples of binary messages are:
- 3 + 4
- score > 20
- price / earnings
- gm sales + ford sales
The library of messages available in Vision is constantly expanding. In addition, you may create and redefine unary and keyword messages as often as needed. You cannot directly add new binary messages; however, you can interactively redefine how a binary message operates in a specific situation. More detailed information on defining messages is available.
Names, Variables, and Assignment
Selectors are objects that represent the strings used to name objects and messages in the system. Selectors are also referred to as Message Names or Names. Names appear throughout the examples in this document. For example, the name gm has been used to refer to the object representing the company General Motors, the name eps has been used to refer to a time series of gm's earnings per share values, and the name select: has been used to refer to a message that applies a selection criteria to a list.
The literal representation of a name is a sequence of letters, digits and the character '_'. A name can contain any number of these characters, but cannot begin with a digit. Upper and lower case letters can be used and are considered to be distinct characters. The following names are valid:
- x
- myVariable
- variableName1
- variable_name
- __tmp
- 1x
- abc$
- 3rd variable
are not valid. 1x is invalid because it begins with a digit. abc$ is not valid because it contains an illegal character.
Any character (including spaces) can be included in a name if it "escaped" using the '\' character. The following variations on the previous examples are valid names:
- \1x
- abc\$
- \3rd \variable
As the third example illustrates, any number of "escaped" characters can be included in a name.
Names are used throughout the Vision environment in a number of forms. When you define fixed and time series properties, you supply a selector as the argument to the defineFixedProperty: and define: messages. When you define a class constant, you supply a selector as the first argument to the define:toBe: message. When you define a method, you supply a selector to define the name of the method. For example:
myClass defineFixedProperty: 'fixed' ; yourClass define: 'ts' ; ourClass defineMethod: [ | runReport | ... ] ;defines the name fixed as a fixed property of the class myClass, defines the name ts as a time series property of the class yourClass, and defines the name runReport as a method of the class ourClass.
Notice that the names used to define properties and constants are enclosed in single quotes. The single quotes identify that the name is a selector and not a string. Enclosing the name in double quotes would work as well; however, if you provide the single quote (i.e., the selector) version, your name will be checked to make sure it is a valid name. For example:
Object define: 'variable name' ;produces a syntax error whereas:
Object define: "variable name" ;does not.
Names used to store values are often referred to as Variable Names or Variables. The result of any Vision expression can be saved into a variable. For example, in the expression:
!x <- 2 + 2the name x is used to store the result of evaluating the expression 2 + 2. If you then execute the expression:
x + 1Vision will use the stored value of x (4) to evaluate the expression and return the result 5.
To create a variable, type ! followed by a valid name. The <- and -> messages are used to assign a value into this variable. Note that the assignment messages are formed using the two characters '<' and '-' or '-' and '>'. For example:
!x <- 2 ; !y <- 3 ; 4 -> !z ;Variables can be used to store values other than numbers. You can save the results of any Vision expression by assigning the expression to a variable name. For example:
- !autoSales <- gm sales + ford sales
- !universe <- mylist union: yourlist
- !optimalList <- universe select: [score > 20]
You can create as many variables as you need during the course of your session. You have complete discretion over the names you use. Names can contain any number of characters. You should choose names that are easy to remember and somewhat descriptive. Any information that you save into a variable is available for the remainder of your session or until you redefine the variable.
One additional fact is needed to complete this discussion of variable assignment. If you want to assign a new value to a name that already is in use, you should prefix the name by the ':' character instead of the '!' character as shown below:
:x <- 17 ;The '!' character tells Vision to create a new variable using the name provided. A variable name prefixed by the ':' character tells Vision to change the value of an existing variable. In many cases, you can use the two forms interchangeably. Note that updating a variable is identical to updating a fixed property. In fact, a variable really is a fixed property of the environment in which it is defined. More detailed information about environment layers is available.
When you place the ':' character in front of a name, you are requesting the Intensional Form of the value. The intensional form of a property is used to update its value. The intensional form of a method is used to display its definition.
Expressions
The act of "sending a message" to an object always produces another object as a result. For example the expression:
gm salesreturns a numeric value, the expression:
gm industryreturns an industry, and the expression:
universe select: [score > 20]returns a list of companies. This resultant object can act as the recipient for another message.
An Expression in Vision consist of a series of messages applied in succession. For example, the expression gm industry returns an object representing GM's industry. The message sales could be sent to this industry to return the total sales for the industry. The expression:
gm industry saleswould therefore return the total sales for gm's industry. In this example, the expression gm industry produces an object representing GM's industry. Sending the message sales to this object produces a new object representing the total auto industry sales as illustrated below:
Expressions provide a simple way to
from one object to another. Expanding on the earlier definition, the general form for a Vision expression is:recipient message1 message2 message3 ...Each message is sent to the resultant object of the previous message expression as shown below:
For example, the expression:
gm sales + ford salescould be used to add the sales figures for the two companies. The expressions gm sales and ford sales each returns an object representing a numeric sales value. Sending the message + to GM's sales instructs it to add Ford's sales to it, producing a new value.
The expression:
gm :eps asOf: 8705could be used to access a specific data point from GM's time series of earnings values. The expression gm :eps returns an object that is a time series representing GM's earnings. The keyword message asOf:8705 could be sent to this time series to access the earnings value as of May.
The expression:
universe select: [score > 20] . countcould be used to find out how many companies in universe passed the screen. The keyword message expression universe select: [score > 20] returns an object which is a list of those companies that met the criteria. Sending the message count to this new list will return the number of companies in the list.
A Parameter is really just an expression that is supplied as an argument to a binary or keyword message. Parameter values can be as simple as an explicit number or string or a named object. Any expression can also be used as a parameter. For example, you could add GM's industry sales to 100 using the expression:
100 + gm industry salesThis expression computes the sales value and adds it to 100.
Expressions must begin with a selector (i.e., the name of any object) or a literal. A Literal is a Number, a String, a Block, or a Magic Word. Expressions cannot start with binary or keyword messages. The following examples are NOT valid expressions:
+ 3 (incorrect expression) define: 'newProperty' (incorrect expression)Since the + and define: messages must be sent to a named object or a literal, both of these expressions would generate a syntax error.
A literal can only be the first object in an expression. For example, you cannot send the message 100 to gm:
gm 100 (incorrect expression)This request would generate a syntax error as well.
Printing
When you execute an expression, Vision automatically sends the message print to the final result. In other words, when you submit the request:
3Vision actually evaluates the expression:
3 printand therefore prints the value 3 when it is done. If you submit the request:
3 printyou will see the result, 3, printed twice. The first 3 is the one you explicitly requested; the second is Vision automatically sending the print message to the result. All objects in the system have a default way in which they print. For example, integers are right justified in a nine character field and print with no decimal places and decimal numbers are right justified in a nine character field and print with two decimal places. Strings are left justified when they are printed. You can redefined the behavior of the print message by class as needed. In addition, many variations on the print message have been defined to allow you to specify output widths, commas in numeric fields, and justification.
For example, the print: message requires a single parameter that supplies a print format. The format can be an integer or decimal number. The integer portion of the format specifies the total width of the output. If a decimal value is provided, the decimal portion indicates the number of decimal places to print if appropriate. For example, the expression:
10.123 print: 7.2 ;displays the number in 7 total character positions with 2 decimal places. The number is right-justified by default. The expression generates the output:
##10.12where the # character indicates a blank space. The messages printNL and printNL:are identical to the print and print: messages, except they automatically print a new line character after printing.
More detailed examples of printing and formatting techniques are available.
Defining Lists
Instances of the class List represent collections of objects that are used as a unit or referenced positionally. A list is updated by appending objects to its end.
One way to create a list is to use the ',' binary message to append objects together. For example, the expression:
!sampleList <- 10, -3, 20, 132 ;creates a list of four integers and saves the list as the variable named sampleList. Any type of object can be included in a list and the list can contain objects from multiple classes. For example, the expression:
!mixedList <- 1, "xyz", TRUE, NA, -3.45 ;creates a list of five objects representing five distinct classes (Integer, String, TRUE, NA, and Double).
The binary message ',' changes the recipient list directly. For example:
sampleList , 100modifies the list in sampleList by appending the object 100 to the end of the list.
More detailed information about creating and operating on lists is available.