Metaphor: The Electronic Kitchen
Module 2
Browsing, typing, using an application
+ Being a guest at a dinner party:
enjoying the meal
Module 3
Authoring, designing a system
+ Being the host of a dinner party:
ordering the meal
Module 4
Scripting, writing a program
+ Being the staff of a dinner party:
preparing the meal
Simple Information
Integers, such as 0, 3, 8594785 (there are no commas in HyperTalk
numbers)
Real numbers, such as 0.232, 78.9001
Strings, which are characters enclosed in quotes, such as "THIS IS A
STRING", or "So is this!!!", or "90"
Boolean information, which can be just two values, true or false
Structured Information
The basic unit of structured information in HyperTalk
is the field
Fields may be divided into
(1) Lines, separated by carriage returns
(2) Items, separated by commas
(3) Words, separated by spaces
(4) Individual characters
and can be combined: char 3 of word 1 of line 6 of field 4
Example: The No Account stack
Chunk HyperTalk Description
all of Able's account line 1 of card field "Data"
the fourth name item 1 of line 4 of card field "Data"
Floyd's account id item 2 of line 3 of card field "Data"
the last 3 digits of Zogg's id char 3 to 5 of item 2 of line 13 of
card field "Data"
Notice how chunks are described from small to large
HyperTalk Variables
HyperTalk variable names can be as long as you wish, as long as
(1) They begin with a letter
(2) The initial letter is optionally followed by letters, digits, or
the underscore
(3) They not duplicate any words which have special meaning to
HyperTalk, like put or repeat
Examples:
Legal variables: x, line_count, Convert2Decimal
Illegal variables: line count, A+, 2Decimal (why?)
HyperTalk is case-insensitive
Information Processing: Toss, Blend, and Dribble
Moving information:
put source expression into destination
Examples:
put 0 into totalSoFar (places zero into a variable)
put empty into card field 1 (erases a card field)
put "Hi" (places two characters in Message box)
put word 3 of line 1 of card field 3 into field "Result"
HyperTalk assumes fields live in backgrounds. If there's a field on a
card, you must let HyperTalk know by using the word card.
Numeric Operations
The numeric commands: add, subtract, multiply, and divide, and their
operator forms +, -, *, and /.
Some sample arithmetic expressions:
add 1 to sum
put x + 3 into field "holder"
subtract sum from sum
multiply sum by 1.1
put 3.6 * (sum + 5 / (x + 2)) into field "holder"
The lines with double hyphens are comments.
String Operations
& concatenates: It attaches strings end to end
&& concatenates with a blank between
length(string), returns the number of characters, including spaces,
tabs, and return characters, in the variable string
number of chunks in source. This counts the number of chunks of the
kind specified in the text source, as in
put number of lines of card field "Data" into num
(The words in and of are interchangeable in chunk descriptions.)
Logical (Boolean) Operators
Operator Action
op1 = op2 true when op1 and op2 have the same value
op1 op2 true when op1 and op2 have different values
( is Option-=; can also be written <>)
op1 < op2 true when op1 is less than op2
op1 ¾ op2 true when op1 is less than or equal to op2
(¾ is Option-<; can also be written <=)
op1 > op2 true when op1 is greater than op2
op1 op2 true when op1 is greater than or equal to op2
( is Option->; can also be written >=)
(These last three require op1 and op2 to be boolean)
op1 and op2 true when op1 and op2 are true
op1 or op2 true when either op1 or op2 or both are true
not op1 true when op1 is false
Flow of Control
Unless there is instruction to the contrary, HyperTalk and most other
languagesexecute their statements in the order they appear.
We often want to execute statements in different order than they are
written, depending on what is happening as the program is being run
Conditional: The if Statement
if boolean expression then
statements
end if
or
if boolean expression then
statements
else
statements
end if
These act exactly as you would expectthe part after if is done only when
the boolean expression is true.
Repetition: The repeat Statements
repeat with index = start exp to finish exp
statements
end repeat
(1) start exp(ression) and finish exp(ression) are each evaluated at
the start, and not modified thereafter.
(2) index is set to start exp.
(3) If variable is less than or equal to finish expression, steps (a)
and (b) are performed, otherwise step (4).
(a) The statements are performed.
(b) The variable is increased by 1 and control passes to step (3)
again.
(4) Control is passed to the statement following end repeat.
Example: To find the average of all balances (that is, all word 4s of all
lines)
on mouseUp
--first, check to make sure there is data
if card field "Data" is empty then
answer "Enter data before calculating or sorting" ¬
with "OK, I will"
else
-- initialize a counter variable
put 0 into totalSoFar
-- this is for our convenience, so we don't have to write
-- "number of lines of card field "Data"" twice later
put number of lines of card field "Data" into num
-- go line-by-line through the data field, adding up balances
repeat with count = 1 to num
add word 4 of line count of card field "Data" to totalSoFar
end repeat
set numberFormat to "0.##"
-- So that average will be rounded to two decimal places
put totalSoFar/num into average
-- display the result
put "Total balance of $" & totalSoFar && "for" &&
num && "accounts" & return & return into card field "Results" put
"Average balance = $" & average after card field "Results" set the
scroll of card field "Results" to 0 end if
end mouseUp
Unit-Level Control
Each objectstack, card, field, buttonhas a script associated with it.
Objects pass information among themselves by messages.
Messages are generated by user events, such as mouse clicks and typing,
or they can be generated from within scripts.
Messages are received and acted upon by parts of scripts called message
handlers.
The Message Handler
Example: A button that beeps when it is pressed
on mouseUp
-- when the button receives a mouseUp message
beep 1
-- do a single beep
end mouseUp
The lines with double hyphens are comments.
A message handler always looks like
on event name
statements to respond to event
end event name
An object's script may contain many message handlers, but only one
handler is permitted for each event.
Example: A noisier button could have two handlers in its script
on mouseUp
wait 1 second
-- you should be able to figure out what this does
beep 1
end mouseUp
on mouseDown
beep 2
end mouseDown
How does HyperCard know where to send messages?
HyperCard rules for messages:
(1) Messages to which a button or field can respond are sent to the
button or field where the mouse pointer is at present.
(2) Messages that are appropriate for cards are sent to the current
card.
(3) Messages that are appropriate for cards as well as buttons or
fields, are sent to the button or field if the pointer is currently in
one of those objects, or to the current card, if the pointer isn't in a
button or field.
Some of the 36 HyperCard messages and their possible destinations
Destination Message Sent when
Button mouseUp mouse button is released
or field mouseDown mouse button is pressed
mouseStillDown button still down, pointer still in object
mouseEnter pointer has entered object
mouseLeave pointer was in object, has left
mouseWithin pointer in object
Card mouseUp, mouseDown, mouseStillDown
openCard card becomes current (displayed)
closeCard another card becomes current
openStack stack with this card is opened
closeStack stack with this card is closed
quit quitting HyperCard
idle nothing is happening
The Object Hierarchy
HyperCard deals uses an object hierarchy to determine how messages are
sent and passed.
At each level in the hierarchy, if a message is inappropriate for that
object, or if the object has no handler, the message is sent to the next
level.
The levels are:
Button or field --> card --> background -->
stack --> Home stack --> HyperCard
A Sample Object Hierarchy
To provide a beep for every mouse click on card 55:
We could put a single mouseDown handler in the card's script, and not in
any of the objects on the card.
If button 1 already had a mouseDown handler to do something else, we could
use HyperTalk's pass command to pass the mouseDown message up to card 55 by
including
pass mouseDown
in the button's mouseDown handler.
Script-Generated Messages
A script can generate messages by proclaiming their names.
The named message is sent up the hierarchy, starting at the object whose
script generated the message.
Somewhere in the hierarchy there must be a handler for the message.
Example:
on mouseUp
--this might be in button 1 of card 55
--of stack "Fred"
some statements
makeNoise -- send a message
some more statements
end mouseUp
on makeNoise
-- this handler could be anywhere at or above
-- button 1 in the hierarchy: button 1, card 55,
-- stack "Fred", or Home stack
beep
wait 1 second
beep
end makeNoise
Information Control: at 425 degrees for 40 minutes
We frequently need to say "Do this, using that, this many times."
This is accomplished by including parameters as part of a message.
Example: A handler to interchange line1 and line2 of card field Data.
on swap line1, line2
------------------------------------------------------------------
-- Interchanges line1 and line2 in card field "Data"
------------------------------------------------------------------
put line line1 of card field "Data" into tempLine
put line line2 of card field "Data" into line line1 of card field "Data"
put tempLine into line line2 of card field "Data"
end swap
swap is used to sort card field 1 in No Account. It is part of the script
for the "Do it!" button.
on mouseUp
------------------------------------------------------------------
-- Here's where the actual sorting goes on.
-- Uses a selection sort, by repeatedly finding the least item,
-- and swapping its line into its proper place in the field
------------------------------------------------------------------
.
. Some lines are omitted here for clarity
.
repeat with current = 1 to ¬
(number of lines of card field "Data") - 1
put FindMin(current, whichWord, 1) into found
swap current, found
end repeat
end mouseUp
FindMin returns the line number at or after current with the smallest item.
Example: How selection sort works
We have boxed the current element and outlined the element found by FindMin:
FindMin is a function handler. A function handler returns a single value
back to the script that called it.
The result of a call to a function handler may be used anywhere a variable
may.
A function handler is written slightly differently than a command
handler:
function Its name Its parameter list
-- Note that we start with "function", not "on"
statements
return some value or expression
-- This says, "Set the value that will be
-- sent back to the calling script."
-- A function handler may have several
-- return statements.
statements
end Its name
The FindMin Function Handler
function FindMin startingLine, whichWord
------------------------------------------------------------------
-- Finds the location of the least element among all words "whichWord"
-- in card field "Data" beginning at line "start" in that field.
------------------------------------------------------------------
-- Initialization: As far as we know now, the smallest value is
-- the first one we are going to look at
put startingLine into where
-- so we'll store its line number in "where'
put word whichWord of line startingLine of card field "Data" into currentMin
-- and its value in "currentMin"
-- Here's where we look through each line from "start"
-- to the last line in the field, looking for the smallest item
repeat with thisLine = startingLine to number of lines of card field "Data"
if word whichWord of line thisLine of card field "Data" < currentMin then
-- We found a new smallest element, so save its value
put word whichWord of line thisLine of card field "Data" into currentMin
-- and save the line number where we found it
put thisLine into where
end if
end repeat
-- We're done checking lines, so we return the location of the least item
return where
end FindMin
Stages of Program Design
Conception: precise specification of the software
Incubation: design of the software
Birth: coding, according to the design, and debugging
the code
Growth: testing, to make sure the code performs as specified
Maturity: maintenance of the software
The Software Blueprint
Having designed the software blueprint, we then coded everything, but in
skeleton form.
Top-down design is a useful technique for writing programs (and for other
tasks as well).
We used stubs like this
on mouseUp
put "This button will eventually sort" ¬
into card field "Results"
end mouseUp
Advantages:
If things go wrong, you have a good idea where the error is.
At any stage, you have a working (if limited) application, so you can check it as you go.
Coding
We used a large-to-small approach.
We first used a pseudocode description of the sorting routine to help us
organize our thoughts:
on mouseUp
repeat with lineNum = 1 to the end of the list
find the smallest item in the list at or after lineNum
swap the line containing that item with line lineNum
end repeat
end mouseUp
We'll need command handler to swap two lines and a function handler to find
the line with the smallest item.
We then wrote those handlers, though in more complicated situations we
might have repeated the process, breaking the parts into subparts.
Testing
A simple rule holds here: Try everything!
Have someone else try your application with no coaching from you.
When errors occur, it is helpful to include embedded statements to display
messages:
put "About to sort. Using field" && theField
This places a message in the Message box so you can watch the execution as
it goes.
Maintenance
We write programs for people, as well as for computers.
Someone will have to maintain the program later.
Always write your programs to make things as easy as possible down the
road:
Make the code logical, simple, and modular.
You can never have too many comments!