Beruflich Dokumente
Kultur Dokumente
Apple Computer, Inc. 1993, 1994, Apple Computer, Inc. All rights reserved. No part of this publication or the software described in it may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Computer, Inc., except in the normal use of the software or to make a backup copy of the software. The same proprietary and copyright notices must be afxed to any permitted copies as were afxed to the original. This exception does not allow copies to be made for others, whether or not sold, but all of the material purchased (with all backup copies) may be sold, given, or loaned to another person. Under the law, copying includes translating into another language or format. You may use the software on any computer owned by you, but extra copies cannot be made for this purpose. Printed in the United States of America. The Apple logo is a registered trademark of Apple Computer, Inc. Use of the keyboard Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. No licenses, express or implied, are granted with respect to any of the technology described in this book. Apple retains all intellectual property rights associated with the technology described in this book. This book is intended to assist application developers to develop applications only for licensed Newton platforms.
Apple Computer, Inc. 20525 Mariani Avenue Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, APDA, AppleLink, LaserWriter, Macintosh, and Newton are trademarks of Apple Computer, Inc., registered in the United States and other countries. The light bulb logo, MessagePad, NewtonScript, and Newton Toolkit are trademarks of Apple Computer, Inc. Adobe Illustrator and PostScript are trademarks of Adobe Systems Incorporated, which may be registered in certain jurisdictions. FrameMaker is a registered trademark of Frame Technology Corporation. Helvetica and Palatino are registered trademarks of Linotype Company. ITC Zapf Dingbats is a registered trademark of International Typeface Corporation. Simultaneously published in the United States and Canada.
ALL IMPLIED WARRANTIES ON THIS MANUAL, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE LIMITED IN DURATION TO NINETY (90) DAYS FROM THE DATE OF THE ORIGINAL RETAIL PURCHASE OF THIS PRODUCT. Even though Apple has reviewed this manual, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS MANUAL, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS MANUAL IS SOLD AS IS, AND YOU, THE PURCHASER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS MANUAL, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modication, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specic legal rights, and you may also have other rights which vary from state to state.
LIMITED WARRANTY ON MEDIA AND REPLACEMENT If you discover physical defects in the manual or in the media on which a software product is distributed, APDA will replace the media or manual at no charge to you provided you return the item to be replaced with proof of purchase to APDA.
P R E FA C E
Related Books
This book is one in a set of books included with Newton Toolkit, the Newton development environment. Youll also need to refer to these other books in the set:
n
Newton Programmers Guide. This book is the denitive guide and reference for Newton programming. This book explains how to write Newton programs and describes the system software routines that you can use to do so.
xi
P R E FA C E
Newton Toolkit Users Guide. This book introduces the Newton development environment and shows how to develop Newton applications using Newton Toolkit. You may want to read this book rst if you are a new Newton application developer. Newton Book Maker Users Guide. This book describes how to use Newton Book Maker and Newton Toolkit to make Newton digital books and to add online help to Newton applications. This book is included only if you purchased the Newton Toolkit package that includes Book Maker. Newton Human Interface Guidelines. This book contains guidelines to help you design Newton applications that optimize the interaction between people and Newton devices.
Sample Code
The Newton Toolkit product includes many sample code projects. You can examine these samples, learn from them, experiment with them, and use them as a starting point for your own applications. These sample code projects illustrate most of the topics covered in this book. They are an invaluable resource for understanding the topics discussed in this book and for making your journey into the world of Newton programming an easier one. The PIE Developer Technical Support team continually revises the existing samples and creates new sample code. You can nd the latest collection of sample code in the Newton developer area on AppleLink. You can gain access to the sample code by participating in the PIE developer support program. For information about how to contact Apple regarding the PIE developer support program, see the section Developer Products and Support, on page xiv.
xii
P R E FA C E
Boldface. Key terms and concepts appear in boldface on rst use. These terms are also dened in the Glossary. Courier typeface. Code listings, code snippets, and special identiers in the text such as predened system frame names, slot names, function names, method names, symbols, and constants are shown in the Courier typeface to distinguish them from regular body text. If you are programming, items that appear in Courier should be typed exactly as shown. Italic typeface . Italic typeface is used in code to indicate replaceable items, such as the names of function parameters, which you must replace with your own names. The names of other books are also shown in italic type, and rarely, this style is used for emphasis.
Syntax Conventions
The following syntax conventions are used to describe NewtonScript expressions in this manual. literal italics [] Courier text indicates a word or character that must appear exactly as shown. Italics indicate something you must replace with anything that matches its denition. Brackets indicate that the enclosed item is optional.
xiii
P R E FA C E
{choose|one}
A group of words, separated by vertical bars (|) and grouped with curly brackets, indicates an either/or choice. An asterik (*) indicates that the preceding item(s), which is enclosed in square brackets, can be repeated zero or more times. A plus sign (+) indicates that the preceding item(s), which is enclosed in square brackets, can be repeated one or more times.
[]*
[]+
Fax AppleLink
xiv
P R E FA C E
If you provide commercial products and services, call 408-974-4897 for information on the developer support programs available from Apple.
xv
Contents
Figures, Tables, and Lisings ix
Preface
xi
About the Audience xi Related Books xi Sample Code xii Conventions Used in This Book Special Fonts in Text xiii Syntax Conventions xiii Developer Products and Support
xiii
xiv
Chapter 1
Overview
1-1
Introduction 1-1 Semantic Overview 1-2 Expressions 1-2 The Object Model 1-2 Data Types and Classes 1-3 Scope 1-4 Extent 1-6 Garbage Collection 1-6 How Is NewtonScript Dynamic? Basic Syntax 1-8 Semicolon Separators 1-8 In-Line Object Syntax 1-9 Character Set 1-9 Comments 1-10 A Code Example 1-10
1-7
iii
Chapter 2
2-1
2-21 2-25
iv
Chapter 3
Flow of Control
3-1
Compound Expressions 3-1 IfThenElse 3-2 Iterators 3-3 For 3-4 Foreach 3-6 Loop 3-10 While 3-11 Repeat 3-12 Break 3-12 Exception Handling 3-13 Working with Exceptions 3-14 Dening Exceptions 3-15 Exception Symbol Parts 3-16 Exception Frames 3-16 The Try Statement 3-18 Throwing Exceptions 3-18 Throwing an Exception to Another Handler Catching Exceptions 3-20 Responding to Exceptions 3-22
3-20
Chapter 4
4-1
About Functions and Methods 4-1 Func Denition 4-2 Return 4-2 Messages 4-3 Message-Send Operators 4-3 Function Invocations 4-7 Call With 4-7 Global Function Invocation 4-8 Global Function Denition 4-8 Passing Parameters 4-9 Function Objects 4-9
Function Context 4-10 The Lexical Environment 4-10 The Message Environment 4-11 An Example Function Object 4-12 Using Function Objects in Advanced Ways
4-13
Chapter 5
5-1
Inheritance 5-1 Prototype Inheritance 5-2 Creating Prototype Frames 5-2 Prototype Inheritance Rules 5-3 Parent Inheritance 5-4 Creating Parent Frames 5-4 Parent Inheritance Rules 5-5 Combining Prototype and Parent Inheritance 5-5 Inheritance Rules for Setting Slot Values 5-7 An Object-Oriented Example 5-8
Chapter 6
Built-In Functions
6-1
Object System Functions 6-2 String Functions 6-8 Bitwise Functions 6-13 Array Functions 6-13 Integer Math Functions 6-20 Floating Point Math Functions 6-22 Managing the Floating Point Environment Financial Function 6-38 Exception Functions 6-38 Message Sending Functions 6-40 Data Extraction Functions 6-42 Data Stufng Functions 6-46 Miscellaneous Functions 6-50 Summary of Functions and Methods 6-53 vi
6-35
Appendix A
Reserved Words
A-1
Appendix B
B-1
Appendix C
Class-Based Programming
C-1
What Are Classes Good For? C-1 Classes: A Brief Reminder C-2 Inheritance in NewtonScript C-3 The Basic Idea C-3 Practical Issues C-6 Class Variables C-7 Superclasses C-9 Using Classes to Encapsulate Soup Entries ROM Instance Prototypes C-10 Leaving Instances Behind C-11 Conclusion C-11
C-10
Appendix D
D-1
Appendix E
E-1
vii
Glossary
GL-1
Index
GL-1
viii
Chapter 1
Overview
Figure 1-1 Listing 1-1 Listing 1-2
Chapter 2
Characters with special meanings 2-4 Codes for specifying special characters within strings 2-8 Special slot names and their specications 2-13 Constant substitution work-arounds 2-18 Operator precedence and associativity 2-32
Chapter 3
Flow of Control
Figure 3-1 Table 3-1 Table 3-2 Table 3-3 Listing 3-1 Listing 3-2 Listing 3-3
Result comparison for the iterator foreach and foreach deeply 3-10 Exception frame data slot name and contents Exception frame examples 3-17 Exception symbol 3-15 The Throw function 3-19 Several onexception clauses ordered improperly 3-21
3-16
ix
The onexception clauses properly ordered Handling a soup store exception 3-22 An exception handler checking the exception frame 3-23
3-22
Chapter 4
4-1
The parts of a function object. 4-10 A run-time function object snapshot 4-13
Chapter 5
5-1
A prototype frame 5-2 A prototype chain 5-3 Parent-child relationship 5-4 Prototype and parent inheritance interaction order 5-6 An inheritance structure 5-9
Chapter 6
Built-In Functions
Table 6-1 Table 6-2
6-1
Floating point exceptions 6-35 Exception frame data slot name and contents
6-39
Appendix B
B-1
Character codes sorted by Macintosh character code B-1 Character codes sorted by Unicode
B-7
CHAPTER
Overview
NewtonScript is a state-of-the-art, dynamic, object-oriented programming language; developed for the Newton platform.
Introduction
In creating NewtonScript, the overriding goal was to enable developers to easily create fast, smart applications. Therefore the language had to be
n n n n n
effective; for its intended use of writing Newton applications expressive and exible; to make it straightforward to use consistent; to allow reuse of concepts and structures portable; to allow exploration of different architectures small; to allow it to work with limited RAM
The constraints of the Newton system required a language that could produce reusable code libraries, had both efcient use of memory and automatic garbage collection.
Introduction
1-1
CHAPTER
Overview
The language worked with principles that were used rst in languages like Smalltalk and LISP. NewtonScript was further inspired by work done on the language Self, at Stanford University.
Semantic Overview
This section briey introduces some of the special features of the NewtonScript language.
Expressions
NewtonScript is an expression-based language. Almost everything in NewtonScript returns a value. Therefore, we talk about expressions rather than statements in this manual.
immediatesin which the 32 bits contain immutable data references in which the 32 bits refer indirectly to an object
For more information about NewtonScript objects see Chapter 2, Objects, Expressions, and Operators.
1-2
Semantic Overview
CHAPTER
Overview
Listing 1-1
A simple frame
In the Newton system, objects can be typed further. For instance, the values of name and company are plain strings. However, phones could be further dened as being of type workPhone and faxPhone. These user-dened objects could then be manipulated by the Newton system in different ways. For instance, when the person using your application chooses to send a fax phone number, a set of actions different from those for a work phone number are initiated. The data object constructed in Listing 1-1 is shown inFigure 1-1. The facility that lets the system know about the type of an object is known as latent typing. Types are associated with objects. This means that a variable can hold any kind of object and can hold different types of objects at different times. For more information about specic NewtonScript objects see Chapter 2, Objects, Expressions, and Operators.
Semantic Overview
1-3
CHAPTER
Overview
Figure 1-1
Note
Smalltalk enthusiasts should note that NewtonScript classes have nothing to do with class-based programming as in Smalltalk. You can, however, use class-based programming concepts to organize parts of your NewtonScript application. For more information about this see Appendix C, Class-Based Programming. u
Scope
The part of a program within which a variable can be used is called the scope of the variable. Normally a variable is available within the function where it is dened, although slots that are used like variables can also be inherited from proto and parent frames. See Frame beginning on page 2-11, and Chapter 5, Inheritance and Lookup, for more information about frames and inheritance, respectively. When looking up the value of a variable, NewtonScript rst searches local variables, then inherited variables, through the proto and parent chains, as described in Chapter 5, Inheritance and Lookup, and nally global variables. 1-4
Semantic Overview
CHAPTER
Overview
Within the code segment aFrame:= {foo: 10, bar: func(x) begin if foo then Print ("hello"); if x > 0 then begin local foo; //local variable to function foo:= 42; end return foo; end; } the local variable foo has its scope restricted to the function denition bar. Even though foo is declared within a begin end code segment, its scope is not conned by that construct. When foo is used in the expression, if foo then Print ("hello"); before it is declared as a local variable, it is already dened by the compiler as an implicit local and initialized to the value of nil. If the slot variable, foo, with the value of 10, is to be used as the value for foo, that is stated explicitly as if self.foo then Print ("hello"); Otherwise, the search for the value of the variable goes by the rules, rst to local variables, (the local variable foo = nil), then to global variables named foo, and then to inherited slot variables named foo. In this example, the compiler created a local variable foo which is local to the method bar and is not initialized until the If expression that assigns it the value 42 executes. Therefore, nothing is ever printed.
Semantic Overview
1-5
CHAPTER
Overview
When you send the message, bar, with a parameter value of ten, to the aFrame object, in the expression aFrame:bar(10) a value of 42 is returned. The same message with a parameter value of negative ve aFrame:bar(-5) returns nil. See also Accessing Functions to learn more about message sending.
Extent
The extent of a variable refers to the period of time in which a variable may be used. In many languages, the scope of a variable is the same thing as its extent. However, in NewtonScript a variable has data storage space allocated for it while it is referenced anywhere in executing code. Automatic garbage collection occurs only after an object is no longer referenced anywhere. Therefore, storage allocated for data structures is available until no references to the structure exist. You should make sure not to leave any references to large data structures youve allocated after youre done using them. If you do, NewtonScript will not reclaim the associated memory. One example on the Newton platform of where you might think about this is when you close an applicationyou can set slots to nil in the applications base frame.
Garbage Collection
In NewtonScript, garbage collectionthat is, reclaiming the storage of objects that are no longer usedis carried out automatically by the system. Thus the programmer does not need to worry about memory management. In fact, its
1-6
Semantic Overview
CHAPTER
Overview
impossible to have dangling pointers, which often cause the most insidious and hard to nd bugs in an application. If youve had to do garbage disposal manually in another language you can relax; the Newton system reclaims memory for you sometime after the last reference to an object goes away. Setting the value of all slots and variables referring to an object to nil allows the Newton garbage collector to reclaim the memory used by the object. Automatic garbage collection is triggered every time the system runs out of memory. Theres not really any reason to invoke garbage collection manually. However, if you must do so, you can call the global function GC. (See Chapter 6, Built-in functions.
Semantic Overview
1-7
CHAPTER
Overview
Basic Syntax
Rather than invent yet an entirely new syntax, NewtonScript was designed with Pascal in mind. Wherever possible, the syntax is modeled closely after Pascal.
Semicolon Separators
The semicolon (;) is used to separate lines, not to terminate them. Though semicolons are not required at the end of a line, you may spread one expression over several lines or enter multiple expressions on a single line by using the semi-colon. Expressions can be entered in a free-form manner, but we recommend that standard indentation be used for enhanced readability, as in this example: if expression then expression else another expression; Note that you may use as much whitespace as you wish; it is ignored.
Note
If you forget to add an important semicolon at the end of a Newtonscript expression, the interpreter uses whatever is on the next line as it tries to interpret a larger statement than intended, thus causing unusual error reports. For an example, see the code in the Note on page 4-6. u
1-8
Basic Syntax
CHAPTER
Overview
Character Set
NewtonScript uses the standard 7-bit ASCII character set rather than the enhanced ASCII character set used by Macintosh computers. This ensures that your code will work in any Newton development environment.
Basic Syntax
1-9
CHAPTER
Overview
Comments
NewtonScript uses the same convention for delineating comments as is used in the C++ programming language. Multi-line comment text needs to be surrounded by an opening right slash, asterisk (/*) and a matching asterisk, right slash (*/) at the end. For example /* This is an example of a comment. It can be on one line or as many lines as you need. */ If your comment is short enough to stay on one line, you can use two right slashes (//) before the text to signal that the rest of the line is a comment and should be ignored. This is often useful for putting a comment on the same line as a line of code as in this example: x:= 5 ; //This is a single-line comment. Note that nested multi-line comments are not allowed. However, within a / *... */ comment block, comments using the // notation are allowed.
A Code Example
If you like to try to understand code before you read the manual, continue on through this section, otherwise stop here and go to the next chapter. Note that in the code the curly brackets ({}) denote a frame object and the colon-equal ( :=) is the assignment operator, and the colon (:) is the message-send operator, which sends the message following it to the frame expression appearing before it. The code shown in Listing 1-2 is described in How Is NewtonScript Dynamic? beginning on page 1-7.
1-10
A Code Example
CHAPTER
Overview
Listing 1-2
A dynamic example
y := { YMethod: func () print("Y method"), yVar: 14 }; x := { Demo: func () begin self.newVar := 37; print(newVar); self.NewMethod := func () print("hello"); self:NewMethod(); self._parent := y; print(yVar); self:YMethod(); end }; x:Demo();
A Code Example
1-11
CHAPTER
You can determine the primitive class of an object obj by executing the expression PrimClassOf(obj). Similarly, you can determine the class of an object obj by executing the expression ClassOf(obj).
2-1
CHAPTER
Objects with immediate as their primitive class can be further identied as belonging to a class of: Integer, Char, or Boolean. System-dened objects with binary as their primitive class can also be further identied as belonging to a class of: Symbol, String, and Real. With reference objects, Newton allows user-specied classes for any objects you create. The class you assign an object must be a symbol. (See Symbol beginning on page 2-6 for more information about them.) Classes function as semantic types that inform the system about the data in a binary object. For example, the class 'string indicates a binary object containing a string and the class 'phoneNumber indicates a string containing a phone number. With this knowledge, a Newton device could use phone numbers in ways it would not use strings (to dial a phone, for instance.) Built-in class symbols occur in a hierarchy. For example, the class 'phoneNumber might be a subclass of the class 'string. The only class whose subclasses are important to the NewtonScript built-in functions is 'string. There are several string-manipulation functions that require their arguments to have the class 'string or a subclass of 'string. You can determine if x is a subclass of y using the function IsSubclass(x, y). You can determine if the class of an object obj is x or any subclass of x using the function IsInstance(obj, x). (Note that this is just shorthand for IsSubclass(ClassOf(obj), x).) For more information about these and the other Newton built-in functions see Chapter 6, Built-In Functions. The method of determining class relationships between objects is dependant upon how that feature is implemented in the NewtonScript implementation you are using. The NewtonScript class structure is shown in Figure 2-1.
2-2
CHAPTER
Figure 2-1
Character
$ { nonEscapeCharacter |\ { \ | n | t | u hexDigit hexDigit | u hexDigit hexDigit hexDigit hexDigit } } Characters in the standard character set are specied in your code by the dollar sign ($) and
n
a backslash escape character (\) followed by a special character specication such as, n, t, u, or 2 hexadecimal digits. a backslash escape character (\) followed by u (for unicode) and four hexadecimal digits. a non-escape character.
2-3
CHAPTER
The character set in Newton is stored as Unicode, in two bytes, to facilitate international conversions. By design, the rst 128 characters match the rst 128 characters of the Macintosh standard character set. You must use Unicode character codes to specify special characters other than the ASCII character set. Characters are immediate objects. (For more information about immediate objects see The Object Model beginning on page 1-2.) nonEscapeCharacter Consists of any ASCII character with code 32127 except the back slash (\). hexDigit Consists of: {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9| a | b| c | d | e | f | A | B | C | D | E | F}
For example, $a or $7 represent the characters a and 7, respectively. Special characters like must be specied as Unicode (16-bit) characters by using the four-digit hex character code preceded by $\u. For example, the Unicode equivalent of is: $\uF7FF You specify a new line by imbedding the code $\n in a string. Special character codes are summarized in Table 2-1.
Table 2-1
Character code
$\n $\t $\\ $\ hexDigit hexDigit $\u hexDigit hexDigit hexDigit hexDigit
See Appendix C, Special Character Codes for a list of the special characters and their Unicode equivalents.
2-4
CHAPTER
Boolean
NewtonScript denes only one Boolean constant, true. Functions and control structures use nil as false and anything else as true. When you don't have anything else to use as true, use the special immediate true.
Integer
[ - ] [ digit ]+ | 0x [hexDigit ]+ All integers in NewtonScript can be written in either decimal or hexadecimal. When a digit is prexed with zero and the letter x (0x) it signies a hexadecimal value. The optional minus sign (-) before a digit signies a negative integer. Here are some examples of integers: 13475 -86 0x56a
Integers range from 536870911 through -536870912. When that limit is exceeded behavior is undened. Integers are immediate objects. (For more information about immediate objects see The Object Model beginning on page 1-2.) digit hexDigit Consists of: {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9} Consists of: {digit | a | b| c | d | e | f | A | B | C | D | E | F}
Note
2-5
CHAPTER
Real
[-] [digit ]+.[ digit ]* [ { e | E } [ - ] [ digit ]+ A real number consists of one or more digits followed by a decimal point with zero or more additional digits. The optional minus (-) at the start indicates a negative number. You can specify scientic notation by placing the letter e (upper or lower case) directly after the last digit and following it with a negative or positive digit in the range of -308 to +308. digit Consists of: {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}
NewtonScript oating point real numbers are represented internally in double precision; 64 bits. They have approximately 15 decimal digits of precision. Some examples of real numbers include: -0.587 123.9 3.141592653589 Here are some examples of exponential notation used to represent real numbers: 763.112e4 87.3789E-45 -34.2e6 69.e-5
Real numbers are stored as binary objects and have the class Real.
Symbol
{ { alpha | _ } [ { alpha | digit | _ } ]* | ' |' [ { symbolChar | \ { ' |' | \ } ]* ' |'} A symbol is an object used as an identier. NewtonScript uses symbols to name variables, classes, messages, and frame slots. You can also use symbols as simple identifying values, as you would use enumerated types in other languages. Symbol names may be up to 254 characters and may include any printable ASCII character; for instance, |Weird%Symbol!| is valid. A symbol can be written by itself, without being enclosed in vertical bars, if it begins with an alphabetic character or an underscore and contains only alphabetic characters, underscores, and digits. NewtonScript is case insensitive, though it preserves case.
2-6
CHAPTER
Consists of: {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}. Consists of: {AZ and az}. Consists of any ASCII character with code 32127 except | or \.
One place where the Newton system requires symbols is in exception handling. An example of an exception symbol is: |evt.ex.fr.intrp| Note that vertical bars are required because of the dots in the symbol. You can read more about them in Dening Exceptions beginning on page 3-15. Symbols appearing in expressions are normally evaluated as variable references. You can prevent this by preceding the symbol with a single quote ( '). The quoted symbol evaluates to the symbol itself. See also Quoted Constant beginning on page 2-18.
String
" [ { stringChar | escSeq } ]* [ truncEscape ] ] " A string constant is written as a sequence of characters enclosed in double-quotation marks. stringChar escSeq Consists of a tab character or any ASCII character with code 32127 except the double quote (") or backslash (\). Consists of either a special character specication sequence or a unicode specication sequence.The special character specication sequence is: backslash (\) followed by a quote ("), backslash (\), the letter n or the letter t. The escape sequence for specifying Unicode begins with backslash-u (\u), is followed by any number of groups of four hexDigits , and ends with backslash-u ( \u). Consists of the shortened unicode specication sequence. It is: backslash-u (\u), is followed by any number of groups of four hexDigits.
truncEscape
2-7
CHAPTER
Here are some simple examples of strings: "pqr" "Now is the time" ""
Within strings you can include Unicode characters that are not in the standard character set by inserting the escape code, \u, to toggle on the Unicode hex mode. Follow the \u with any number of groups of fournumber codes specifying the special character. You can add another \u to toggle the Unicode hex mode off and return to the regular character set, though, you are not required to toggle the hex mode off. (See Appendix B, Special Character Codes, for a list of these characters.) For example, you could specify the French phrase, Garon, laddition, sil vous plat!, by embedding Unicode in the string to specify the special characters as follows: "Gar\u00e7\uon, laddition, sil vous pla\u00ee\ut!" Other codes you use within strings to specify special characters are summarized in Table 2-2.
Table 2-2
Character code
\n \t \u \\ \"
newline character tab character toggles Unicode on and off backslash character double quote character
2-8
CHAPTER
Array
[ [ symbol : ] [ object [ , object]* [ , ] ] ] An array is a collection of zero or more objects enclosed in square brackets ( []) and separated by commas. The user-dened class for the array may optionally be specied by beginning the array with a symbol followed by a colon (:). symbol Consists of a identier that is, syntactically, a symbol. If present, sets a user-specied class for the array. See the section Symbol beginning on page 2-6, for more information about their syntax. May consist of any NewtonScript object. NewtonScript numbers the elements in an array by beginning with zero for the rst element. Objects are separated by commas if there are more than one in the array.
object
Note
The syntax [symbol : object ()] is ambiguous; the rst symbol could be either a class for an array, or a variable to be used as the receiver for a message send. NewtonScript uses the rst interpretation. u Semantically, the array is an ordered collection of objects which are indexed numerically, beginning with zero. As with frames, the array can hold any type of object, including methods, frames, and arrays. Like other non-immediate objects, arrays can have a user-specied class, and can have their size changed dynamically. Here is a simple example of an array literal: [1,2,3] You can specify a class name for an array by preceding the rst array element with any arbitrary identier that species a class and a trailing colon, as shown here: [RandomData: [1,2,3], "Last element"]
2-9
CHAPTER
Note that this array holds a mixture of objects. It contains another array as its rst element, the number zero and a string as the second element.
Note
NewtonScript allows an optional trailing comma after the last array element. The trailing comma can be useful if you are going to add more elements to the array. u
Array Accessor
arrayExpression [ indexEpression ] Array elements are accessed with an expression, that evaluates to an array, and an index expression, that evaluates to an integer and is enclosed in square brackets. arrayExpression indexEpression An expression that evaluates to an array. An expression that evaluates to an integer. The indexExpression corresponds to the element of the array you wish to access. Note that arrays are indexed starting with zero.
For example, with the array myArray, which is dened as myArray := [123, [4,5,6], "Alice's Restaurant"]; you access the rst element in the array by using the expression: myArray[1]; This expression evaluates to [4,5,6]; returning the contents of the second element of the array rather than the rst. This is because array indexes are numbered beginning at zero. Note that array accessors are actually operators and are included here for your convenience. The rest of the NewtonScript operators are documented in Operators beginning on page 2-19.
2-10
CHAPTER
Frame
{ [ symbol : value [ , symbol : value ]* [ , ] ] } A frame is a collection of zero or more slots enclosed in curly brackets and separated by commas. A slot consists of a symbol followed by a colon (:) and a slot expression. The symbol refers to the value of the slot expression. symbol A symbol giving the name of the slot. Note that slot symbols beginning with the underscore character (_) are reserved for system use; do not begin your slot symbol with the underscore character. Can be any object, including another frame or method.
value
A frame is an unordered collection of slots which consist of a name and value pair. As with arrays, the value of a slot can be any type of object, including methods and even other frames and arrays. Frames can be used as repositories for data, like records in Pascal and structs in C, but can also be used as objects which respond to messages. As such, the frame is the basic programming unit in NewtonScript. A simple record-like frame containing names and phone numbers might appear as {name:"Joe Bob", phone:"4-5678", employee:12345} Here is an example frame that contains integers in the rst three slots, and a method in the fourth slot: Jupiter := {size:491, distance:8110, speed: 34, position: func(foo) speed*foo/3.1416}
2-11
CHAPTER
You may specify an optional class name for a frame by using the slot name class. Inserting the class slot: class : 'planet into the Jupiter frame gives it an appropriate class name. Just as for array classes, the class of a frame gives it a type, not special properties. However, if you wanted to give all objects of class planet special characteristics and functionality you could use the NewtonScript inheritance structure to set up relationships that allow objects to inherit data from other objects. (See Chapter 5, Inheritance and Lookup.) You specify these relationships to other frames by referencing them from slots named _proto and _parent. The relationships these slots establish allow you to take advantage of the NewtonScript double inheritance scheme to construct object-oriented applications. Chapter 5, Inheritance and Lookup, describes these concepts. There are several slot names which are recognized by the system and used for special purposes. All these slots are optional. They are described in Table 2-3.
Frame Accessor
frameExpr. {symbol | ( pathExpr )} Frame values are accessed with an expressionthat evaluates to a frameand either a symbol, or an expression enclosed in parentheses, that evaluates to a path expression. A frame accessor expression returns the contents of the specied slot, or if the slot does not exist the expression evaluates to nil. frameExpr symbol pathExpr Any expression that evaluates to a frame. A symbol reference to a slot. See Symbol beginning on page 2-6 for the syntax of symbols. Any expression that evaluates to a path expression object. The pathExpr corresponds to the slot of the frame you wish to access. Note that arrays are indexed starting with zero.
2-12
CHAPTER
Table 2-3
Slot Name
Specication
class: identifier
You use the special slot name class to specify a semantic type for your frame. The class of your object must be a symbol. You use the special slot name _parent to designate another frame as a parent frame to this frame. You can repeat this process, as necessary with other frames, to construct a parent inheritance chain. For information about inheritance see Chapter 5, Inheritance and Lookup. You use the special slot name _proto to designate another frame as a prototype frame to this frame. Repeat this process, as necessary with other frames, to construct a prototype inheritance chain. For information about inheritance see Chapter 5, Inheritance and Lookup.
_parent: frame
_proto: frame
Slots in a particular frame can be accessed by using a dot followed by a symbol. For example, the expression: myFrame.name; returns the contents of the name slot from the frame referenced by the variable myFrame. If the slot is not found in the specied frame using this syntax, the search for the slot continues through the inheritance chain. The next place NewtonScript looks is in the prototype frame and then in any of the prototype frames prototypes until the end of the prototype chain is reached. If the slot is not found, the search stops; it does not continue up through the parent frames. If the slot does not exist the expression evaluates to nil. The built-in functions GetVariable and GetSlot provide similar kinds of slot access but with different inheritance behavior. For more information see Chapter 6, Built-In Functions.
2-13
CHAPTER
For more information about the inheritance mechanism see Chapter 5, Inheritance and Lookup. Note that frame accessors are actually operators; they are included here for your convenience. The rest of the NewtonScript operators are documented in Operators beginning on page 2-19. You can also access frame slots by using a path expression. Read about these in the section Path Expression beginning on page 2-29.
Expressions
A simple expression consists of values and an operator, as shown in the code: 12 + 3; The values (12 and 3) and the inx operator plus (+), that appears in the line between them, are evaluated to return the value 15. Variables are often used in expressions as named containers in which to store values. For example, you can use a variable on the left side of an assignment expression, as in currentScore := 12; to store a value. The variable currentScore then becomes the identier for the value. For more information about the assignment operator (:=), see the section Operators, in this chapter.
Variables
A variable is named by a symbol. You can use this symbol to refer to any kind of value; from numbers to frames. When a method is executing and a variable reference is encountered, the system evaluates the value of the variable. This is done following the variable lookup rules of NewtonScripts double inheritance scheme. Variable lookup is discussed in Chapter 5, Inheritance and Lookup.
2-14
Expressions
CHAPTER
The next section discusses the use of the local keyword to declare local variables.
Local
local varSymbol [:= expression ] [, var2Symbol := expression ]* The local declaration consists of the keyword local, any number of initialization clausessymbol, assignment operator (:=), and expression. varSymbol Consists of an identier that is, syntactically, a symbol. The symbol names a variable that may be initialized with the optional expression. For more information on symbols see the section Symbol beginning on page 2-6. Consists of any valid NewtonScript expression.
expression
You can ensure that the value of a variable is determined in a function (i.e. that the variable is local to that function) by using a local expression to declare the variable. You should be sure to declare all local variables, to avoid hard-to-nd bugs. The scope of a local variable is restricted to the function denition in which it is declared. You can refer to it only within that function. You may use the local expression to identify a variable as local without initializing it as in the example: myFunc: func (x) begin local myVar, counter; ... end This example declares the variables myVar and counter as local variables and initializes them to nil. Then, each time the function denition for myFunc is executed, new local variables are created that are unique to that function.
Expressions
2-15
CHAPTER
You may optionally use a local expression with one or multiple assignment clauses to assign a value to a variable or variables, as shown in the expression: local x:=3, y:=2+2, z; This expression creates three local variables, x, y, and z, and initializes them to the values of 3, 4, and nil, respectively. The declaration of the local variable is processed at compile time but the values are assigned at run time, when the expression is encountered. For example, the expressions x := 10; local x, y := 20; result in a value of 10 for x and a value of 20 for y. This works because local definitions work anywhere in the function. By contrast, you can produce a run-time error by attempting to access the value of an uninitialized variable. For example, the expressions x := y + 10; local x, y := 20; result in a value of 10 for x and a value of 20 for y. This works because local definitions work anywhere in the function.
Constants
There are several ways to get unchangeable objects in NewtonScript. You can:
n n n
use the keyword constant put a single quote character (') before an object literal initialize a variable to a literal value
2-16
Expressions
CHAPTER
Constant
constant constSymbol := expression [, constSymbol := expression ]* The constant declaration consists of the keyword constant and one or more initialization clauses consisting of a symbol, assignment operator (:=), and expression. constSymbol Consists of an identier that is, syntactically, a symbol. For more information see the section Symbol beginning on page 2-6. Any expression consisting of operators and constants. The value of this expression becomes the value of constSymbol.
expression
When a constants is used as a value, NewtonScript effectively substitutes literal values for the constant.This means that if you declare a constant as in the expression constant kConst := 32; then when you use thisConstant as a value in your code, NewtonScript automatically substitutes the value 32. So that if you write sum := kConst + 10; its exactly as if you had written sum := 32 + 10; However, if you use the same identier as anything other than a value, as in the expressions: x:kConst(42); kConst(42); x.kConst; the value you dened is not substituted. This can be a problem if you dene a constant to have a function or method as its value. For these cases there are built-in functions you can use as work-arounds, as shown in Table 2-4.
Expressions
2-17
CHAPTER
Table 2-4
No Substitution
You should also note that the constant value you assign does not get substituted when used in a quoted expressions like: '{foo: kConst}; '[kConst]; See the next section to learn more about the single quote syntax. s WARNING You can create local constants by putting the declaration in a function. Since they are in the same name space of the compiler as local variables, a local variable with the same name can override constants and vice versa. s
Quoted Constant
'object The single quote character (') begins a kind of expression called a quoted constant. You use the quote to create a literal object. The object is constructed at compile time, and a reference to the same object results each time the object literal is evaluated. Here are several examples of literal objects formed with the quoted constant syntax: '{name: "Joe Bob", income: yearTotal}; 'myFrame.someSlot; '[foo, 1234, "a string"];
2-18
Expressions
CHAPTER
When a quote appears outside of the brackets or braces, it applies to every element in the array or frame, and symbols within the array or frame do not need individual quotes. For instance, if you try to create this seemingly correct frame: storyFrame := {Bear1: Mama, Bear2: Papa, Bear3: Baby}; you nd that an error is caused when the value Mama gets interpreted as an undened variable. One way to x this is to put quotes before each name, or more simply to put one quote before the whole frame, as shown in the expression: storyFrame := '{Bear1: Mama, Bear2: Papa, Bear3:Baby}; You can pass a quoted frame literal as a parameter to apply the object as needed.
Operators
The NewtonScript operators are:
n n n n n n n n
assignment arithmetic boolean equality relational unary message-send array and frame accessors
All NewtonScript operators, except the message-send operators and array and frame accessors are discussed in this section. The message-send operators are described in Chapter 4, Functions and Methods. The access operators are described in Frame Accessor beginning on page 2-12 and Array Accessor beginning on page 2-10.
Operators
2-19
CHAPTER
Assignment Operator
lvalue:= expression In an assignment expression, the symbol, frame accessor, or array accessor that is the left-hand value for the assignment operator (:=), is assigned the value of the expression appearing to the right of assignment operator. lvalue expression Consists of a symbol, a reference to an array element, or a reference to a frame slot. Consists of any valid NewtonScript expression.
You use assignment expressions to change the value of variables and slots. A simple assignment expression looks like this: a := 10; However, you can use any NewtonScript expression on the right-hand side of an assignment expression; when it is evaluated its value is assigned to the lvalue. For example, the variable x is set to refer to the value of the if expression in this assignment expression: x := (if a > b then a else b); Here is an example of the assignment of a frame to a variable: myFrame := {name: "", phone: "123-4567"} Now you can refer to the name slot in another assignment expression and change its value, like this: myFrame.name := "Julia" Note that the NewtonScript inheritance rules affect the ultimate behavior of assignment expressions in frames. For more information about inheritance and setting slot values see Inheritance Rules for Setting Slot Values, in Chapter 5. You can assign values to array slots in a similar manner. The second line of this code fragment changes the value 789 to 987. myArray := [123, 456, 789, "a string"]; myArray [2] := 987;
2-20
Operators
CHAPTER
Note
If you accidentally write an assignment expression as = rather than :=, your expression becomes a simple relational expression. For example, the expression x = 5; evaluates to true or nil and leaves the value of x unchanged. u
Operators
2-21
CHAPTER
In the example there are two structs, a and b. Each s truct contains an integer x. The integer a.x is assigned the value 1. The value of struct b is saved in struct a and a.x then is set to 2. As you would expect, the value of b.x is unchanged at this point (it is still 1.) The results of this code example are shown in Figure 2-2.
Figure 2-2
C code example
The equivalent code in NewtonScript gives a very different outcome: local a := {x: 1, y: 3}; local b := a; a.x := 2; // at this point b.x = 2 The rst assignment expression constructs a frame, with two slotsnamed x and ywith values of 1 and 3, respectively. Both refer to the same frame. When the value of a is assigned to the local variable b, in the expression local b := a; NewtonScript makes b refer to that frame. Both local variables, a and b, now refer to the same frame.
2-22
Operators
CHAPTER
The expression: a.x := 2; changes the value of the x slot. Since both variables, a and b, refer to the same frame, the value of b.x is also changed to two, though, it was not explicitly assigned. You can see these results in Figure 2-3.
Figure 2-3 A NewtonScript code sample
Note
Assignments of arrays and strings in C are handled in the same manner as assignments of references in NewtonScript. u
Operators
2-23
CHAPTER
Arithmetic Operators
{ + | - | * | / | div | mod | << | >> } NewtonScript provides the standard set of binary arithmetic operators. They are: the addition (+) and subtraction (-) operators, the multiplication (*) and division (/) operators, the truncating operators div and mod, and the bitwise shift operators, bitwise left shift (<<) and bitwise right shift (>>). + The plus operator adds the two numbers it appears between. The minus operator subtracts the number to its right from the number to its left. Note that minus can also be used as a unary operator to negate an expression. See Unary Operators beginning on page 2-27. The multiply operator multiplies the two numbers it appears between. The division operator divides the number to its left by the number to its right. The divide and truncate operator divides the number to its left by the number to its right and truncates the remainder so that a whole number is returned. The modulo operator divides the number to its left by the number to its right and returns only the remainder. The bitwise shift left operator is an inx operator. In the expression: x << y ; x is shifted left by y bits. >> The bitwise shift right operator is an inx operator. In the expression: x >> y ; x is shifted right by y bits. The most significant bit is duplicated in the shift operation.
* / div
mod <<
2-24
Operators
CHAPTER
<>
<
>
Operators
2-25
CHAPTER
<=
The less than or equal to operator compares the values of numbers, characters, and strings; returning true if the operand on the left of the operator is less than or equal to the operand on its right and nil otherwise. An error is signalled if you try to compare arrays or frames. The less than or equal to operator compares the values of numbers, characters, and strings; returning true if the operand on the left of the operator is greater than or equal to the operand on its right and nil otherwise. An error is signalled if you try to compare arrays or frames.
>=
This expression tests the identity of two reference objects: "abc"<> [1, 2]; It evaluates to true because the two objects are not the same object. Likewise, the equal (=) operator, when applied to two frame objects, compares their identity, as shown when you execute the code: [1,2] = [1,2]; This expression evaluates to nil even though at rst glance it looks as though it should be true. The relational operators work with numbers, characters, and strings. If you try to use these operators with arguments that are arrays or frames, an error is signalled.
Boolean Operators
{ and | or } The Boolean operators, and and or, are binary logical operators that compare two expressions. and The and operator tests the logical truth of its two operands; returning true if both expressions are true and nil otherwise.
2-26
Operators
CHAPTER
or
The or operator tests the logical truth of its two operands; returning true if either expression is true and nil if both expressions are false.
Expressions involving the Boolean operators, and and or, like their counterparts, || and &&, in the C programming language, short circuit or stop evaluation as soon as the truth of an expression is determined. For instance, if x < length(someArray) evaluates to nil in a conditional expression like if x > 0 and someArray[x] then doSomething else doSomethingElse; processing is stopped immediately and goes on to the else clause. If one part of an and operation is not true, the whole and expression is not true. Therefore, it is not necessary to evaluate the second half of the and expression when the rst half is not true. When this occurs it is said that execution is short-circuited. The return value of an expression using any of the logical operators is either nil, which is false, or anything other than nil, which is true.
Unary Operators
{ - | not } The unary prex operators, minus (-) and not, precede any single expression. not The minus (-) operator returns the additive inverse of the expression it precedes. The not operator is used before an expression to perform a logical negation of that expression.
Operators
2-27
CHAPTER
Here are some examples of these operators in use: -x; not x; -(1 + 5); not(a and -f(12) > 3); Exists is another NewtonScript unary (but postfix) operator. It is described in the sectionExists beginning on page 2-30.
String Operators
string1 { & | && } string2 The two string operators, && and &, create a new string from the contents of two strings you provide. The single & operator creates a new string that has no spaces between the two objects, while the double && operator adds a space between the two strings in the new string. If you use an object that is not a string in an && or & expression, NewtonScript converts the object to a string and uses it to construct a new string. This works for symbols, characters, and numbers. An & and && expression returns a new string. & An & expression concatenates the string yielded by the expression on its left to the string yielded by the expression on its right. An && expression creates a new string by concatenating, with a space, the string yielded by the expression on its left to the string yielded by the expression on its right.
&&
The single & operator concatenates the two strings by leaving no space, in the new string, between what was the second string and the rst string. For instance, the expression: "foo" & 17 creates the new string: "foo17"
2-28
Operators
CHAPTER
In contrast, the && operator creates a new string by copying the rst string, adding a space, and then copying the second string, as you can see, in the following expression and its result: "happy" && "days" "happy days"
Path Expression
symbol [ . symbol]+ A path expression is a way of encapsulating an access path through a set of objects. It may be a symbol, an integer, or an array of class pathExpr which contains symbols and integerssymbols represent frame slot accesses and integers represent array slot accesses. Path expressions containing only symbols may be written as object literals consisting of a series of symbols separated by dots. symbol pathExpression Consists of a symbol that evaluates to a frame or array. Consists of any valid NewtonScript expression that evaluates to a symbol
You can access data in a frame by using a path expression like this: myFrame.(pathExpression); The expression myFrame evaluates to a frame and pathExpression evaluates to a path expression object. This example constructs a slot path expression: myFrame:={Kind:"Cat",Type:{Hair:"long",Color:"black"}}; myFrame.('Type.color); The value it returns is the string "black". Since a path expression is represented internally as an array of class pathExpr, the expression ('Type.color) creates the array [pathExpr: 'Type, 'color].
Operators
2-29
CHAPTER
You could rewrite the previous example using array syntax for the path expression, as shown in these expressions: myFrame:={Kind:"Cat",Type:{Hair:"long",Color:"black"}}; slotPath := '[pathExpr: Type, color]; myFrame.(slotPath); Like frame slots, array elements can also be accessed using path expressions. The path to an array element is simply the array index of the element. Here is an example: myframe:={name:"Matt",info:{grade:"B",tests:[87,96,73]}}; mypath:='[pathExpr: info,tests,1]; myframe.(mypath); The expression myFrame.(mypath) evaluates to 96. Note that you can also use path expressions to set the value of a slot. For instance, to upgrade the third test score above, use an expression like: myframe.(mypath):= 98;
Exists
lValue exists Exists is a special postfix operator that follows a single symbol, frame access expression, or message send. The exists operator is used to check for the existence of variables, slots, or methods. When you apply the exists operator to an identier, such as a variable, it returns true if the variable is dened in the current context and nil otherwise. (For more information about the scope of variables see Scope beginning on page 1-4.) lValue Consists of an expression that evaluates to a symbol, frame accessor, or a message-send.
2-30
Operators
CHAPTER
All of these are legal forms for an exists expression to take: x exists; x.y exists; x.(y) exists; x:m exists; Here is an example of a simple ifthen structure that uses exists: if myVar exists then myVar else 0; When you apply exists to a frame accessor, exists returns true if the slot exists in the frame or in any of its prototype frames, and nil otherwise. (For more information about prototype frames and inheritance, see Chapter 5, Inheritance and Lookup. ) Ifthen expressions are described in Chapter 3, Flow of Control. This operator can be particularly useful if you want to check for the existence of a slot that may or may not be in a prototype frame: if myFrame.aSlot exists then if not hasSlot(myFrame, 'aSlot) then print("'aSlot slot is in a prototype of myFrame") The built-in function hasSlot provides similar functionality to the exists operator though they differ in the type of inheritance that is used to search for slots. See also Chapter 5, Inheritance and Lookup, and Chapter 6, Built-In Functions.
Operator Precedence
In case it is not inherently apparent in an expression, a set of ratings tells the compiler which operator to evaluate rst (or which operator takes precedence). Table 2-5 lists the order of precedence of all the NewtonScript operators in order from top to bottom. Note that operators grouped together in the table are of equal precedence.
Operator Precedence
2-31
CHAPTER
. : :? [] << >> * / div mod + & && exists < <= > >= = <> not and or :=
slot access message send conditional message send array element unary minus left shift right shift multiply oat division integer division remainder add subtract concatenate (string copy of expression value) concatenate with 1 space between variable & slot existence less than less than or equal greater than greater than or equal equal not equal logical not logical and logical or assignment
left-to-right left-to-right
none left-to-right
2-32
Operator Precedence
CHAPTER
Flow of Control
This chapter discusses the syntax and semantics of the standard ow-of-control mechanisms including: compound expressions, conditional expressions and iterators. Also included is a discussion of the non-standard ow-of-control mechanism called exception handling that NewtonScript uses to control exceptional situations or errors.
Compound Expressions
begin expression1; expression2; expressionN[;] end The keywords begin and end are used to group expressions, not to create structured blocks that dene the scope of variables, as they are in some languages.
Compound Expressions
3-1
CHAPTER
Flow of Control
This construct is useful in conditional expressions, in any of the looping expressions, and in function denitions. In fact, anywhere the syntax species a single expression, you can use a compound expression instead. The compound expression returns the result of the last expression. expression Consists of any valid NewtonScript expression; it must be separated from the next expression by a semicolon, unless it is the last expression in the compound expression. In this case, the keyword end separates it from any following expressions.
If you want to execute more than one expression in a conditional expression, use the keywords begin and end to group the expressions as shown in this example: if x=length(myArray) then begin result := self:read(x); print(result) end
IfThenElse
if testExpression then expression [;] [else alternateExpression] The ifthenelse construct allows you to dictate programmatic ow of control using test conditions. As is standard in other programming languages, you use an if expression to carry out one set of operations, when the condition you set up in a test expression is true, and another set of operations when the text expression evaluates to nil.
3-2
IfThenElse
CHAPTER
Flow of Control
The if expression returns the value of its expression or alternateExpression. clause, unless the test condition is not true and there is no else clause. In that case, nil is returned. testExpression Consists of an expression that tests for the truth of a condition. If the test expression evaluates to anything other than nil, the expression following it is executed. Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.) This expression is executed if the test is true; its value is returned as the value of the if expression. alternateExpression Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.) The else clause, along with the alternateExpression that follows it, is executed if the test expression evaluates to nil.
expression
Iterators
NewtonScript includes these iterators:
n n n n n n
Iterators
3-3
CHAPTER
Flow of Control
Note
Loops do not work outside of a function because local variables must be declared within a function and iterators require local variables to control the number of iterations executed. This is a problem you might encounter this while trying out code in the Inspector window of the Newton Toolkit. For more information about local variables see Local beginning on page 2-15. For more information about functions see Chapter 4, Functions and Methods. u
For
for counter := initialValue to finalValue [by incrValue ] do expression The for loop performs a set of expressions repeatedly, until a loop counter variable equals or exceeds a specied nal value or a Break expression is reached. A counter variable keeps track of the number of times the loop has executed. You specify the initial value and nal value of the counter variable. If you choose not to specify the amount to increase (or decrease) the counter by using the optional keyword by followed with an incremental value, the counter gets incremented by the default value of 1. A for loop expression returns nil (or the argument of a break expression, if one is used to terminate the loop.) counter This symbol is set to the value of the initialValue expression when a for loop starts. After each repetition of the loop, the counter variable is incremented by the value of incrValue . or by the default value of 1 if an incremental value is not specied. On loop exit the value of counter is undened. It is an error to change its value from within the loop body. If you do so, loop behavior is undened.
3-4
Iterators
CHAPTER
Flow of Control
initialValue
This expression must evaluate to an integer. It is evaluated once before the loop starts and is used as the initial value of the counter. This expression must evaluate to an integer. It is evaluated once before the loop starts and is used as the nal value of the counter. This expression follows the keyword by. It is evaluated once before the loop starts and used throughout the loop execution to increment (or decrement) the counter variable. The incremental value expression must evaluate to an integer (either positive or negative); a value of zero generates a run-time error. If you do not specify an incremental expression, after the keyword by, a default value of 1 is used to increment the counter.
nalValue
incrValue
expression
Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.)
Iterators
3-5
CHAPTER
Flow of Control
Foreach
foreach [slot,] value [deeply] in frame | array collect | do expression Using the foreach iterator is one way you can access data stored in frames or arrays. This iterator executes once for each element in an array or frame allowing you to either iterate an expression over each value stored in an array or frame, or to collect data during each iteration. In an array, iteration begins with the rst element of the array, element[0]. In a frame the starting point and susbsequent order of iteration is unpredictable because frame slots are not stored in any particular order. This iterator also has a special option, deeply, for frame iteration over values in the target frame and in its proto chain of frames as well. For information on prototype inheritance see Chapter 5, Inheritance and Lookup. A foreach expression returns nil (or the argument of a break expression, if one is used to terminate the loop.) slot This symbol is set to the name or index of the next slot on each loop iteration over the elements of an array or frame. The value of this variable is undened on loop exit. Using the slot variable is optional. If you specify just one variable of the slot, value pair, its assumed to be as the value .. Set to the value of the next array element or frame slot on each loop iteration over the elements of an array or frame. The value of this variable is undened on loop exit. Using the value variable is mandatory. If you specify just one variable, of the slot, value pair, its value is assigned as the element value. An expression that evaluates to an array. An expression that evaluates to a frame.
value
array frame
3-6
Iterators
CHAPTER
Flow of Control
expression
Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.) Species the option that iteration occurs over values in the immediate frame rst and then in the _proto frame(s). (For information on prototype inheritance see Chapter 5, Inheritance and Lookup.) If you specify the deeply option and the frame you are concerned with does not have a _proto frame, no error is produced. Instead, the slot values evaluate to those of the current frame.
deeply
You use foreach to access data stored in a frame that functions like a Pascal record or a C struct. The data used in the following example is the nameFrame frame, defined as: nameFrame := { name:"Carol", office:"San Diego", phone:"123-4567"}; You can use the foreach do loop to access and print the slot names and values stored in a nameFrame by writing a method like reportIt: report:= { reportIt: func(frameName) begin foreach slot, value in frameName do begin display(slot); display(":"); print(value); end end }
Iterators
3-7
CHAPTER
Flow of Control
When you send the message reportIt with the argument nameFrame to the report object, as shown here: report:reportIt(nameFrame); This is the output produced: "Carol" "San Diego" "123-4567" Using collect with the foreach iterator makes it easy to collect the data and manipulate it. Consider a dataFrame which is dened as: dataFrame := {1,3,5,7,9} You can collect the squares of each value in dataFrame and print the results, with the code shown here: result := foreach value in dataFrame collect value*value; print(result); The values are collected in an array, as shown in the output: ["Carol", "San Diego", "123-4567"] If you want the foreach iterator to look up slot values in the prototype frame in addition to the current frame, use the deeply option. To make use of the deeply option with this iterator, your data set must include a frame that references a prototype frame. For purposes of example we can use the data dened here as: x := {one:1, two:2, three:3}; y := {four:4, five:5, combo:x}; z := {six:6, _proto:y};
3-8
Iterators
CHAPTER
Flow of Control
You can consult the picture of this data, shown in Figure 3-1, while looking at the different results, produced by using foreach alone and with the deeply option that are shown in the accompanying table, Table 3-1.
Figure 3-1
Table 3-1 allows you to compare the results produced by two functions, normalList and deeplyList, as applied to the data in Figure 3-1.
Iterators
3-9
CHAPTER
Flow of Control
Table 3-1
foreach normallist := func (param) begin foreach tempItem in param collect tempItem; end; :normallist(x) #4413441 [1, 2, 3] :normallist(y) #4413A11 [4, 5, {One: 1, two: 2, three: 3}] // same
foreach deeply deeplylist := func (param) begin foreach tempItem deeply in param collect tempItem; end; :deeplylist(x) #44137D9 [1, 2, 3] :deeplylist(y) #4413C49 [4, 5, {One: 1, two: 2, three: 3}] :deeplylist(z) #4416FE1 [6, 4, 5, {One: 1, two: 2, three: 3}]
Loop
loop expression This mechanism simply repeats any expressions that occur within the loop expression until a break expression is encountered; if no break expression is reached the loop never ends. The loop expression returns the argument of the break expression that is used to terminate the loop. expression Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more
3-10
Iterators
CHAPTER
Flow of Control
information see the section Compound Expressions.) This expression is evaluated during each loop iteration. This example prints the value of the variable x until it reaches the value of 0 and the break expression is executed. local x:=4; loop if x = 0 then break else begin print(x); x:=x-1 end 4 3 2 1
While
while condition do expression The while loop evaluates the conditional expression rst. If it evaluates to a non-nil value (true or any other value that is not nil) the expression after the keyword do executes. This sequence repeats until the conditional expression evaluates to nil and ends loop execution. A while expression returns nil (or the argument of a break expression, if one is used to terminate the loop.) condition Consists of an expression that tests for the truth of a condition. If the test expression evaluates to nil, loop execution ends. Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.) This expression is evaluated during each loop iteration.
expression
Iterators
3-11
CHAPTER
Flow of Control
Repeat
repeat expression until condition The repeat loop executes the expression(s) inside the loop rst and then evaluates the test expression. If the expression at the end of the loop evaluates to nil, the expressions repeat and the test expression is evaluated again. This continues until the expression evaluates to non-nil, at which point the loop ends. A repeat expression returns nil (or the argument of a break expression, if one is used to terminate the loop.) condition Consists of an expression that tests for the truth of a condition. If the conditional expression evaluates to anything other than nil, loop execution ends. Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.) This expression is evaluated during each loop iteration.
expression
Break
break [expression ]; While not an iterator itself, the Break expression interrupts the execution of any of the iterative structures. You must use the Break expression to stop the simple Loop structure, which has no built-in constructs to stop it. If a expression follows Break, it is evaluated and returned as the value of the loop. If you use the Break with no expression following it, the loop returns the value nil. expression Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.) The value of this expression is returned as the value of the Break expression.
3-12
Iterators
CHAPTER
Flow of Control
Exception Handling
NewtonScript exception handling allows you to respond to exceptional conditions that arise during the execution of your program. An exceptional condition, or exception, is a condition that either the Newton system software or your own code raises when something unexpected or erroneous happens at run time. When an exception is raised at run time, the system can transfer control to an exception handler, which is a block of code that attempts to handle the condition gracefully, rather than allowing the application to crash. An exception handler can respond by displaying an error message, reverting the state of a computation, or taking some other action or actions. The act of raising an exception is known as throwing an exception. An exception handler catches the exception and responds in some manner. Each exception has a unique name and each exception handler responds to a specic exception or class of exceptions. Newton system software throws and catches a number of built-in exceptions. You can dene, throw, and catch your own exceptions, and you can also catch and handle the built-in exceptions. This section describes exception handling in NewtonScript. Exception handling is a non-standard ow of control mechanism that NewtonScript inherited from Newton system software. NewtonScript exception handling allows you to respond to exceptional conditions that arise during the execution of your program. An exceptional condition, or exception, is a condition that either the Newton system software or your own code raises when something unexpected or erroneous happens at run time. When an exception is raised at run time, NewtonScript can transfer control to an exception handler, which is a block of code that attempts to handle the condition gracefully, rather than allowing the application to crash. An exception handler can respond by displaying an error message, reverting the state of a computation, or taking some other action or actions. 3-13
Exception Handling
CHAPTER
Flow of Control
In NewtonScript, the act of raising an exception is known as throwing an exception. An exception handler catches the exception and responds in some manner. Each exception has a unique name and each exception handler responds to a specic exception or class of exceptions. Newton system software throws and catches a number of built-in exceptions. You can dene, throw, and catch your own exceptions, as well as the built-in exceptions by using the try, throw, and catch built-in exception-handling functions.
dene an exception symbol for a specic exception or class of exceptions enclose a list of statements within a try statement to catch any exceptions that occur during execution of those statements catch a specic exception or class of exceptions with an onexception statement use the CurrentException function to examine the frame associated with the exception that you are handling throw an exception when you detect a condition that request handling rethrow an exception from within your exception-handling code to allow the next handler for the exception to respond to it
n n
You can provide exception handling for any list of statements in your NewtonScript programs. You can also nest an exception-handling block of code inside of another exception-handling block of code to provide a hierarchical chain of exception handlers. Each exception handler can specify which exception or class of exceptions it processes by naming the symbol or symbol prex that it handles. An exception handler can also reraise (rethrow) the exception that it is handling to allow other exception handlers in the chain an opportunity to process the exception.
3-14
Exception Handling
CHAPTER
Flow of Control
The basic process for implementing exception handling is as follows: 1. Decide on a name for the exceptions that you are going to dene and how you are going to respond when each exception is raised. 2. Write your code and use the Throw function to raise exceptions where appropriate. 3. Write an onexception clause for each exception. Each clause names an exception and provides a statement to handle that exception. 4. Enclose the list of statements in which you are raising and handling exceptions with a Try statement.
Dening Exceptions
Each exception is named with an exception symbol. You must adhere to the following format rules when dening an exception symbol. Each symbol
n n n n
must be enclosed in vertical bars (|) can contain up to 127 characters can contain multiple parts that are separated by semicolons (;) must contain at least one part that begins with the prex evt.ex
Listing 3-1
Exception symbols
|evt.ex| |evt.ex.fr.intrp| |evt.ex.div0| |evt.ex.msg; type.ref.frame| The prexes contained in the exception symbols are used to dene the hierarchy of exception handlers, as described in the section Catching Exceptions beginning on page 3-20. These prexes are also important for dening exception types, as described in the section Exception Frames on page 3-16.
Exception Handling
3-15
CHAPTER
Flow of Control
Exception Frames
A frame is associated with each exception. This exception frame contains two slots: a name slot and a data slot. The name slot is always named name and always contains the exception symbol. The name and contents of the data slot depend on the composition of the exception symbol, as shown in Table 3-2.
Slot contents
a data object, which can be any NewtonScript object a message string an integer error code
3-16
Exception Handling
CHAPTER
Flow of Control
Table 3-3 shows several examples of exceptions and the frames associated with them.
Exception frame
{name: '|type.ref|, data: {type: 'inka, size: 42, weight: 177}} {name: '|evt.ex.msg|, message: "there seems to be a problem"} {name: '|evt.ex|, error: -48666}
You can access the frame that is associated with an exception from within your exception handler by calling the CurrentException function. CurrentException CurrentException() Returns the frame that is associated with the current exception. You can examine the frame returned by CurrentException to determine what kind of exception you are handling. For example, you can call the HasSlot function to determine if the frame contains a slot named error and take appropriate action thereafter.
IMPORTANT
You can call the CurrentException function only from within an onexception clause. s
Exception Handling
3-17
CHAPTER
Flow of Control
Exception symbols are described in the previous section. Examples of the try statement and onexception clauses are found in Listing 3-4 on page 3-22.
Throwing Exceptions
To raise an exception in NewtonScript, you need to call the Throw function and include the exception name and data as parameters. The form of the data that you send as a parameter must match the type of exception that you are throwing.
3-18
Exception Handling
CHAPTER
Flow of Control
Throw Throw(name , data) Raises an exception and creates an exception frame with the specied name and data. name data An exception symbol that names the exception being raised. The data for the exception. The possible values for this parameter depend on the composition of name and are shown in Table 3-2 on page 3-16.
You call the Throw function from within a list of statements that are enclosed by a Try statement. NewtonScript transfers control to the onexception clause whose symbol matches name . Listing 3-2 shows several examples of calls to the Throw function.
Listing 3-2
Throw('|evt.ex.foo|, -12345); Throw('|evt.ex.msg|, This is my message); Throw('|type.ref.something|, [a, b, c]); Note that the composition of the exception symbol that you pass as the rst parameter to the Throw function denes the kind of data that you pass as the second parameter:
n
The rst statement in Listing 3-2 requires an error number as its second parameter. The second statement in Listing 3-2 contains the prex |evt.ex.msg| and thus requires a message string as its second parameter. The third statement in Listing 3-2 contains the prex |type.ref|and thus requires a data object (in this case, an array) as its second parameter.
Exception Handling
3-19
CHAPTER
Flow of Control
You can call the Rethrow function only from within an onexception clause. s
Catching Exceptions
When an exception is thrown during the execution of a list of statements, execution of that list of statements is terminated and control is transferred to the rst exception handler that matches the exception. Each exception handler is an onexception clause enclosed within a try statement, as shown below in Listing 3-3 and Listing 3-4. Each onexception clause species the symbol of the exception or class of exceptions that it handles. The exception handler that most specically matches the symbol of the exception that has been raised is the handler that gets invoked. This happens as follows: 1. When an exception is raised, Newton system software examines the onexception clauses of the try statement that is currently active. The onexception clauses are examined in order, from rst dened to last dened. 2. The rst matching onexception clause gets executed and the value of the clause becomes the value of the try statement. A matching
3-20
Exception Handling
CHAPTER
Flow of Control
onexception clause is one whose exception symbol is a prefix of any of the parts of the exception that was raised. 3. If the active try statement does not contain a matching onexception clause, the exception is passed onto the next enclosing try statement. 4. The exception is passed along to enclosing try statements until it is handled. Any exception that contains the |evt.ex| prex will be handled by the the system, which responds by displaying an error alert. 5. If the exception is not handled by any exception handler, the program continues to run from the point where the exception was raised. Since the exceptions are handled in an order that goes from most specic to least specic matching symbol, you need to order your onexception clauses from most specic to least specic. For example, the code in Listing 3-3 contains three onexception clauses whose ordering is problematical.
Listing 3-3
try c := x:myFunc(p, q); :anotherFunc(c) onexception |evt.ex.pgm.fnerr| do begin print(function error); c := nil; end onexception |evt.ex.pgm| do print(program error) onexception |evt.ex.pgm.dataerr| do print(data error); The nal onexception clause in Listing 3-3 will never get executed because the second onexception clause catches any exceptions that contain the |evt.ex.pgm| prefix. Changing the order of the clauses to make the least specic (the |evt.ex.pgm| symbol) clause last xes the problem. The new version of the code is shown in Listing 3-4.
Exception Handling
3-21
CHAPTER
Flow of Control
Listing 3-4
try c := x:myFunc(p, q); :anotherFunc(c) onexception |evt.ex.pgm.fnerr| do begin print(function error); do c := nil; end onexception |evt.ex.pgm.dataerr| do print(data error) onexception |evt.ex.pgm| do print(program error);
IMPORTANT
The onexception syntax is not forgiving about extra semicolons. You should never have a semicolon (;) before an onexception clause. s
Responding to Exceptions
This section shows and describes several examples of using exception handling in a NewtonScript application program. Listing 3-5 shows an exception handler that catches the exception that is raised by the Newton system software when there is not enough memory to store a new date in the Datebook soup.
Listing 3-5
3-22
Exception Handling
CHAPTER
Flow of Control
Listing 3-6 shows an exception handler that examines the exception frame to determine if the exception represents a certain error. If so, the handler takes an action; otherwise, the handler rethrows the exception so that it can be caught by another handler.
Listing 3-6 An exception handler checking the exception frame
onException |evt.ex| do if HasSlot(CurrentException(), 'error) then begin if CurrentException().error = -48211 then Print(The string you entered is too large) else Rethrow(); end else Rethrow();
Exception Handling
3-23
CHAPTER
This chapter describes the way you encapsulate and access code in functions and methods, as well as related topics, including:
n n n n
4-1
CHAPTER
Func Denition
func(paramList) expression The func expression is used to create a function or method. The syntax of a function constructor consists of: the reserved word func, followed by parentheses surrounding zero or more parameters in a comma separated list, and a body of code that consists of zero or more expressions. A function returns the value of its expression. paramList Consists of an optional list of identiers that are separated by commas and enclosed in parentheses. If your function does not use parameters you must still include an empty set of parentheses following the keyword func. Consists of any valid NewtonScript expression. A compound expression may be substituted. (For more information see the section Compound Expressions.)
expression
The sample function in this example simply returns the value of the difference between its two parameters: func(n1, n2) begin if n1 > n2 then n1 - n2 else n2 - n1 end }
Return
return returnValue; The return expression is used to exit a function and return a value. The expression following the keyword return is optional. When an expression appears following return, it is evaluated and its value is
4-2
CHAPTER
returned as the value of the function. If you do not specify a return value, nil is returned on function exit. returnValue Consists of any valid NewtonScript expression or compound expression. Specifying a return value is optional; if no expression follows the return keyword, it evaluates to nil.
Messages
You send messages to objects to execute methods, as in other object-oriented languages. In NewtonScript, the frame is the only kind of object that receives messages. See Frame beginning on page 2-11. Most code is executed in response to messages you send to a frame. Usually you send a message by using either the colon (:), which is the message send operator, or the colon-question mark (:?), which is the conditional message send operator. Note that you can also use the built-in function Perform() to send a message. See Chapter 6, Built-In Functions.
Message-Send Operators
[{ inherited|frameExpr}] { :|:?} message(paramList) You can choose either the message-send operator, which is a colon (:), or the conditional message-send operator, which is a colon-question mark (:?), to send a message to a frame. The message-send (:) operator, sends a message and its arguments, if any, to a frame object. The conditional message-send (:?) rst checks to see if a method exists anywhere in the inheritance chain before sending the message. The optional frame expression that appears before the operator species the frame where the message is sent.
Messages
4-3
CHAPTER
If a frame expression is specied, the message is sent directly to the frame you specify, and it becomes the receiver of the message. When nothing appears before the message-send operator, the message is sent to the current receiver which you can refer to using the pseudo-variable, self. Rather than leaving a blank before the message-send operator, you can make your code more readable by putting self there, to specify explicitly the current receiver. If you want to call an inherited method instead of the method that overrides it, you use the keyword, inherited, before the message-send operator. This forces NewtonScript to bypass the receiver and lookup the value of the method in the prototype chain, starting after the frame where the currently executing method was found. Note that lookup stops at the end of the prototype chain and does not continue up the parent chain. For more information on lookup see Chapter 5, Inheritance and Lookup. The message that follows the message-send operator is a symbol. The message-send operator looks for a frame slot with that name. The frame slot must reference a function with the same number of parameters used in the message-send parameter list. frame Consists of any valid NewtonScript expression that evaluates to a frame. The frame you specify becomes the receiver of the message. When the frame is omitted and does not appear before the colon in a expression like: :message(argList); the message is sent to the current receiver. inherited A keyword specifying that the message is being sent to an inherited version of the method code residing somewhere in the prototype chain. Using the inherited keyword forces method lookup to continue down the prototype chain rather than starting in the current receiver. Consists of a symbol. This symbol is used to look up the method using the standard inheritance rules, beginning
message
4-4
Messages
CHAPTER
with the receiver, at run time. For more information on lookup see Chapter 5, Inheritance and Lookup. paramList Consists of a list of zero or more parameters, in a list, separated by commas and enclosed by parentheses. The number of parameters must match the number of parameters expected by the method.
When a message-send expression like: frame4:msg1(); executes, the message, msg1, is sent to the object, frame4. If you send the same message without specifying what frame is the receiver, as in the expression: :msg1(); then the message is sent to the current receiver. The same operation could be written as: self:msg1(); When a message is sent, NewtonScript looks up the method using normal inheritance rules. To force the use of a method that is in a prototype frame rather than the current frame you use the inherited keyword, as shown in the expression: inherited:msg1(); If it is not possible for you to be sure if a method exists, send the message using the conditional message-send ( :?) operator. This operator insures that the message is sent only if NewtonScript can nd the method. This could be useful if you are working on some views in an application and are implementing a ViewClickScript. ViewClickScript is a function that the developer must supply. It is called by the system when a view is tapped by a user. See the Newton Programmers Guide for more information about Newton system functions.
Messages
4-5
CHAPTER
The conditional message send (:?) operator ensures that the message is sent only if a view in the inheritance chain actually has a ViewClickScript. You can see the use of the conditional message send (:?) operator in the code following: ViewClickScript: func(unit) begin local gBounds := :GlobalBox(); local y := GetPoint(firstY,unit); constant delta := 10; if y-gBounds.top < delta OR gBounds.bottom-y < delta then begin :Drag(unit,nil); :Parent():Dirty(); end else inherited:?viewClickScript(unit); end,
Note
The error message expected array, frame, or binary but got 8 was printed in response to the following code: :Emit(, [t2, t1, Length(node.r3)]) :PopTemp('ref); Because of the missing semicolon at the end of the rst line this is parsed as the expression: (:Emit(,)):PopTemp('ref); The emit invocation resulted in an 8, which was used as the receiver for the PopTemp message. This was NOT what the programmer intended. There are two habits, each of which would have prevented this error: always use self:foo() instead of :foo() and always put a semicolon (;) at the end of a expression. u
4-6
Messages
CHAPTER
Function Invocations
When you want to execute a function object, without changing the receiver, you can use the call with syntax, the global function call syntax, or the built-in function, Apply. This section describes the call with and global function call syntax. For information about the built-in function Apply see Chapter 6, Built-In Functions.
Call With
call function with (paramList) The call with expression is used to execute the specied function object and its parameters, using the value of the receiver that was captured when the function object was created. Thus, the function object executes as a closure would in a language like Lisp. See the section Function Objects beginning on page 4-9 for more information. A call with expression returns the value of the function object it executes. function paramList Consists of any valid NewtonScript expression that evaluates to a function. Consists of a list of zero or more parameters, in a list, separated by commas and enclosed by parentheses. The number of parameters must match the number of parameters expected by the function.
See Using Function Objects in Advanced Ways beginning on page 4-13, for an example of how a call with expression can be used in unusual ways.
Function Invocations
4-7
CHAPTER
Many global function denitions are built into NewtonScript (see Chapter 6, Built-In Functions, for a list of them).
4-8
Function Invocations
CHAPTER
Passing Parameters
Parameters are passed by value in NewtonScript. In other languages this sometimes means that these parameters are unchangeable by the function. However, you should note that some NewtonScript values are references, and when a reference is the value of a parameter the function can modify that object. For more information about NewtonScript immediates and references, see Immediate and Reference Values beginning on page 2-21.
Function Objects
When code of the form: func(paramList) expression; executes, a function object is constructed. Functions are rst-class objects in NewtonScript. This simply means that they are on par with all other NewtonScript objects. In addition to their implicit type, they contain contextual information. The context of a function object consists of: the lexical context, or the code in which it is dened, the message environmentwhich is the frame to which it is sent and the frame where it is foundas well as function code. The parts of a function object are shown in Figure 4-1. When the function evaluates, it is the function object that executes and produces values. In other programming languages, like Lisp, this kind of function object is known as a closure.
Passing Parameters
4-9
CHAPTER
Figure 4-1
Function Context
NewtonScript uses the context of a functionthe lexical environment and the message environmentto establish values for any variables that are used in a function without being dened there.
4-10
Function Objects
CHAPTER
However, you can have a function denition that includes another function denition in its body of code, as shown in boldface type in this example: frame2:={task1: func(e) begin local total := 0; task2:= func() ; total end } Since the function, task2, is embedded in the function, task1, it has a lexical environment that consists of the task1 function denition.
Function Objects
4-11
CHAPTER
Self The value of the pseudo-variable self is always set to the value of the receiver. Therefore, you can use self to reference the receiver in your code. Note that you cannot set self as you could a real variable, hence its designation as a pseudo-variable. The value of self in the following example is frame1. f := frame1:task1({x:2});
4-12
Function Objects
CHAPTER
Figure 4-2
Function Objects
4-13
CHAPTER
When you invoke the function object add3 one more time with the value nineteen (19) it evaluates to twenty-two (22). Again yousee that the value of x from the previous call to add3 was captured in the resulting function object. This is shown in these two lines of code: call add3 with (19); #58 22
4-14
Function Objects
CHAPTER
NewtonScript supports several object-oriented features and concepts through its double inheritance scheme. Frames are the basic data structure in NewtonScript. Inheritance between frames is set up through slots named _parent and _proto. This chapter describes parent and prototype inheritance as well as
n n n n
how to set up frames with these relationships the rules associated with parent and prototype inheritance how inheritance affects setting slot values the uses of parent and prototype inheritance
Inheritance
There are two kinds of inheritance in NewtonScript: prototype inheritance and parent inheritance.
Inheritance
5-1
CHAPTER
Prototype Inheritance
A frame can have a prototype, which is simply another frame it names as the value of a _proto slot. A frame inherits slots from its prototype if it does not contain them in itself. If a frame contains a slot with the same name as a slot in the prototype, it overrides the value of the prototype slot. You use inheritance from prototype frames (abbreviated as protos) for
n
object renementin the Newton system there are many user interface elements that are system protos which you can use or modify in your own interface. persistent storage of datathese values are commonly stored in ROM or on a PCMCIA card.
Figure 5-1
A prototype frame
5-2
Inheritance
CHAPTER
Figure 5-2
A prototype chain
Inheritance
5-3
CHAPTER
Parent Inheritance
Besides prototypical relationships between frames, you can set up hierarchical parent-child relationships. Inheritance from parent frames is used for:
n
sharing information between objects behavior and data objects, for example creating hierarchies, like the view hierarchy of Newton applications
Figure 5-3
Parent-child relationship
5-4
Inheritance
CHAPTER
Inheritance
5-5
CHAPTER
Figure 5-4
Note
You can use the inherited keyword when sending a message, to force an inherited version of the method to be executed rather than the version in the current frame. This lookup uses only prototype inheritance. u
5-6
Inheritance
CHAPTER
Inheritance
5-7
CHAPTER
An Object-Oriented Example
You may understand inheritance better if you construct an inheritance structure on which to experiment. Use the code: frame1 := { slot1: "slot1 from frame1", slot6: 99 }; frame2 := { _parent: frame1, slot1: "slot1 from frame2", slot2: "slot2 from frame2"}; frame3 := { slot3: "slot3 from frame3", slot5: 42}; frame4 := { _parent: frame2, _proto: frame3, msg1: func() begin //show slot from parent inheritance Print(slot1); //show slot from proto inheritance Print(slot3); //show slot from parent inheritance - again //but doesn't work because // self.slot1 only searches proto chain Print(self.slot1); //show slot from proto inheritance - again Print(self.slot3); end }
5-8
Inheritance
CHAPTER
This produces the inheritance structure shown in Figure 5-5 and lets you see where slots are found in the inheritance structure.
Figure 5-5
An inheritance structure
Inheritance
5-9
CHAPTER
Built-In Functions
NewtonScript supports a number of built-in functions. The following groups of functions are included here:
n n n n n n n n n n n n n
Object system String Bitwise Array Math Floating point math Control of oating point math Financial Exception Handling Message sending Data extraction Data stufng Miscellaneous
6-1
CHAPTER
Built-In Functions
The return value is a symbol. Some of the common object classes are: 'int, 'char, 'boolean, 'string, 'array, 'frame, 'function, and 'symbol. Note that this is not necessarily the same as the primitive class of an object. For binary, array, and frame objects, the class can be set differently from the primitive class. Frames or arrays without an explicitly assigned class are of the primitive class 'frame or 'array, respectively. If a frame has a class slot, the value of the class slot will be returned. Here are some examples: f:={multiply:func(x,y) x*y}; classof(f); #1294 Frame f:={multiply:func(x,y) x*y, class:'Function}; classof(f); #1294 Function s:="India Joze"; classof(s); #1237 String See also PrimClassOf on page 6-5.
6-2
CHAPTER
Built-In Functions
Clone Clone(object) Makes and returns a shallow copy of an object; that is, references within the object are copied, but the data pointed to by the references is not. object The object to copy.
This is an efcient way to create multiple frames with the same set of slots. Here is an example: seaFrame := {Ocean: "Pacific", Size: "large" , Color: "blue"}; clone (seaFrame); #1665 {Ocean: "Pacific", Size: "large", Color: "blue"} Note that the two frames refers to the same strings. DeepClone DeepClone(object) Makes and returns a deep copy of an object; that is, all of the data referenced within the object is copied, including that referenced by magic pointers (pointers to ROM objects). object The object to copy.
It is not guaranteed that every part of the data structure is in RAM. (Certain information, such as the symbols naming frame slots, may be shared with the original object.) Contrast this function with Clone which only makes a shallow copy, and the functions TotalClone and EnsureInternal which ensure that the object exists entirely in internal RAM.
6-3
CHAPTER
Built-In Functions
GetVariable GetVariable( frame, slotSymbol) Returns the value of a slot in a frame. If the slot is not found, nil is returned. frame slotSymbol A reference to the frame in which to begin the search for the slot. A symbol naming the slot whose value you want to get.
This function begins its search for the slot in the specied frame and makes use of the full proto and parent inheritance. IsArray IsArray(obj) Returns true if object, obj, is an array. obj IsBinary IsBinary(obj) Returns true if object, obj, is a binary object. obj IsFrame IsFrame(obj) Returns true if object, obj, is a frame. obj IsImmediate IsImmediate(obj) Returns true if object, obj, is an immediate. obj The object to test. The object to test. The object to test. The object to test.
6-4
CHAPTER
Built-In Functions
IsInstance IsInstance(obj, class) Returns true if obj's class symbol the same as class or a subclass of class. obj Map Map(obj, function) Applies a function to the slot name and value of each element of an array or frame. obj function An array or frame. A function to apply to the elements or slots in obj. The function is passed two parameters: slot and value. The slot parameter contains an integer array index if obj is an array, or it contains a symbol naming a slot, if obj is a frame. The value parameter contains the value of the array or frame slot referenced by the slot parameter. The object to test.
This is equivalent to: foreach slot,value in obj do call function with (slot,value) See discussion of foreach in Foreach beginning on page 3-6. PrimClassOf PrimClassOf(obj) Returns the primitive class of an object. object The object whose primitive class to return.
Returns a symbol identifying the primitive data structure type of the object, one of: 'immediate, 'binary, 'array, or 'frame. See also ClassOf on page 6-2.
6-5
CHAPTER
Built-In Functions
RemoveSlot RemoveSlot(object, slot ) Removes a slot from a frame or array. object slot The name of the frame or array from which to remove the slot. A symbol naming the frame slot you want to remove, or the index of the array slot to remove.
This function returns the modied frame or array. ReplaceObject ReplaceObject(originalObject, targetObject) Causes all references to an object to be redirected to another object. originalObject targetObject The original object. The object to which you want to redirect references to originalObject.
This function always returns nil. Note that you cannot specify immediate objects as parameters to this function. Here is an example: x:={name:"Star"}; y:={name:"Moon"}; replaceobject(x,y); x; #469E69 {name: "Moon"} y: #46A1E9
{name: "Moon"}
6-6
CHAPTER
Built-In Functions
SetClass SetClass(object, classSymbol) Sets the class of an object. object classSymbol The object whose class to set. A symbol naming the class to give to the object.
This function returns the object whose class was set. You can set the class of the following kinds of objects: frames, arrays, and binary objects. Note that you cannot set the class of an immediate object. When setting the class of a frame, if a class slot doesn't exist, one is created in the frame. For example: x:={name: "Star"}; setclass(x, 'someClass); #46ACC9 {name: "Star", class: someClass} TotalClone TotalClone(object) Makes and returns a deep copy of an object; that is, all of the data referenced within the object is copied. object The object to copy.
This function is identical to DeepClone, except that this function guarantees that the object returned exists entirely in internal RAM. TotalClone does not follow magic pointers, so that objects referenced through magic pointers are not copied.
6-7
CHAPTER
Built-In Functions
String Functions
These functions operate on and manipulate strings. BeginsWith BeginsWith(string, substr ) Returns true if string begins with substr, or returns nil otherwise. This function is case and diacritical-mark insensitive. An empty substr matches any string. string substr Capitalize Capitalize(string) Capitalizes the rst character in string and returns the result. string is modied. string CapitalizeWords CapitalizeWords(string) Capitalizes the rst character of each word in string and returns the result. string is modied. string The string to modify. The string to modify. The string to test. A string.
6-8
String Functions
CHAPTER
Built-In Functions
Downcase Downcase(string) Changes each character in string to lowercase and returns the result. string is modied. string EndsWith EndsWith(string, substr ) Returns true if string ends with substr, or returns nil otherwise. This function is case and diacritical-mark insensitive. An empty substr matches any string. string substr StrCompare StrCompare(a, b ) Returns a negative number if string a is less than string b . Returns zero if string a and b are equal. Returns a positive number if string a is greater than string b . Case is not signicant (i.e., Hello and hello are equal). a b A string. A string. The string to test. A string. The string to modify.
Note that this is a content comparison of the two strings, not an identity comparison. StrConcat StrConcat(a, b ) Concatenates string b onto string a and returns the result as a new string. a b A string. A string.
String Functions
6-9
CHAPTER
Built-In Functions
StrEqual StrEqual(a, b ) Returns true if the two strings, a and b , are equal. a b A string. A string.
Case is not signicant. Note that this is a content comparison of the two strings, not an identity comparison. StrLen StrLen(string) Returns the number of characters in a string, excluding the null terminator. string StrMunger StrMunger(dstString, dstStart, dstCount, srcString, srcStart, srcCount ) Replaces characters in dstString using characters from srcString and returns the destination string after munging is complete. This function is destructive to dstString . dstString dstStart dstCount The destination string. The starting position within dstString. The number of characters to be replaced in dstString. You can specify nil for dstCount to go to the end of the string A string. This can be nil to simply delete the characters. The starting position in srcString from which to begin taking characters to place into dstString. The number of characters to use from srcString. You can specify nil to go to the end of srcString. A string.
6-10
String Functions
CHAPTER
Built-In Functions
Here is an example: StrMunger("abcdef", 2, 3, "ZYXWV", 0, nil) "abZYXWVf" StrPos StrPos(string, substr , start) Returns the position of substr in string, or nil if substr is not found. The search begins at character position start. (The rst character position in a string is zero.) This function is not case sensitive. string substr start Here is an example: StrPos("abcdef", "Bcd", 0) 1 StrReplace StrReplace(string, substr , replacement, count) Replaces each occurrence of substr in string with replacement . count is the number of replacements to perform, or nil to replace all occurrences. The string, string, is modied. This function returns the number of replacements performed. string substr replacement count A string. A string. A string. An integer. A string. A string. An integer.
String Functions
6-11
CHAPTER
Built-In Functions
StrTruncate StrTruncate(string, length ) Truncates a string to the indicated length, in pixels. (Of course, the length does not include the null terminator.) Returns the truncated string. string length A string. An integer.
StrTruncate requires a current font in order to work. For example, if you call it from a view, the function will use the viewFont slot information. Heres an example of how to use the function from the Inspector: {viewFont: ROM_fontsystem10, msg: func() StrTruncate("abcdefg",25) }:msg() This function adds an ellipsis (...) to the end of the truncated string. SubStr SubStr(string, start, count) Returns a new string containing count characters from string, starting at position start. Character positions begin with zero for the rst character. string start count Upcase Upcase(string) Capitalizes each character in string and returns the result. The string, string, is modied. string A string. A string. An integer. An integer.
6-12
String Functions
CHAPTER
Built-In Functions
Bitwise Functions
These functions perform logical operations on bits. Band, Bor, Bxor, and Bnot Band(a, b ) Bor(a, b ) Bxor(a, b ) Bnot(a) These bitwise functions each return an integer result of their operation on one or two integer parameters. They perform bitwise AND, OR, XOR, and NOT, respectively. a b An integer. An integer.
Array Functions
These functions operate on and manipulate arrays. AddArraySlot AddArraySlot (array , value) Appends a new element onto an array. array value An array. A value to be added as new element in the array.
Bitwise Functions
6-13
CHAPTER
Built-In Functions
For example: myArray := [123, 456] #1634 myArray addArraySlot (myArray, "I want chopstix"]) #12 "I want chopstix" myArray #1634 [123, 456, "I want chopstix"] Array Array(size, initialValue) Returns a new array with size number of elements each of which contain initialValue . size initialValue ArrayMunger ArrayMunger(dstArray , dstStart, dstCount, srcArray, srcStart , srcCount) Replaces elements in dstArray using elements from srcArray and returns the destination array after munging is complete. This function is destructive to dstArray. dstArray dstStart dstCount srcArray srcStart srcCount The destination array. The starting element in the destination array. The number of elements to be replaced in dstArray. You can specify nil for dstCount to go to the end of the array. An array. Can be nil to simply delete the elements. The starting position in the source array from which to begin taking elements to place into the destination array. The number of elements to use from the source array. You can specify nil to go to the end of the source array. An integer. A value.
6-14
Array Functions
CHAPTER
Built-In Functions
Here is an example: ArrayMunger([10,20,30,40,50], 2, 3, [55,66,77,88,99], 0, nil) [10, 20, 55, 66, 77, 88, 99] Using ArrayMunger is the most efcient way to join two arrays. To put B at the front of A: ArrayMunger(A, 0, 0, B, 0, nil) To put B at the end of A: ArrayMunger(A, Length(A), 0, B, 0, nil) You can also do this with SetUnion, which has the additional property that it eliminates duplicates, but ArrayMunger is much faster if you dont need that property. ArrayPos ArrayPos(array , item, start, test ) Searches for item in array, beginning at array position start, using test . Test is a function you supply. array item start test An array. An item that may be in the array. An integer. A function.
This function uses test to determine if an element satises the search. Test is called once for each array element and is passed two parameters:
n n
When test nds an element that satises the search criteria you want, it should return true. If you specify nil in place of a function for test, ArrayPos tests for equality.
Array Functions
6-15
CHAPTER
Built-In Functions
This function returns the array position of the rst item that tests true. If no items are found that meet the test then this function returns nil. Length Length (array ) Returns the number of elements in the array. array For example: myArray := [123, 456, "I want chopstix"] length (myArray) #12 3 Note that arrays are indexed from 0, but length returns a count of the number of characters. Therefore, the last element of this example is element 2.
Note
An array.
If you pass a string to this function, you will get a length that is (numChars+1)*2, because characters are stored in Unicode and the null terminator is counted. To get the length of strings, use StrLen instead. u SetAdd SetAdd (array , value, uniqueOnly) Appends an element to the specied array and returns the modied array. array value uniqueOnly The array to which SetAdd appends the element in value . The element to append to the array specied by array. Whether only unique elements are to be added to the array; if the value of this parameter is non-nil, SetAdd appends value to the array only if it is not already present in the array. If the element specied by the value parameter is already present in the array, SetAdd
6-16
Array Functions
CHAPTER
Built-In Functions
returns nil and does not append the element. If uniqueOnly is nil, the item is appended to the array without checking whether it is unique.
Note
The type of comparison used in this function is pointer comparison, not content comparison. u SetContains SetContains(array , item) array item An array. An item that may be in the array.
Searches each element of an array to determine if item is equal to one of the array elements. If a match is found, this function returns the array index of the matching array element. If item is not found in the array, nil is returned.
Note
The type of comparison used in this function is pointer comparison, not content comparison. u SetDifference SetDifference(array1 , array2) Returns an array that contains all of the elements in array1 that do not exist in array2 . array1 array 2 An array. An array.
The type of comparison used in this function is pointer comparison, not content comparison. u
Array Functions
6-17
CHAPTER
Built-In Functions
SetLength SetLength (array , l ength) Sets the length of an array. array length An array. An integer.
This function is useful for increasing or decreasing the size of an array. If you increase the size of the array, new elements are lled with a nil value. For example: myArray := [123, 456, "I want chopstix"] #1634 myArray setLength (myArray, 4) #1634 [123, 456, "I want chopstix", NIL] myArray [3] := 789 #3156 789 myArray #1634 [123, 456, "I want chopstix", 789] SetRemove SetRemove (array , value) SetRemove removes the specified element from the specified array and returns the modied array. The length of the array is decreased by one and all of the elements after the deleted element are shifted by one to the next lowest numbered array position. If the item is not found in the array, this function returns nil. array value
Note
The array from which SetRemove removes the specied element The element to remove from the array specied by array
The type of comparison used in this function is identity comparison, not content comparison. u
6-18
Array Functions
CHAPTER
Built-In Functions
SetUnion SetUnion(array1 , array2, uniqueFlag) Returns an array that contains all of the elements in array1 and all of the elements in array2 . array1 array 2 uniqueFlag An array. An array. If any non-nil value, SetUnion will not include any duplicate items in the array it returns. If uniqueFlag is nil, all elements from both arrays are included, even if there are duplicates.
If both of the arrays are nil, an empty array is returned. SetUnion can eliminate duplicates. If you do not need that property, you can combine two arrays more efciently using ArrayMunger. See page 6-14.
Note
The type of comparison used in this function is identity comparison, not content comparison. u Sort Sort(array , test, key) Sorts an array and returns it after it is sorted. The sort is destructive; that is, the array you give it is modied. The sort also is not stable; that is, elements with equal keys wont necessarily have the same relative order after the sort. array test An array. Denes the sort order. It can be a function object that takes two parameters A and B and returns a positive integer if A sorts after B, returns zero if A sorts equivalently to B, and a returns a negative integer if A sorts before B.
Array Functions
6-19
CHAPTER
Built-In Functions
For much greater speed, specify one of the following symbols for test : '|<| '|>| Sort in ascending numerical order Sort in descending numerical order
'|str<| Sort in ascending string order '|str>| Sort in descending string order key Denes the sort key within each array element. Specify nil to use the array elements directly as they are. You can specify a path expression, in which case the array elements are assumed to be frames or arrays and the path is applied to each element to nd the sort key. Or, you can specify a function that takes one parameter and returns the key.
This example sorts myArray in ascending numerical order according to the timestamp slot of the entries: Sort(myArray, '|<|, 'timestamp) This example sorts myArray in descending string order according to the rst and last names concatenated together: Sort(myArray, '|str>|, func (e) e.first && e.last)
6-20
CHAPTER
Built-In Functions
Abs Abs(x) Returns the absolute value of an integer or real number. x Ceiling Ceiling(x) Returns the smallest integer not less than the specied real number. (Rounds up the real number to an integer.) x Floor Floor(x) Returns the largest integer not greater than the specied real number. (Rounds down the real number to an integer.) x Random Random (low, high) Returns a random integer in the range between the two integers low and high. The range is inclusive of the numbers low and high. low high For example: random (0, 100) #120 72 An integer. An integer. A real number. A real number. An integer or real number.
6-21
CHAPTER
Built-In Functions
Adding 1 to +INF yields +INF. Dividing 1 by +0 yields -INF. Dividing 1 by -INF yields 0.
When an operation cannot produce a meaningful result, the operation delivers a NaN. For example, 0 divided by 0, +INF added to -INF, and sqrt(1) yield NaNs. NaNs propagate through arithmetic operations. Thus, the result of 3.0 added to a NaN is the same NaN. See the IEEE Floating Point standard documentation or the Apple Numerics Manual for more information on Infinities and NaNs. That manual describes SANE, the Standard Apple Numerics Environment. Newtons oating point facilities are not SANE-compliant, but include many elements of SANE.
6-22
CHAPTER
Built-In Functions
Acos Acos(x) Returns the arccosine of x. x Acosh Acosh(x) Returns the arc-hyperbolic-cosine of x. x Asin Asin(x) Returns the arcsine of x. x Asinh Asinh(x) Returns the arc-hyperbolic-sine of x. x Atan Atan(x) Returns the arctangent of x. x An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.
6-23
CHAPTER
Built-In Functions
Atan2 Atan2(x,y) Returns the arctangent of x/y in [-pi, pi] using the sign of both parameters to determine the quadrant of the computed value. x y Atanh Atanh(x) Returns the arc-hyperbolic-tangent of x. x Cos Cos(x) Returns the cosine of x. x Cosh Cosh(x) Returns the hyperbolic cosine of x. x Fmod Fmod(x,y) Returns the oating-point modulus of x and y. That is, if m = fmod(x, y) and q = trunc(x / y) then q * y + m = x. x y An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.
6-24
CHAPTER
Built-In Functions
Erf Erf(x) Returns the error function of x. x Erfc Erfc(x) Returns the complementary error function of x. x Exp Exp(x) Returns ex. x Expm1 Expm1(x) Returns the base e exponential of x - 1, that is: exp(x) - 1 x An integer or real number. An integer or real number. An integer or real number. An integer or real number.
For small enough parameters, expm1 is expected to be more accurate than the straight forward computation of exp(x) - 1. Fabs Fabs(x) Returns the oating-point absolute value of x. x An integer or real number.
6-25
CHAPTER
Built-In Functions
x > y returns x - y x <= y returns +0 If one parameter is a NaN, returns that NaN. If both parameters are NaNs, returns the rst parameter. An integer or real number. An integer or real number.
x y FMax FMax(x,y)
Returns the maximum of its two parameters. This corresponds to the max function in Fortran. NaN parameters are treated as missing data. If one parameter is a NaN and the other is a number, then the number is returned. If both are NaNs, then the rst parameter is returned. x y FMin FMin(x,y) Returns the minimum of its two parameters. This corresponds to the min function in Fortran. NaN parameters are treated as missing data. If one parameter is a NaN and the other is a number, then the number is returned. If both are NaNs, then the rst parameter is returned. x y An integer or real number. An integer or real number. An integer or real number. An integer or real number.
6-26
CHAPTER
Built-In Functions
IsFinite IsFinite(x) Returns a Boolean indicating whether or not x is innite. True means that x is nite; nil means x is innite. x IsNaN IsNaN(x) Returns a Boolean indicating whether or not x is a NaN. True means that x is NaN. x
Note
Saying that x is a NaN and is not a number are not the same thing. The string "foo" is not a number, but is not a NaN either. NaN is a special numerical value. u IsNormal IsNormal(x) Returns true if x is normalized, nil otherwise. LessEqualOrGreater LessEqualOrGreater(a, b ) Returns true if neither a nor b is a NaN, and therefore the two parameters are ordered. a b An integer or real number. An integer or real number.
6-27
CHAPTER
Built-In Functions
a is greater than or less than b Neither a or b is a NaN, and therefore the two parameters are ordered An integer or real number. An integer or real number.
a b Log Log(x)
Returns the logarithm of x. x Logb Logb(x) Returns the binary exponent of x as a signed integral value. When the input parameter is a denormalized number, the exponent is determined as if the input parameter had rst been normalized. Log1p Log1p(x) Returns the base e logarithm of 1+x, that is: log (1+x) For small enough parameters, log1p is expected to be more accurate than the straightforward computation of log (1+x). x An integer or real number. An integer or real number.
6-28
CHAPTER
Built-In Functions
Log10 Log10(x) Returns the base-10 logarithm of x. x NearbyInt NearbyInt(x) Returns x rounded to the nearest long int and delivers the result as a real. For example, 12345678.875 rounds to 12345679.0. NearbyInt differs from Rint only in that it does not raise the inexact exception. It is the NearbyInt function recommended by the IEEE oating-point standard 854. x Pow Pow(x, y ) Returns xy. x y Random RandomX(x) Returns a two-element array, based on the random seed x, which is a real. The rst element of the result is a pseudo-random number that is the result of the SANE randomx function. The second element is the new seed returned by the randomx function. x An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.
6-29
CHAPTER
Built-In Functions
Remainder Remainder(x, y ) Returns the remainder of x divided by y. x y RemQuo RemQuo(x,y) Returns a two-element array. The rst element is the remainder of x divided by y. The second element is the seven low-order bits of x divided by y as a value between 127 and 127. x y Rint Rint(x) Returns x rounded to the nearest long int and delivers the result as a real. For example, 12345678.875 rounds to 12345679.0. x RintToL RintToL(x) Returns x rounded to the nearest int. The result is undened if the rounded value is outside the range of int. x An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.
6-30
CHAPTER
Built-In Functions
Round Round(x) Returns x rounded to the nearest integral value in double format similar to the Fortran anint function. That is: add half to the magnitude and truncate. x Scalb Scalb(x, y ) Scales y by a given integer power x of 2, returning x * 2y. This is more efcient than a straightforward computation of x * 2y. x y SignBit SignBit(x) Returns a non-zero value if the sign of the parameter x is negative. This includes, NaNs, innities and zeros. x Signum Signum(x) Returns 1.0, -1.0, or 0.0, depending on the sign of x, according to these rules:
n n
If x is an integer, returns -1 if x < 0, 1 if x > 0, or 0 if x = 0. If x is a real, returns -1.0 if x < 0, 1.0 if x > 0, or 0.0 if x = 0. An integer or real number.
6-31
CHAPTER
Built-In Functions
Sin Sin(x) Returns the sine of x. x Sinh Sinh(x) Returns the hyperbolic sine of x. x Sqrt Sqrt(x) Returns the square root of x. x Tan Tan(x) Returns the tangent of x. x Tanh Tanh(x) Returns the hyperbolic tangent of x. x An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.
6-32
CHAPTER
Built-In Functions
Trunc Trunc(x) Returns a real number that contains the integral value nearest to but no larger in magnitude than x. x Unordered Unordered(a, b ) Returns true if a or b is a NaN, and therefore unordered. a b An integer or real number. An integer or real number. An integer or real number.
a is greater than or equal to b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.
a b
a is less than or equal to b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.
a b
6-33
CHAPTER
Built-In Functions
a is equal to b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.
a b
a is greater than b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.
a b UnorderedOrLess
a is less than b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.
a b
6-34
CHAPTER
Built-In Functions
FeClearExcept FeClearExcept(excepts) Clears the supported exceptions represented by excepts. excepts One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT FeGetEnv FeGetEnv(envp) Stores the current oating-point environment in the envp object. envp A pointer to an object for the oating-point environment.
6-35
CHAPTER
Built-In Functions
FeGetExcept FeGetExcept(flagp, excepts) Stores a representation of the exception ags indicated by the integer parameter excepts in the object flagp. flagp excepts A reference to an object for the oating-point exception ags. One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT FeHoldExcept FeHoldExcept(envp) Saves the current environment in the envp object, clears the exception ags, and clears oating-point exception enables. envp A pointer to an object for the oating-point environment.
FeRaiseExcept FeRaiseExcept(excepts) Raises the supported exceptions represented by excepts. excepts One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT FeSetEnv FeSetEnv(envp) Installs the oating-point environment represented by the object pointed to by envp.
6-36
CHAPTER
Built-In Functions
envp
A reference to an object for the oating-point environment. The value of envp must be set by a call to fegetenv or feholdexcept, by an implementation-dened macro of type fenv_t, or by the use of the pointer macro FE_DFL_ENV as the parameter.
FeSetExcept FeSetExcept(flagp, excepts) Sets or clears the exception ags indicated by the int parameter excepts according to the representation in the object pointed to by the pointer parameter flagp. flagp A reference to an object for the oating-point exception ags. The value of flagp must have been set by a previous call to fegetexcept. One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT This function does not raise exceptions; it just sets the state of the ags. FeTestExcept FeTestExcept(excepts) Determines which of the specied subset of the exception ags are currently set. The parameter excepts species the exception ags to be queried as a bitwise OR of the exception macros. This function returns the bitwise OR of the exception macros corresponding to the currently set exceptions included in excepts. excepts One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT
excepts
6-37
CHAPTER
Built-In Functions
FeUpdateEnv FeUpdateEnv(envp) Saves the current exceptions, installs the environment represented through its pointer parameter envp, and then re-raises the saved exceptions. envp A reference to an object for the oating-point environment.
This function, which supersedes the SANE function procexit, can be used in conjunction with feholdexcept to write routines which hide spurious exceptions from their callers.
Financial Function
This function performs nancial calculations. Annuity Annuity(rate , periods) Calculates the present value factor of an annuity at a given interest rate over the specied number of periods. rate periods The interest rate per period (for example, 12% per year would be specied as a monthly rate of .01). An integer specifying the number of periods.
Exception Functions
These functions are used to raise and handle NewtonScript exceptions in an application. For more information about exception handling and how to use these functions, refer to the chapter Exception Handling beginning on page 3-13. For a list of system exceptions, see the appendix Errors in the Newton Programmers Guide. 6-38
Financial Function
CHAPTER
Built-In Functions
The section Managing the Floating Point Environment beginning on page 6-35 describes some functions that deal with oating-point exceptions, which are not related to NewtonScript exceptions. Throw Throw(name , data) Raises an exception and creates an exception frame with the specied name and data. name data An exception symbol that names the exception being raised. The data for the exception. The possible values for this parameter depend on the composition of name and are shown inTable 6-2.
Table 6-2
Exception frame data slot name and contents Slot name Slot contents
Exception symbol
A data object, which can be any NewtonScript object A message string An integer error code
See Exception Handling beginning on page 3-13 for more information on Throw. Rethrow Rethrow() Reraises the current exception to allow the next enclosing Try statement an opportunity to handle it. Rethrow throws the current exception again, passing along the same parameters are were passed with the original call to
Exception Functions
6-39
CHAPTER
Built-In Functions
the Throw function. This allows you to pass control from within an exception handler to the next enclosing Try statement.
IMPORTANT
You can call the Rethrow function only from within the dynamic extent of an onexception clause. s CurrentException CurrentException() During exception processing (that is, inside the dynamic extent of an onexception block), returns the frame that is associated with the current exception. You can examine the frame returned by CurrentException to determine what kind of exception you are handling. For example, you can call the HasSlot function to determine if the frame contains a slot named error, and take appropriate action thereafter. (The format of the frame depends on the exception, but it always contains a name slot with the exception symbol.) CurrentException gives a meaningful response only from within the dynamic extent of an onexception clause. Outside the extent of onexception, it returns nil.
6-40
CHAPTER
Built-In Functions
parameterArray
The Perform function returns the return value of the message it sent. Note that the method named by message is executed in the context of frame, not in the context of the frame from within which Perform is called. Heres an example of using this function in the Inspector: f:={multiply: func(x,y) x*y}; perform(f, 'multiply, [10,2]); #50 20 Note that f:multiply(10,2) is equivalent to Perform(f, 'multiply,[10,2]) Apply Apply(function, parameterArray) Calls a function, passing the supplied parameters. The Apply function returns the return value of the function it called. function parameterArray The function to call. An array of parameters to be passed to the function.
Apply respects the environment of the closure it is passed. Heres an example of using this function in the Inspector: f:=func(x,y) x*y; Apply(f[10,2]); #50 20 The Apply call is equivalent to: f(10,2);
6-41
CHAPTER
Built-In Functions
All Unicode conversions use the Macintosh extended character set for codes greater than or equal to 128. ExtractByte ExtractByte(data, offset) Returns one signed byte from the given offset. data offset For example: ExtractByte("\uFFFFFFFF",0); #3FC 255 The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.
6-42
CHAPTER
Built-In Functions
ExtractBytes ExtractBytes(data, offset, length , class) Returns a binary object of class class containing length bytes of data starting at offset within data. data offset length class ExtractChar ExtractChar(data, offset) Returns a character object of the character at the given offset in the data. data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted. The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted. An integer giving the number of bytes to extract. The class of the return value.
Gets one byte at the specied offset, converts it to Unicode and returns the character it makes from it. For example: ExtractChar("\uFFFFFFFF",0); #2C76 $\u02C7 //Note $a is at offset 1 in a Unicode string ExtractChar("abc",0); #6 $\00 ExtractChar("abc",1); #616 $a
6-43
CHAPTER
Built-In Functions
ExtractLong ExtractLong(data, offset) Returns an integer object of the low 30 bits of an unsigned long at the given offset, right-justied (that is, the low 30 bits of a four-byte value). data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.
Reads four bytes at the specied offset, but ignores the high-order bits (rst two). Returns a 30 bit signed value ExtractLong("\uFFFFFFFF",0); #FFFFFFFC -1 ExtractLong("\uC0000007",0); #1C 7 ExtractXLong ExtractXLong(data, offset) Returns a 30-bit signed integer, left-justied (that is the high 30 bits of a four-byte value) from the specied offset. data offset For example: ExtractXLong("\u0000000F",0); #4 1 The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.
6-44
CHAPTER
Built-In Functions
ExtractWord ExtractWord(data, offset) Returns an two-byte signed integer object from the given offset. data offset For example: ExtractWord("\uFFFFFFFF",0); #FFFFFFFC -1 //if you want unsigned use: band(ExtractWord(-),0xFFFF); #40004 65535 ExtractPString ExtractPString(data, offset) Returns a Unicode string object derived from the Pascal-style string (a length byte followed by text) at the given offset. data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted. The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.
ExtractUniChar ExtractUniChar(data, offset) Gets two bytes at the specied offset and returns the Unicode character represented by those bytes. data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.
6-45
CHAPTER
Built-In Functions
6-46
CHAPTER
Built-In Functions
For example: x := "\u00000000"; StuffByte(x,0,-1); x[0] #FF006 $\uFF00 x := "\u00000000"; StuffByte(x,0,0xFF); x[0] #FF006 $\uFF00 StuffChar StuffChar(aString , offset, toInsert) Stuffs one byte into aString at the specied offset. aString offset toInsert A string in which data is to be stuffed. The position in aString at which stufng is to begin. A character or integer to be stuffed in aString . You pass it a two byte Unicode value as toInsert. The function makes a one-byte character from that value and stuffs the one-byte character.
If toInsert : is an integer: writes the low byte of toInsert . If toInsert: is a character: converts from Unicode and writes a byte.
6-47
CHAPTER
Built-In Functions
x := "\u00000000"; StuffChar(x,1,-1); x[0] #1A6 $\1A ExtractByte(x,1) #68 26 ExtractByte(x,0) #0 0 StuffLong StuffLong(aString , offset, toInsert) Writes four bytes at the specied offset using the 30 bit signed value you pass it as the third parameter, and sign extends it to 32 bytes. aString offset toInsert For example: x := "\u00000000"; StuffLong(x,0,-1); x[0] #FFFF6 $\uFFFF x[1] #FFFF6 $\uFFFF x := "\u00000000"; StuffLong(x,0,0x3FFFFFFA); x[0] #FFFF6 $\uFFFF x[1] #FFFA6 $\uFFFA A string in which data is to be stuffed. The position in aString at which stufng is to begin. The data to be stuffed in aString.
6-48
CHAPTER
Built-In Functions
StuffUniChar StuffUniChar(aString , offset, toInsert) Stuffs the two-byte Unicode encoding for the character indicated by toInsert into aString at the specied offset. aString offset toInsert For example: x := "\u00000000"; StuffUniChar(x,0,"\uF00F"[0]); x[0] #F00F6 $\uF00F x := "\u00000000"; StuffUniChar(x,0,0x0AA0); x[0] #AA06 $\u0AA0 StuffWord StuffWord(aString , offset, toInsert) Writes the low order two bytes of toInsert at the specied offset. aString offset toInsert For example: x := "\u00000000"; StuffWord(x,0,0x3FFF1234); x[0] #12346 $\u1234 A string in which data is to be stuffed. The position in aString at which stufng is to begin. The data to be stuffed in aString. A string in which data is to be stuffed. The position in aString at which stufng is to begin. A character or integer to be stuffed in aString .
6-49
CHAPTER
Built-In Functions
Miscellaneous Functions
These are other miscellaneous functions and methods. BinaryMunger BinaryMunger(dst, dstStart, dstCount, src, srcStart, srcCount) Replaces bytes in dst using bytes from src and returns dst after munging is complete. This function is destructive to dst . dst dstStart dstCount src srcStart A value to be changed. The starting position in dst and The number of bytes to be replaced in dst. You can specify nil for dstCount to go to the end of dst. A value. Can be nil to simply delete the contents of dst. The starting position in the source binary from which to begin taking elements to place into the destination binary. The number of bytes to use from the source binary. You can specify nil to go to the end of the source binary.
srcCount
6-50
Miscellaneous Functions
CHAPTER
Built-In Functions
Chr Chr(integer) Converts a decimal integer to its Unicode character equivalent. integer Here is an example: chr(65) $A Compile Compile(string) Compiles an expression sequence and returns a function that evaluates it. string The expression to compile. An integer.
Here are two examples. Note that, in the rst example, x is a local variable. compile("x:= {a:self.b, b:1234}") #440F711 <CodeBlock, 0 args #440F711> f:=compile("2+2") f(); #440F712 4
Note
All characters used in NewtonScript code must be 7-bit ASCII. This usually is no problem, but can create problems with Compile in certain situations. Suppose you tried this call: Compile ("blah, blah, blah, \u0F0F\u") The Unicode character is not a 7-bit character, it is 16 bits. Therefore, you get an error. (The \u switch turns on Unicode character mode.) You should do this instead: Compile ("blah, blah, blah, \\u0F0F\\u")
Miscellaneous Functions
6-51
CHAPTER
Built-In Functions
The backslash escape character preceding the \u prevents Unicode mode from being turned on for the compile. (The \u is read simply as the string "\u" instead of the Unicode switch.) Note, also, that: compile("func()...") returns a function that constructs the function. The environment is captured when the function constructor is executed: f := compile("func()b"); x := {a:f, b:0}; g:=x:a(); #440F713 <CodeBlock, 0 args #440F711> Executing the function construction captures the message environment with x as receiver. g(); #440F714 0 So now it can nd b. Ord Ord (char) Converts a character to its Unicode decimal integer equivalent. char Here is an example: ord($A) 65 A character.
u
6-52
Miscellaneous Functions
CHAPTER
Built-In Functions
6-53
CHAPTER
Built-In Functions
StrMunger(dstString, dstStart, dstCount, srcString, srcStart, srcCount ) StrPos(string, substr , start) StrReplace(string, substr , replacement, count) StrTruncate(string, length ) SubStr(string, substr , start) Upcase(string) Bitwise Functions Band(a, b ) Bor(a, b ) Bxor(a, b ) Bnot(a) Array Functions AddArraySlot(array , value) Array(size, initialValue) ArrayMunger(dstArray , dstStart, dstCount, srcArray, srcStart , srcCount) ArrayPos(array , item, start, test ) Length(array ) SetAdd(array , value, uniqueOnly) SetContains(array , item) SetDifference(array1 , array2) SetLength(array , length) SetRemove(array , value) SetUnion(array1 , array2, uniqueFlag) Sort(array , test, key) Integer Math Functions Abs(x) Ceiling(x) Floor(x) Random(low, high)
6-54
CHAPTER
Built-In Functions
Floating Point Math Functions Acos(x) Acosh(x) Asin(x) Asinh(x) Atan(x) Atan2(x, y) Atanh(x) Cos(x) Cosh(x) Fmod(x, y) Erf(x) Erfc(x) Exp(x) Expm1(x) Fabs(x) FDim(x, y) FMax(x, y) FMin(x, y) IsFinite(x) IsNaN(x) IsNormal(x) LessEqualOrGreater(a, b ) LessOrGreater(a, b ) Log(x) Logb(x) Log1p(x) Log10(x) NearbyInt(x) Pow(x, y) RandomX(x) Remainder(x, y) RemQuo(x, y) Rint(x) RintToL(x) Round(x) Scalb(x, y) SignBit(x) Signum(x) Sin(x) Sinh(x) Sqrt(x) Tan(x) Tanh(x) Trunc(x) Unordered(a, b ) UnorderedGreaterOrEqual(a, b ) UnorderedLessOrEqual(a, b ) UnorderedOrEqual(a, b ) UnorderedOrGreater(a, b ) UnorderedOrLess(a, b )
6-55
CHAPTER
Built-In Functions
Managing the Floating Point Environment FeClearExcept(excepts) FeGetEnv(envp) FeGetExcept(flagp, excepts) FeHoldExcept(envp) FeRaiseExcept(excepts) FeSetEnv(envp) FeSetExcept(flagp, excepts) FeTestExcept(excepts) FeUpdateEnv(envp) Financial Functions Annuity(rate , periods) Exception Functions Throw(name , data) Rethrow() CurrentException() Message Sending Functions Perform(frame, message, parameterArray) Apply(function, parameterArray) Data Extraction Functions ExtractByte(data, offset) ExtractBytes(data, offset, length , class) ExtractChar(data, offset) ExtractLong(data, offset) ExtractXLong(data, offset) ExtractWord(data, offset) ExtractPString(data, offset) ExtractUniChar(data, offset)
6-56
CHAPTER
Built-In Functions
Data Stufng Functions StuffByte(aString , offset, toInsert) StuffChar(aString , offset, toInsert) StuffLong(aString , offset, toInsert) StuffUniChar(aString , offset, toInsert) StuffWord(aString , offset, toInsert) Power-Related Functions AddPowerOffHandler (view) BatteryLevel(0) RemovePowerOffHandler (view) Miscellaneous Functions BinaryMunger(dst, dstStart, dstCount, src, srcStart, srcCount) Chr(integer) Compile(string) Ord(char)
6-57
APPENDIX
Reserved Words
The following words are reserved in NewtonScript. You may not use any of these words as symbols unless you enclose the word in vertical bars, like this: |self|. and begin break by call collect do div else end exists for foreach from func global if in inherited local loop mod not onexception or repeat return self send set then throw to try until while with
A-1
APPENDIX
80 81 82 83 84 85 86 87 88 89 8A 8B 8C
00C4 00C5 00C7 00C9 00D1 00D6 00DC 00E1 00E0 00E2 00E4 00E3 00E5
continued
B-1
APPENDIX
8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3
00E7 00E9 00E8 00EA 00EB 00ED 00EC 00EE 00EF 00F1 00F3 00F2 00F4 00F6 00F5 00FA 00F9 00FB 00FC 2020 00B0 00A2 00A3
continued
B-2
APPENDIX
A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA
00A7 2022 00B6 00DF 00AE 00A9 2122 00B4 00A8 2260 00C6 00D8 221E 00B1 2264 2265 00A5 00B5 2202 2211 220F 03C0 222B
continued
B-3
APPENDIX
BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1
00AA 00BA 2126 00E6 00F8 00BF 00A1 00AC 221A 0192 2248 2206 00AB 00BB 2026 00A0 00C0 00C3 00D5 0152 0153 2013 2014
continued
B-4
APPENDIX
D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8
201C 201D 2018 2019 00F7 25CA 00FF 0178 2044 00A4 2039 203A FB01 FB02 2021 00B7 201A 201E 2030 00C2 00CA 00C1 00CB
continued
B-5
APPENDIX
E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
00C8 00CD 00CE 00CF 00CC 00D3 00D4 F7FF 00D2 00DA 00DB 00D9 0131 02C6 02DC 00AF 02D8 02D9 02DA 00B8 02DD 02DB 02C7
B-6
APPENDIX
CA C1 A2 A3 DB B4 A4 AC A9 BB C7 C2 A8 F8 A1 B1 AB B5 A6 E1 FC BC
00A0 00A1 00A2 00A3 00A4 00A5 00A7 00A8 00A9 00AA 00AB 00AC 00AE 00AF 00B0 00B1 00B4 00B5 00B6 00B7 00B8 00BA
continued
B-7
APPENDIX
C8 C0 CB E7 E5 CC 80 81 AE 82 E9 83 E6 E8 ED EA EB EC 84 F1 EE EF CD
00BB 00BF 00C0 00C1 00C2 00C3 00C4 00C5 00C6 00C7 00C8 00C9 00CA 00CB 00CC 00CD 00CE 00CF 00D1 00D2 00D3 00D4 00D5
continued
B-8
APPENDIX
85 AF F4 F2 F3 86 A7 88 87 89 8B 8A 8C BE 8D 8F 8E 90 91 93 92 94 95
00D6 00D8 00D9 00DA 00DB 00DC 00DF 00E0 00E1 00E2 00E3 00E4 00E5 00E6 00E7 00E8 00E9 00EA 00EB 00EC 00ED 00EE 00EF
continued
B-9
APPENDIX
96 98 97 99 9B 9A D6 BF 9D 9C 9E 9F D8 F5 CE CF D9 C4 F6 FF F9 FA FB
00F1 00F2 00F3 00F4 00F5 00F6 00F7 00F8 00F9 00FA 00FB 00FC 00FF 0131 0152 0153 0178 0192 02C6 02C7 02D8 02D9 02DA
continued
B-10
APPENDIX
FE F7 FD B9 D0 D1 D4 D5 E2 D2 D3 E3 A0 E0 A5 C9 E4 DC DD DA AA BD B6
02DB 02DC 02DD 03C0 2013 2014 2018 2019 201A 201C 201D 201E 2020 2021 2022 2026 2030 2039 203A 2044 2122 2126 2202
continued
B-11
APPENDIX
C6 B8 B7 C3 B0 BA C5 AD B2 B3 D7 F0 DE DF
2206 220F 2211 221A 221E 222B 2248 2260 2264 2265 25CA F7FF FB01 FB02
B-12
APPENDIX
Class-Based Programming
NewtonScript is often described as an object-oriented language. However, even if (or especially if) you have some experience with other object-oriented languages, such as Smalltalk or C++, you may be a bit confused by it. NewtonScript does have many features that will be familiar to you, but it has one important difference: NewtonScript is prototype-based, rather than class-based. That is, rather than dividing the world into classes and instances for the purposes of inheritance, NewtonScript objects inherit directly from other objects. Dont forget everything you know about class-based programming, though. It is possible, and even desirable, to simulate classes in NewtonScript. Even though the language contains no explicit features to support classes, you can use a simple set of stylistic conventions to gain the familiar advantages of classes when you need them, without losing the exibility of prototypes.
C-1
APPENDIX
Class-Based Programming
Classes let you divide your programs functionality into manageable pieces. By combining a data structure with the functions that operate on it, classes make the program more understandable and maintainable. A well-written class can be reused in other applications, which saves you effort. There are plenty of reasons why classes are a good idea; you can look in any book on object-oriented programming for more. You should use the view structure of your application to divide it into parts according to the user interface. Its a good idea to implement some or all of the internal data structures as classes.
C-2
APPENDIX
Class-Based Programming
Inheritance in NewtonScript
The NewtonScript object model is prototype-based. Frames inherit directly from other frames; there are no classes. A frame may be linked to other frames through its _proto and _parent slots. These slots dene the inheritance path for the frame. When you send a message to a frame, the method that executes can use the slots of that frame (the receiver) as variables. If a variable or method reference cannot be resolved in the receiver, the proto chain is searched. If the desired slot still isnt found, the search moves one step up the parent chain, searching the parent and its proto chain, and so forth. These rules came about because they are a good t for the Newton programming environment, which is oriented around the view system. Parent inheritance provides inheritance of variables and messages through the view hierarchy: you can dene a variable in a view for all its subviews to access. Proto inheritance allows views to share common templates, and also lets most of the data stay out of RAM. Even though the inheritance system (and all of NewtonScript) is closely integrated with the view system, it is really just a set of rules that can be applied in whatever way you nd useful. You can send messages to any frame, not just a view frame, and non-view frames can take advantage of the inheritance rules as well. As this article will demonstrate, the same rules are suitable for a form of class-based programming.
Inheritance in NewtonScript
C-3
APPENDIX
Class-Based Programming
although I will use the terms class, instance, and so forth, they are all just frames being used in specic ways. The main idea is to use parent inheritance to connect instances with classes. An instance is a frame whose slots make up the instance variables, and whose _parent slot points to the class (another frame). The classs slots make up the methods. As a simple example, consider a class Stack that implements a push-down stack. It has the standard operations Push and Pop that add and remove items, and a predicate IsEmpty that determines if there are any items on the stack. The representation is very simple: just an array of items and an integer giving the index of the topmost item. The class frame looks like this: Stack := { New: func (maxItems) {_parent: self, topIndex: -1, items: Array(maxItems, NIL)}, Clone: func () begin local newObj := Clone(self); newObj.items := Clone(items); newObj end, Push: func (item) begin topIndex := topIndex + 1; items[topIndex] := item; self end,
C-4
APPENDIX
Class-Based Programming
Pop: func () begin if :IsEmpty() then NIL else begin local item := items[topIndex]; items[topIndex] := NIL; topIndex := topIndex - 1; item end end, IsEmpty: func () topIndex = -1 }; The class frame begins with the New method. This is a class method that is intended to be used as message of the Stack class itself, as in Stack:New(16). It consists simply of a frame constructor that builds an instance frame. An instance always has a _parent slot that refers to the class frame; note that because New is a message intended to be sent to the class, it can just use self to get the class pointer. The rest of the slots contain the instance variables: a topIndex slot for the index of the topmost item (-1 if the stack is empty) and an items slot for the array of items. New takes an argument that determines the maximum number of items on the stack, but it would be easy to make this dynamic (if it didnt have to t in an article like this). Its usually a good idea to provide a Clone method for a class. This lets you make a copy of an object without having to know how deep the copy has to go (such knowledge would violate the encapsulation that is one of the reasons to have a class in the rst place). In the case of Stack, a simple Clone would leave the items array shared between two instances, which would result in confusing and incorrect behavior. A DeepClone, on the other hand, would copy the entire class frame along with the instance, C-5
APPENDIX
Class-Based Programming
because of the pointer in the _parent slot. That would actually work in this case, although it would waste huge amounts of spacewatch out for this sort of mistake. The correct way to clone a Stack is to clone the instance, then give the clone a clone of the items array, which is what the Clone method above does. After the New and Clone methods, which are usually present in any class, come the methods particular to this class. The Push method increments topIndex and adds the item to the end of the items array. Note that instance variables such as topIndex and items are accessed simply by their names, because they are slots of the receiver. The Pop method calls the IsEmpty method to see if the stack is empty. If so, it returns nil; if not, it returns the topmost item and decrements topIndex. It assigns nil to the former topmost slot so it wont prevent the item from being garbage collected. The NewtonScript code you write to use a class is similar to code you would write in a language like Smalltalk. You create an object by sending the New message to its class. You use the resulting instance by sending messages to it. Of course, you do all this in NewtonScript syntax, which uses the colon for sending a message. s := Stack:New(16); s:Push(10); s:Push(20); x := s:Pop() + s:Pop(); At the end of this code, the value of x will be 30.
Practical Issues
Before getting into more advanced topics, heres some practical information about doing class-based programming with current tools. (See the Newton Toolkit Users Guide. for information about the Newton Toolkit implementation issues discussed in this section.)
C-6
Practical Issues
APPENDIX
Class-Based Programming
The Newton Toolkit as it exists today doesnt include any features that specically support class-based programming; for example, the browser only shows the view hierarchy. Nevertheless, its not too hard to get classes into your application. You need to build the class frame itself into your package, and you need to make it accessible from NewtonScript code. You can do both at once by putting the class directly into an evaluate slot of your applications main view. For the above example, you could add a slot called Stack to the main view and type the class frame just as it appears (but not including the Stack assignment (:=) line) into the browser. If you prefer, you could make the class frame a global compile-time variable by putting it (including the assignment this time) into Project Data. That wont make it available to your run-time code, however; you still have to create the Stack slot in the main view, but you can just type and enter Stackas its value. You have to put the class in Project Data if you want to use superclasses (more on this later).
Class Variables
You can create class variables, that is, variables that are shared by all instances of a class, by adding slots to the class frame. This is the same way you add variables to a view to be shared by the subviews, but its a bit more tricky because the view system does something automatically for views that you have to do manually for classes. Remember that your class frame, like all other data built at compile time, is in read-only space when your application is running. Its not possible to change the values of the slots; thus, its impossible to assign a new value to a class variable. The view system gets around this problem by creating a heap-based frame whose _proto slot points to the view and using that frame as the view. The original slots are accessible through proto inheritance, and assignments create and modify slots in the heap-based frame, overriding the initial values in the original. You can use the same trick for your class frame.
Class Variables
C-7
APPENDIX
Class-Based Programming
For example, lets say you want to have a class variable x whose initial value is zero. The class frame, dened in the Project Data le, contains a slot named x: TheClass := { ... x: 0 ... } The base view has a slot called TheClass whose value is dened simply as TheClass. At some point early in your applications execution, perhaps in the viewSetupFormScript of the view where your class frame is dened, create a heap-based version of the class and assign it to the variable TheClass: viewSetupFormScript: func () begin ... if not TheClass._proto exists then TheClass := {_proto: TheClass}; ... end Now you can use and assign the variable x in methods of TheClass. The instances will inherit it via their _parent slot, and the rst time x is assigned, an x slot will be created in the heap-based part of the class, shadowing the initial value of zero. Note that you only want to do this setup once otherwise youll end up with a chain of frames, one for each time your application has been opened. Checking for the _proto slot, as above, is one way to ensure this; you could also set TheClass := TheClass._proto in your main views viewQuitScript.
C-8
Class Variables
APPENDIX
Class-Based Programming
Superclasses
Its easy to get the close equivalent of a superclass: just give the class a _proto slot pointing to its superclass. This requires the class definitions to be in Project Data so their names are available at compile time. For example, if you have a SortedList class that should have Collection as its superclass: Collection := { ... }; SortedList := {_proto: Collection, ...}; Of course, you have to dene Collection before SortedList to do it this way. If you prefer to reverse their denitions for some reason, you can add the _proto slot later: SortedList := { ... }; Collection := { ... }; SortedList._proto := Collection; If you override a method in a subclass, you can call the superclass version using the inherited keyword. If you have class variables, note that because assignments take place in the outermost frame in the _proto chain (that is, the wrapper you create at initialization time for each class), each class gets its own version of the class variable.
Superclasses
C-9
APPENDIX
Class-Based Programming
C-10
APPENDIX
Class-Based Programming
instance as a little frame that just refers to the class and an initial instance variable prototype that stays in application space: New: func () {_parent: self, _proto: '{ ...initial instance vars... }}
Conclusion
This technique doesnt exactly simulate any existing class-based object system, but it gives you what you need to encapsulate your data types into class-like structures. I nd it to be very useful (stores, soups, and cursors all essentially follow this model), and I hope it will help you create better Newton applications. Have fun!
Biography
Walter Smith joined the Newton group in 1988. He is the principal designer and implementor of NewtonScript and the Newton object store. u
C-11
APPENDIX
nonterminal [] {choose|one}
[]*
[]+
D-1
APPENDIX
In the lexical grammar, the nonterminals are characters rather than tokens and whitespace is signicant. Because almost every construct of the language is an expression, many productions ending in expression are ambiguous; the ambiguity is resolved in favor of extending the expression as long as possible. For example, while true do 2+2 is parsed as while true do (2+2) rather than (while true do 2)+2. The specific productions affected by this rule are functionconstructor, assignment, iteration, if-expression, break-expression, tryexpression, initialization-clause, return-expression, and global-function-decl.
Phrasal Grammar
input: [constituent [ ; constituent ]* [;] ] constituent: { expression | global-declaration } expression: { simple-expression | compound-expression | literal | constructor | lvalue | assignment | exists-expression | function-call | message-send | if-expression | iteration | break-expression | try-expression | local-declaration | constant-declaration | return-expression } simple-expression: { expression binary-operator expression | unary-operator expression | ( expression ) | self } binary-operator: { arithmetic-operator | relational-operator | boolean-operator | string-operator } arithmetic-operator: { + | - | * | / | div | mod | << | >> } relational-operator: { = | <> | < | > | <= | >= }
D-2
Phrasal Grammar
APPENDIX
boolean-operator: { and | or } string-operator: { & | && } unary-operator: { - | not } compound-expression: begin expression-sequence end expression-sequence: [ expression [ ; expression ]* [ ; ] ] literal: { simple-literal | ' object } simple-literal: { string | integer | real | character | true | nil } object: { simple-literal | path-expression | array | frame } path-expression: symbol [ . symbol ]*
Note:
Each dot in ' symbol . symbol ... is ambiguous: it could be a continuation of the path expression or a slot accessor. NewtonScript uses the rst interpretation: 'x.y.z is one long path expression and not the expression: ('x).y.z. u array: [ [ symbol : ] [ object [ , object ]* [ , ] ] ] frame: { [ frame-slot [ , frame-slot ]* [ , ] ] } frame-slot: symbol : object
Phrasal Grammar
D-3
APPENDIX
'[' symbol : symbol ( is ambiguous: the rst symbol could be a class for the array, or a variable to be used as the receiver for a message send. NewtonScript uses the rst interpretation. u frame-constructor: { [ frame-constructor-slot [ , frame-constructor-slot ]* [ , ] ] } frame-constructor-slot: symbol : expression function-constructor: al-argument-list ] ) expression formal-argument-list: symbol [ , symbol ]* lvalue: { symbol | frame-accessor | array-accessor } frame-accessor: expression . { symbol | ( expression ) } array-accessor: expression [ expression ] assignment: lvalue := expression exists-expression: { symbol | frame-accessor | [ expression ] : symbol } exists function-call: { symbol ( [ actual-argument-list ] ) | call expression with ( [ actual-argument-list ] ) }
D-4
Phrasal Grammar
APPENDIX
actual-argument-list: expression [ , expression ]* message-send: [ { expression | inherited } ] { : | :? } symbol ( [ actual-argument-list ] ) if-expression: if expression then expression [ ; ] [ else expression ]
Note:
An else clause is associated with the most recent unmatched then clause. u iteration: { infinite-loop | for-loop | foreach-loop | while-loop | repeat-loop } innite-loop: loop expression for-loop: for symbol := expression to expression [ by expression ] do expression foreach-loop: foreach symbol [ , symbol ] [ deeply ] in expression { do | collect } expression while-loop: while expression do expression repeat-loop: repeat expression-sequence until expression break-expression: break [ expression ] try-expression: try expression-sequence [ onexception symbol do expression [ ; ] ]+ local-declaration: local initalization-clause [ , initalization-clause ]* initialization-clause: symbol [ := expression ]
Phrasal Grammar
D-5
APPENDIX
constant-declaration: constant constant-init-clause [ , constant-init-clause ]* constant-init-clause: symbol := expression return-expression: return [ expression ] global-declaration: { global initialization-clause | global-function-decl } global-function-decl: { global | func } symbol ( [ formal-argument-list ] ) expression
Lexical Grammar
string: " character-sequence " character-sequence: [ { string-character | escape-sequence } ]* [ truncated-escape ] string-character: < tab or any ASCII character with code 32127 except " or \> escape-sequence: { \ { " | \ | n | t } | \ u [ hex-digit hex-digit hex-digit hex-digit ]* \ u } truncated-escape: \ u [ hex-digit hex-digit hex-digit hex-digit ]* symbol { { alpha | _ } [ { alpha | digit | _ } ]* | | [ { symbol-character | \ { | | \ } ]* | }
Note:
D-6
Lexical Grammar
APPENDIX
symbol-character: <any ASCII character with code 32127 except '|' or ' \'> integer: [ - ] { [ digit ]+ | 0x [ hex-digit ]+ } real: [ - ] [ digit ]+ . [ digit ]* [ { e | E } [ - ] [ digit ]+ ] character: $ { non-escape-character | \ { \ | n | t | hex-digit hex-digit |u hex-digit hex-digit hex-digit hex-digit } } non-escape-character: <any ASCII character with code 32127 except '\'> alpha: < AZ and az> digit: { 0|1|2|3|4|5|6|7|8|9} hex-digit: { digit | a | b | c | d | e | f | A | B | C | D | E | F }
Operator Precedence
The precedence of operators, from highest to lowest, is shown in Table 2-5 on page 2-32.
Operator Precedence
D-7
APPENDIX
E-1
APPENDIX
E-2
APPENDIX
E-3
APPENDIX
E-4
Glossary
Array
Binary object
Boolean
Child Class
Constant
A sequence of numerically indexed slots (also known as the array elements) that contain objects. The rst element is indexed by zero. Like other non-immediate objects, an array can have a user-specied class, and can have its length changed dynamically. A sequence of bytes that can represent any kind of data, can be adjusted in size dynamically, and can have a user-specied class. Examples of binary objects include strings, real numbers, sounds, and bitmaps. A special kind of immediate called true. Functions and control structures use nil as false and anything else as true. If you don't have anything else use true. A frame that references another frame (its parent) from a _parent slot. A symbol that describes the data referenced by an object. Arrays, frames, and binary objects can have user-dened classes. A value that does not change. In NewtonScript the value of the constant is substituted wherever the name of the constant is used as an expression.
GL-1
Glossary
Frame
Function object
Global Immediate
Implementor Inheritance
Local
Message
Method
An unordered collection of slots, each of which consists of a name and value pair. The value of a slot can be any type of object, and slots can be added or removed from frames dynamically. A frame can have a user-specied class. Frames can be used like records in Pascal and structs in C, but can also be used as objects which respond to messages. Function objects are created by the function constructor: func(args) funcBody An executable function object includes values for its lexical and message environment, as well as code. This information is captured when the function constructor is evaluated at run time. A variable or function that is accessible from any NewtonScript code. A value that is stored directly rather than through an indirect reference to a heap object. Immediates are characters, integers, or Booleans. See also reference. The frame in which a method is dened. See also receiver. The mechanism by which attributes (slots or data) and behaviors (methods) are made available to objects. Parent inheritance allows views of dissimilar types to share slots containing data or methods. Prototype inheritance allows a template to base its denition on that of another template or prototype. A variable whose scope is the function within which it is dened. You must use the local keyword to explicitly create a local variable within a function. A symbol with a set of arguments. A message is sent using the message send syntax, frame:messageName(), where the message, messageName, is sent to the receiver, frame. A function in a frame slot that is invoked in response to a message.
GL-2
Glossary
Object
Parent PCMCIA
Proto Receiver
A typed piece of data that can be an immediate, array, frame, or binary object. In NewtonScript, only frame objects can hold methods and receive messages. A frame that is referenced through the _parent slot of another frame. Personal Computer Memory Card International Association. This acronym is used to describe the memory cards used by the Newton PDA. Newton memory cards follow the PCMCIA standards. A frame that is referenced through another frame's _proto slot. The frame that was sent a message. The receiver for the invocation of a function object is accessible through the pseudo-variable self. A value that indirectly refers to an array, frame, or binary object. See also immediate. A pseudo-variable that is set to the current receiver. An element of a frame or array that can hold an immediate or reference.
GL-3
Index
A
abs 6-21 accessor array 2-10 frame 2-12 acos 6-23 acosh 6-23 addArraySlot 6-13 annuity 6-38 APDA xiv apply 4-7, 6-41 arithmetic operators 2-24 array GL-1 accessor 2-10 object 2-9 array 6-14 array functions and methods 6-13 addArraySlot 6-13 array 6-14 arrayMunger 6-14 arrayPos 6-15 length 6-16 setAdd 6-16 setContains 6-17 setLength 6-18 setRemove 6-18 setUnion 6-19 sort 6-19 arrayMunger 6-14 arrayPos 6-15 asin 6-23 asinh 6-23 assignment comparing C and NewtonScript 2-21 description of 2-20 operator 2-20 atan 6-23 atan2 6-24 atanh 6-24
B
Band 6-13 beginend 3-1 beginsWith 6-8 binaryMunger 6-50 binary object GL-1 bitwise functions and methods Band 6-13 Bnot 6-13 Bor 6-13 Bxor 6-13 bitwise shift left 2-24 bitwise shift right 2-24 Bnot 6-13 Boolean GL-1 interpretation 2-27 object 2-5 operators 2-26 Bor 6-13 break 3-3, 3-12 built-in functions 6-1 Bxor 6-13
IN-1
INDEX
C
call with 4-7 capitalize 6-8 capitalizeWords 6-8 catching exceptions 3-20 to 3-22 ceiling 6-21 character, object 2-3 characters special, in strings 2-8 with special meanings 2-4 character set 1-9, 2-4 child GL-1 chr 6-51 class 2-1, GL-1 for an array 2-9 ClassOf 2-1 of objects 2-1 PrimClassOf 2-1 primitive 2-1 semantic types 1-3 special frame slot 2-13 special slot in frame 2-13 user-dened for frame 2-12 class-based programming C-1 ClassOf 2-1 classOf 6-2 clone 6-3 closure 4-9 code indentation 1-8 combining prototype and parent inheritance 5-5 comments, syntax 1-10 compile 6-51 compound expressions 3-1 conditional message send example 4-6 operator 4-3 constant GL-1 declaration 2-17 quoted 2-18 constructor function 4-2
object 1-9 cos 6-24 Cosh 6-24 currentException 6-40 CurrentException function 3-17
D
data extraction functions and methods 6-42 extractByte 6-42 extractBytes 6-43 extractChar 6-43 extractLong 6-44 extractPString 6-45 extractUniChar 6-45 extractWord 6-45 extractXLong 6-44 data stufng functions and methods 6-46 stuffByte 6-46 stuffChar 6-47 stuffLong 6-48 stuffUniChar 6-49 stuffWord 6-49 data type 1-3 deepClone 6-3 double inheritance 5-1 downcase 6-9 dynamic model 1-7
E
endsWith 6-9 equality operators 2-25 erf 6-25 erfc 6-25 exception frames 3-16 exception functions currentException 6-40
IN-2
INDEX
exception functions (continued) rethrow 6-39 throw 6-39 exceptions catching 3-20 to 3-22 throwing 3-18 to 3-20 working with 3-14 to 3-23 exception symbols multiple parts 3-16 prexes 3-16 types of 3-16 exists 2-30 exp 6-25 expm1 6-25 expression 1-2, 2-14 expressions compound 3-1 path 2-29 extent 1-6 extractByte 6-42 extractBytes 6-43 extractChar 6-43 extractLong 6-44 extractPString 6-45 extractUniChar 6-45 extractWord 6-45 extractXLong 6-44
F
fabs 6-25 fDim 6-26 feClearExcept 6-35 feGetEnv 6-35 feGetExcept 6-36 feHoldExcept 6-36 feRaiseExcept 6-36 feSetEnv 6-36 feSetExcept 6-37 feTestExcept 6-37 feUpdateEnv 6-38
nancial functions and methods 6-38 annuity 6-38 oating point math functions 6-22 oating point math functions and methods abs 6-21 acos 6-23 acosh 6-23 asin 6-23 asinh 6-23 atan 6-23 atan2 6-24 atanh 6-24 cos 6-24 Cosh 6-24 erf 6-25 erfc 6-25 exp 6-25 expm 6-25 fabs 6-25 fDim 6-26 feClearExcept 6-35 feGetEnv 6-35 feGetExcept 6-36 feHoldExcept 6-36 feRaiseExcept 6-36 feSetEnv 6-36 feSetExcept 6-37 feTestExcept 6-37 feUpdateEnv 6-38 fMax 6-26 fMin 6-26 fmod 6-24 isFinite 6-27 isNan 6-27 isNormal 6-27 lessEqualOrGreater 6-27 lessOrGreater 6-28 log 6-28 log10 6-29 log1p 6-28 logb 6-28 NearbyInt 6-29
IN-3
INDEX
oating point math functions and methods (continued) Pow 6-29 randomX 6-29 remainder 6-30 remQuo 6-30 rint 6-30 rintToL 6-30 round 6-31 scalb 6-31 signBit 6-31 signum 6-31 sin 6-32 sinh 6-32 sqrt 6-32 tan 6-32 tanh 6-32 trunc 6-33 unordered 6-33 unorderedGreaterOrEqual 6-33 unorderedLessOrEqual 6-33 unorderedOrEqual 6-34 unorderedOrGreater 6-34 unorderedOrLess 6-34 floor 6-21 fMax 6-26 fMin 6-26 fmod 6-24 for 3-3, 3-4 to 3-5 foreach 3-3, 3-6 to 3-10 for loop syntax 3-4 frame GL-2 accessor 2-12 class slot 2-13 description of 2-11 object 2-11 parent 5-4 _parent slot 2-13 prototype 5-2 _proto slot 2-13 slot GL-3 slot syntax 2-11
frame functions and methods ClassOf 6-2 clone 6-3 DeepClone 6-3 getVariable 6-4 primClassOf 6-5 removeSlot 6-6 replaceObject 6-6 SetClass 6-7 totalClone 6-7 func expression 4-2, 4-9 function as closure 4-13 constructor 4-2 context 4-10 denition 4-2, 4-9 nancial 6-38 func expression 4-2 global denition 4-8 global invocation 4-8 invocation 4-7, 4-11 object 4-9 object, example of 4-12 passing parameters 4-9 return expression 4-2 simple example 4-2 function context lexical environment 4-10 message environment 4-10 function object GL-2 advanced application 4-13 closure 4-9 denition 4-9 example of 4-12 parts of 4-9 functions and methods 4-1 array 6-13 built-in 6-1 data extraction 6-42 data stufng 6-46 dening 4-2
IN-4
INDEX
functions (continued) oating point math 6-22 math 6-20 message-sending 6-40 miscellaneous 6-50 object system 6-2 strings 6-8 functions and methods abs 6-21 acos 6-23 acosh 6-23 addArraySlot 6-13 annuity 6-38 apply 6-41 array 6-14 arrayMunger 6-14 arrayPos 6-15 asin 6-23 asinh 6-23 atan 6-23 atan2 6-24 atanh 6-24 Band 6-13 beginsWith 6-8 binaryMunger 6-50 Bnot 6-13 Bor 6-13 Bxor 6-13 capitalize 6-8 capitalizeWords 6-8 ceiling 6-21 chr 6-51 classOf 6-2 clone 6-3 compile 6-51 cos 6-24 Cosh 6-24 currentException 6-40 deepClone 6-3 downcase 6-9 endsWith 6-9 erf 6-25
erfc 6-25 exp 6-25 expm1 6-25 extractByte 6-42 extractBytes 6-43 extractChar 6-43 extractLong 6-44 extractPString 6-45 extractUniChar 6-45 extractWord 6-45 extractXLong 6-44 fabs 6-25 fDim 6-26 feClearExcept 6-35 feGetEnv 6-35 feGetExcept 6-36 feHoldExcept 6-36 feRaiseExcept 6-36 feSetEnv 6-36 feSetExcept 6-37 feTestExcept 6-37 feUpdateEnv 6-38 floor 6-21 fMax 6-26 fMin 6-26 fmod 6-24 getVariable 6-4 isArray 6-4 isBinary 6-4 isFinite 6-27 isFrame 6-4 isImmediate 6-4 isInstance 6-5 isNan 6-27 isNormal 6-27 length 6-16 lessEqualOrGreater 6-27 lessOrGreater 6-28 log 6-28 log10 6-29 log1p 6-28 logb 6-28
IN-5
INDEX
functions and methods (continued) map 6-5 NearbyInt 6-29 ord 6-52 perform 6-40 Pow 6-29 primClassOf 6-5 random 6-21 randomX 6-29 remainder 6-30 removeSlot 6-6 remQuo 6-30 replaceObject 6-6 rethrow 6-39 rint 6-30 rintToL 6-30 round 6-31 scalb 6-31 setAdd 6-16 setClass 6-7 setContains 6-17 setDifference 6-17 setLength 6-18 setRemove 6-18 setUnion 6-19 signBit 6-31 signum 6-31 sin 6-32 sinh 6-32 sort 6-19 sqrt 6-32 strCompare 6-9 strConcat 6-9 strEqual 6-10 strLen 6-10 strMunger 6-10 strPos 6-11 strReplace 6-11 strTruncate 6-12 stuffByte 6-46 stuffChar 6-47 stuffLong 6-48
stuffUniChar 6-49 stuffWord 6-49 subStr 6-12 tan 6-32 tanh 6-32 throw 6-39 totalClone 6-7 trunc 6-33 unordered 6-33 unorderedGreaterOrEqual 6-33 unorderedLessOrEqual 6-33 unorderedOrEqual 6-34 unorderedOrGreater 6-34 unorderedOrLess 6-34 upcase 6-12
G, H
garbage collection 1-6, C-6 getVariable 6-4 global GL-2 global function denition 4-8 global function invocation 4-8 glossary GL-1
I, J, K
ifthenelse 3-2 immediates comparing references and 2-21 object model 1-2 immediate value GL-2 implementor 4-11, GL-2 indentation of code 1-8 inx operator 2-14 inheritance 5-1 to 5-9, GL-2 combining proto and parent 5-5 double 5-1
IN-6
INDEX
inheritance (continued) interaction order 5-6 mixed proto and parent 5-5 and overriding values 5-3 parent 5-1, 5-4 PCMCIA 5-2 proto 5-1 inheritance rules history C-3 mixed proto and parent 5-5 parent 5-5 prototype 5-3 inherited description 4-4 example 4-5 in-line object syntax 1-9 instance C-1 integer 2-5 isArray 6-4 isBinary 6-4 isFinite 6-27 isFrame 6-4 isImmediate 6-4 isInstance 6-5 isNan 6-27 isNormal 6-27 iterators 3-3 for 3-4 foreach 3-6 loop 3-10 repeat 3-12 while 3-11
line separator 1-8 local variable 2-15, GL-2 log 6-28 log10 6-29 log1p 6-28 logb 6-28 logical operators 2-26 lookup 5-3 method C-3 mixed proto and parent 5-5 parent inheritance rules 5-5 prototype inheritance rules 5-3 variable C-3 loop 3-3, 3-10 loop syntax foreach 3-6 for loop 3-4 loop 3-10 repeat 3-12 while 3-11
M
map 6-5 math functions, oating point 6-22 math functions and methods 6-20 annuity 6-38 ceiling 6-21 floor 6-21 random 6-21 see also nancial functions 6-38 message 4-3, GL-2 denition 4-3 environment 4-11 receiver 4-4 message sending functions 6-40 message sending functions and methods, perform 6-40 message-send operator 4-3
L
latent typing 1-3 length 6-16 lessEqualOrGreater 6-27 lessOrGreater 6-28 lexical environment of function 4-10
IN-7
INDEX
method GL-2 denition 4-1 and function 4-1 implementor 4-11 methods and functions 4-1 miscellaneous functions and methods 6-50 apply 6-41 binaryMunger 6-50 chr 6-51 compile 6-51 isArray 6-4 isBinary 6-4 isFrame 6-4 isImmediate 6-4 isInstance 6-5 map 6-5 ord 6-52
O
object GL-3 array 2-9 binary 2-1 Boolean 2-5 character 2-3 ClassOf 2-1 class of 2-1 constructor 1-9 frame 2-11 function 4-9 inheritance C-1 in-line syntax 1-9 integer 2-5 literal syntax 1-9 model 1-2 PrimClassOf 2-1 primitive class of 2-1 real 2-6 symbol 2-6 typed data 1-2 object functions 6-2 object model immediates 1-2 references 1-2 onexception, clause 3-18 onexception clause 3-20 to 3-22 examples of 3-21 operator precedence 2-31 operators 2-19 to 2-31 arithmetic 2-24 array accessor 2-10 assignment 2-20 bitwise shift left 2-24 bitwise shift right 2-24 Boolean 2-26 conditional message-send 4-3 div 2-24 equality 2-25 exists 2-30 frame accessor 2-12
N
NearbyInt 6-29 NewtonScript character set 1-9 class-based programming 1-4 classes 1-3 comments 1-10 dynamic model 1-7 expression-based language 1-2 garbage collection 1-6 goals of 1-1 in-line object syntax 1-9 latent typing 1-3 object model 1-2 prototype-based language C-1 syntax 1-8 numbers integer 2-5 real 2-6
IN-8
INDEX
operators (continued) inx 2-14 message-send 4-3 mod 2-24 postx 2-30 prex 2-27 relational 2-25 string 2-28 unary 2-27 ord 6-52 overriding inherited value 5-3
Q
quoted constant 2-18
R
random 6-21 randomX 6-29 real numbers 2-6 receiver 4-11, GL-3 denition 4-4 self 4-4 reference GL-3 references comparing immediates and 2-21 object model 1-2 relational operators 2-25 remainder 6-30 removeSlot 6-6 remQuo 6-30 repeat 3-3, 3-12 replaceObject 6-6 rethrow 6-39 Rethrow function 3-20 return expression 4-2 rint 6-30 rintToL 6-30 round 6-31 rules inheritance, history of C-3 mixed inheritance 5-5
P
parameter passing 4-9 parent GL-3 creating a 5-4 frame 5-4 inheritance 5-4 inheritance rules 5-5 parent inheritance C-4 path expression 2-29 PCMCIA GL-3 PCMCIA card 5-2 perform 6-40 Pow 6-29 precedence of operators 2-31 PrimClassOf 2-1 primClassOf 6-5 primitive class array 2-1 binary 2-1 frame 2-1 immediate 2-1 objects 2-1 programming, class-based C-1 proto 5-2, GL-3 prototype 5-2 inheritance rules 5-3 slot 5-2
S
scalb 6-31 scope 1-4 constants 2-18 local variable 2-15
IN-9
INDEX
self GL-3 self 4-12 semantic types 1-3 semicolon 1-8 setAdd 6-16 setClass 6-7 setContains 6-17 setDifferencearray functions and methods, setDifference 6-17 setLength 6-18 setRemove 6-18 setting slot values 5-7 setUnion 6-19 short-circuit evaluation 2-27 signBit 6-31 signum 6-31 sin 6-32 sinh 6-32 slot GL-3 access 2-29 class 2-13 global GL-2 lookup 5-3 parent 5-1 _parent 2-13 proto 5-1, 5-2 _proto 2-13 setting values 5-7 special names in frames 2-13 syntax 2-11 sort 6-19 special characters in symbols 2-6 sqrt 6-32 strCompare 6-9 strConcat 6-9 strEqual 6-10 string object 2-7 operators 2-28 string functions 6-8
string functions and methods beginsWith 6-8 capitalize 6-8 capitalizeWords 6-8 downcase 6-9 endsWith 6-9 strCompare 6-9 strConcat 6-9 strEqual 6-10 strLen 6-10 strMunger 6-10 strPos 6-11 strReplace 6-11 strTruncate 6-12 subStr 6-12 upcase 6-12 strings, special characters in 2-8 strLen 6-10 strMunger 6-10 strPos 6-11 strReplace 6-11 strTruncate 6-12 stuffByte 6-46 stuffChar 6-47 stuffLong 6-48 stuffUniChar 6-49 stuffWord 6-49 subStr 6-12 symbols class 2-1 special characters in 2-6 syntax 2-6 use of 2-6 and variables 2-14 syntax comments 1-10 conventions xiii in-line object 1-9 object constructor 1-9 object literal 1-9 overview 1-8 semicolon 1-8
IN-10
INDEX
T
tan 6-32 tanh 6-32 throw 6-39 throw function 3-19 examples of 3-19 throwing exceptions 3-18 to 3-20 totalClone 6-7 trunc 6-33 try statement 3-18 examples of 3-21
V
value comparing immediates and references 2-21 immediate GL-2 lookup 5-3 reference GL-3 variable local GL-2 symbol 2-14 ViewClickScript 4-5 view system C-1
U
unary operators 2-27 Unicode 2-4 unordered 6-33 unorderedGreaterOrEqual 6-33 unorderedLessOrEqual 6-33 unorderedOrEqual 6-34 unorderedOrGreater 6-34 unorderedOrLess 6-34 upcase 6-12 user-dened class array 2-9 frame 2-12
W, X, Y, Z
while 3-3, 3-11
IN-11
INDEX
IN-12
THE
APPLE
PUBLISHING
SYSTEM
This Apple manual was written, edited, and composed on a desktop publishing system using Apple Macintosh computers and FrameMaker software. Proof pages were created on an Apple LaserWriter Pro 630 printer. Final page negatives were output directly from the text and graphics les. Line art was created using Adobe Illustrator. PostScript, the page-description language for the LaserWriter, was developed by Adobe Systems Incorporated. Text type is Palatino and display type is Helvetica. Bullets are ITC Zapf Dingbats. Some elements, such as program listings, are set in Apple Courier.
LEAD WRITER
Cheryl Chambers
WRITERS
Christopher Bey
ILLUSTRATOR
Peggy Kunz
EDITOR
David Schneider
PRODUCTION EDITOR
Rex Wolf
PROJECT MANAGER
Gerry Kane Special thanks to Peter Canning, Bob Ebert, Mike Engber, Kent Sandvik, and Walter Smith.