[comp.sys.mac.hypercard] passing param's by reference

KOFOID@cc.utah.edu (08/09/90)

HyperTalk does not allow parameter passing by reference. If I understand
correctly, version 2 will be the same. This makes it difficult to write
generalized handlers for modular use.

I can imagine two ways to do this, but I'm not sure either is possible:

1) Pass a handle to the container being used as a parameter and dereference it
within the script body. The problem is finding the handle. There is no
legitimate way in HT of determining this.

2) Pass the body of a script to an XCMD, which then executes it and sets the
appropriate containers to values calculated within the script. However, the
available glue routines only allow XCMDs to execute singe HT expressions. I am
not at all sure how one could extend this to the execution of a script body,
without first writing an entire HT interpreter, which essentially recreats
HyperTalk within an XCMD!

Does anybody have any ideas? Please don't tell me to use functions! The point
is to be able to manipulate data in a highly generalized fashion *at the
source*, very much like Pascal var parameters.

Cheers,

Eric.

 __________________________________________________________________
|                          (801) 581-3592                          |
|  Snail: Eric Kofoid; Dept. Biology, U. of Utah; SLC, UT 84112    |
|   Fast: bi.kofoid%science@utahcca (BitNet)                       |
| Faster: bi.kofoid@science.utah.edu (InterNet)                    |
|Fastest: kofoid@bioscience.utah.edu (InterNet -> QuickMail)       |
|                                                                  |
| -- The University of Utah is blameless for anything I've said -- |
|__________________________________________________________________|

samr@ellis.uchicago.edu (Samuel A. Rebelsky) (08/11/90)

In article <83758@cc.utah.edu> KOFOID@cc.utah.edu writes:
>HyperTalk does not allow parameter passing by reference. If I understand
>correctly, version 2 will be the same. This makes it difficult to write
>generalized handlers for modular use.
>

If I understand your question(s) correctly, it is possible to create
very general handlers by using the "do" command.

For standard HyperCard objects (such as fields and buttons), you don't
have to be too creative.  For example, consider the following function that
sets some text attributes of a more-or-less arbitrary object.

-- HANDLER:
--   setTextAttribs
-- PARAMETERS:
--   theObj -- a description of an object
-- DESCRIPTION:
--   Sets the attributes of the named object to my favorite values
on setTextAttribs theObj
  do "set the textFont of" && theObj && "to Courier"
  do "set the textSize of" && theObj && "to 12"
  do "set the textStyle of" && theObj && "to bold,italic"
end setTextAttribs

In conjunction with handlers like the above, I often add a utility
function called "quoteIt" that replaces single quotes with double
quotes (you'll see why in a minute). 

-- FUNCTION:
--   quoteIt
-- PARAMETERS:
--   theString -- a string
-- DESCRIPTION:
--   Returns a copy of theString with all instances of the single quote
-- character (') replaced by a double quote (").
function quoteIt theString
  repeat while "'" is in theString
    put quote into char offset("'", theString) of theString
  end repeat
  return theString
end quoteIt

Now, calls to setTextAttribs can take many forms -- the only restriction
is that you should pass a string that names the object.  Some standard
examples follow.

   -- use quoteIt to form the name of the object
   setTextAttribs quoteIt("card button 'Order Pizza'") 
          
   -- use HyperTalk's "name of" function
   setTextAttribs (the name of card field "Favorite Toppings")

   -- put in the quotes by hand
   setTextAttribs "background field" && quote & "Cheeses Used" & quote

   -- abuse HyperTalk's willingness to "fill in the quotes" for objects
   -- whose name consists of a single word.
   setTextAttribs "background button Cook"

Note that the four tricks above all work with many of the Dartmouth
XCMDs/XFCNs (which suggest the latter two sol'ns).

---

I'm not sure if the above completely answers your question, as it
sounds like you actually want to reference variables rather than
objects.  As long as you deal with global variables, you should be able
to use a similar technique.  For example:

-- HANDLER:
--   doSquare
-- PARAMETERS:
--   theVar -- a text string containing the name of a numerica global
--             variable
-- DESCRIPTION:
--   Squares the global variable "in place"
on doSquare theVar
  global A,B,C,X,Y,Z -- include any global variables you may want square
  do "put" && theVar && "*" && theVar && "into" && theVar
end doSquare

-- HANDLER:
--   testSquare
-- PARAMETERS:
--   none
-- DESCRIPTION:
--   Tests the "doSquare" routine
on testSquare
  global X
  repeat forever
    ask "What initial value do you want to use" with 5
    if it is empty then
      exit testSquare
    end if
    put it into X
    answer "X is originally" && X
    doSquare "X"
    answer "After one square operation, X is" && X
    doSquare "X"
    answer "After two square operations, X is" && X
    answer "Try it again?" with "Yes" or "No"
    if it is "No" then
      exit repeat
    end if
  end repeat
end testSquare

---

Clearly, this isn't all the elegant, and it's slower than one would hope
(the "do" command takes a lot of extra time), but I hope that it at least
gives you a start on what you want to do.  I will warn you that excessive
use of the "do" command makes debugging extremely painful.

Samuel A. Rebelsky			samr@cs.uchicago.edu 		or
					samr@midway.uchicago.edu