M Tutorial

(Part 3)

By

Chris Bonnici

Two or More

Both procedures and functions can take more than one parameter. A comma separates each parameter. When dealing with multiple parameters, the method of how parameters are assigned to values in the calling module is by position; i.e. the first value is assigned to the first parameter, the second value to the second parameter, etc. This is known as parameter passing by position. MSM supports a dynamic type of parameter passing not very common in other programming languages. The examples that follow will demonstrate.

PROC003Þ;Parameter Characteristics - ACB - July 1997
Þ;M Web Magazine @ http://www.geocities.com/SiliconValley/7041/mwm.html
Þ;You are using this program at your own risk
Þ;
ÞW #,"1. You have passed ",$$HOWMANY("A","B","C")," parameter(s) to the function"
ÞW !,"2. You have passed ",$$HOWMANY(1,2,3)," parameter(s) to the function"
ÞW !,"3. You have passed ",$$HOWMANY("A",66)," parameter(s) to the function"
ÞW !,"4. You have passed ",$$HOWMANY("A")," parameter(s) to the function"
ÞW !,"5. You have passed ",$$HOWMANY()," parameter(s) to the function"
ÞQ
Þ;*** EOR ***
HOWMANY(PARAM1,PARAM2,PARAM3,PARAM4)
Þ;Returns parameter(s) to the calling module the number of parameters defined.
ÞN CNT
ÞS CNT=0
ÞI $D(PARAM1) S CNT=CNT+1
ÞS:$D(PARAM2) CNT=CNT+1
ÞS:$D(PARAM3) CNT=CNT+1
ÞI $D(PARAM4) S CNT=CNT+1
ÞQ CNT

From PROC003 we can conclude the following:

  • One can pass a variable number of parameters to the procedure or function. In our program we pass anything between 0 and 3.
  • Parameters are not type bound (just like M). In our example program, we sometimes pass character strings, then pass numbers.

The function HOWMANY uses the function $DATA ($D) to check if a parameter has been set. If it is, the function variable CNT is incremented. Finally CNT is returned to the calling program.

$D is very important if the number of parameters can vary. Trying to reference a parameter that does not exist will result in an error. This method helps prevent such an outcome.

Try ItWhat is the maximum number of parameters PROC003 can take? Modify the main program to verify your answer.

PROC004Þ;Parameter Characteristics - ACB - July 1997
Þ;M Web Magazine @ http://www.geocities.com/SiliconValley/7041/mwm.html
Þ;You are using this program at your own risk
Þ;
ÞW #,"1. You have passed ",$$HOWMANY("A","B","C","D")," parameter(s) to the function"
ÞW !,"2. You have passed ",$$HOWMANY("A","","C","D")," parameter(s) to the function"
ÞW !,"3. You have passed ",$$HOWMANY("A","B","C","D","E")," parameter(s) to the function"
ÞQ
Þ;*** EOR ***
HOWMANY(PARAM1,PARAM2,PARAM3,PARAM4)
Þ;Returns parameter(s) to the calling module the number of parameters defined.
ÞN CNT
ÞS CNT=0
ÞI $D(PARAM1) S CNT=CNT+1
ÞS:$D(PARAM2) CNT=CNT+1
ÞS:$D(PARAM3) CNT=CNT+1
ÞI $D(PARAM4) S CNT=CNT+1
ÞQ CNT

In this program we show you some no-dos. You can’t pass more values than there are parameters. You can’t leave a parameter undefined. Try changing line $$HOWMANY("A","","C","D") to $$HOWMANY("A",,"C","D"). You get a syntax error.

So what happens if one needs to pass the first, third and forth parameter but not the second? "Teach" your function what an empty parameter is. One easy way to do it is to pass null values as we did in our example. The problem here is that even though it is empty the parameter is still defined and $D will correctly report it.

Modify the HOWMANY function in PROC004 so that it also ignores parameters that are equal to null. Hint: For each parameter first check that it is defined ($D) then check for null. Use two separate IF commands — IF $D(… IF….

One Way?

As we demonstrated in PROC001 parameters are one way. The calling module passes a value to the called routine, but this value is not returned back. We shall now explain how to make parameters pass values both in and out.

PROC005Þ;Parameter Characteristics - ACB - July 1997
Þ;M Web Magazine @ http://www.geocities.com/SiliconValley/7041/mwm.html
Þ;You are using this program at your own risk
Þ;
Þ;*** main ***
ÞS VARIABLE=10
ÞW !!,"Before calling procedure PROC, the value of VARIABLE in the calling module is ",VARIABLE

ÞD PROC(.VARIABLE)

ÞW !!!,"After calling procedure PROC, the value of VARIABLE in the calling module is ",VARIABLE
ÞQ
Þ;*** EOR ***
PROC(VARIABLE)
ÞD SETBGCOL^COLLIB("YELLOW")
ÞW !!!,?10,"Just entered procedure PROC. Value of VARIABLE is ",VARIABLE
ÞS VARIABLE=VARIABLE+1
ÞW !!,?10,"After adding 1 to VARIABLE in procedure PROC, value of VARIABLE is ",VARIABLE
ÞD SETBGCOL^COLLIB("BLACK")
ÞQ

We took PROC001 and changed only one line (we have coloured it differently, as it might be difficult to see). To make a parameter in-out, in the calling module simply precede the variable name with the period. The output you get when you run PROC005 is


Before calling procedure PROC, the value of VARIABLE in the calling module is 10

Just entered procedure PROC. Value of VARIABLE is 10

After adding 1 to VARIABLE in procedure PROC, value of VARIABLE is 11

After calling procedure PROC, the value of VARIABLE in the calling module is 11


Everything else remains the same.

Different programming languages link the variable and parameter in an in-out scenario differently. Let us analyze how M does it.

PROC006Þ;Parameter Characteristics - ACB - July 1997
Þ;M Web Magazine @ http://www.geocities.com/SiliconValley/7041/mwm.html
Þ;You are using this program at your own risk
Þ;
Þ;*** main ***
ÞS VARIABLE=10
ÞW !!,"Before calling procedure PROC, the value of VARIABLE in the calling module is ",VARIABLE
ÞD PROC(.VARIABLE)
ÞW !!!,"After calling procedure PROC, the value of VARIABLE in the calling module is ",VARIABLE
ÞQ
Þ;*** EOR ***
PROC(PARAM)
ÞD SETBGCOL^COLLIB("YELLOW")
ÞW !!!,?10,"Just entered procedure PROC. Value of PARAM is ",PARAM
ÞW !,?5,"(Value of VARIABLE in main is ",VARIABLE,")"
P10
ÞS PARAM=PARAM+1
ÞW !!,?10,"After adding 1 to PARAM in procedure PROC, value of PARAM is ",PARAM
ÞW !,?5,"(Value of VARIABLE in main is ",VARIABLE,")"
ÞD SETBGCOL^COLLIB("BLACK")
ÞQ

We’ve modified the procedure PROC in the program PROC005 slightly to report the value of VARIABLE in the calling module. In order to "see" the value of VARIABLE, we’ve had to change the name of the parameter. Within PROC we report the value of VARIABLE. As soon as PARAM is incremented, VARIABLE is incremented as well. This means that the variables are linked (in actual fact, the procedure parameter points to the memory location holding the passed variable).

Before we conclude on this topic, there is one thing you should remember with in-out parameter passing; you can only perform this type of operation with variables and will get an error if you attempt this with literals (string or numeric). Why?

Modify PROC003 so that function HOWMANY is changed from a function to a procedure with in-out parameter passing.

You are writing a function that regulates the temperature inside a compartment within a liquid cooled supercomputer. Your function will control a coolant release valve through an in-out parameter. The formula for calculating the amount of coolant is V = 10 * t / 10000, where V is the valve setting and t is the temperature. Your function must work out V and return it back to the calling module within the second parameter of the function. It must also return the string "Red: Shutdown" if t > 1000, "Yellow: Switch some of the CPU’s off" if t > 750. All lesser values of t should cause the function to return the string "Green: Temperature OK". This is to be done via the QUIT command.

 

Goodbye

Next time we will start delving into intrinsic function, that is those functions that are standard in M. Each M implementation has a number of functions that provide quite a lot of functionality. We have already had to use some functions in the past, but now we will go through them in a proper and thorough manner.

Before we signoff we would like to re-remind you that in programming practice is an essential factor to mastering the syntax of any language. So get those fingers moving. If you have any code of your own you would like to share with others, please send it over to us at mwm@mcenter.com. We will print any code we think is appropriate.

Boolean Variables

Variables in M are untyped meaning that what can be stored within them does not have to be defined before. A program may set the variable A=10 meaning that A is storing a number after which the contents of A are changed to "Hello World" (a string). In this section we are going to talk a bit about Boolean variables. These variables are named after the mathematician George Boole. This man was fascinated by the two numbers 0 and 1 (and as some texts claim) in these numbers he saw the absence and presence of God).

A Boolean variable is a switch variable. If we place a 1 in it we mean that the variable is "on". A 0 would be equivalent to "off". When using properly named variables, Boolean variables can make your programs easy to understand and maintain.

This little game (Lander) should help you understand how you can use Boolean Variables effectively.

BOOL001Þ;Boolean Variables - ACB - Feb 1997
Þ;M Web Magazine @ http://www.geocities.com/SiliconValley/7041/mwm.html
Þ;You are using this program at your own risk
Þ;
ÞW #,/CUP(1,1),"A - Left | S - Right | W - Up | Z - Down"
ÞD LAND
ÞQ
Þ;*** EOR ***
LAND
ÞN CRAFT,X,Y,FUEL,GRAVITY,FALL,FLYING,KEYREAD
Þ;The $RANDOM function adds a touch of variability
ÞS FUEL=100,GRAVITY=1,FALL=0,X=$RANDOM(79)+1,Y=1,CRAFT="@"
ÞS FLYING=1 ;The craft is still in air
L10
ÞI 'FLYING D SCORE(FUEL,FALL,X) Q ;Quit if the craft is not flying
ÞW /CUP(24,1),/EL(2),"Fuel: ",FUEL," | Fall: ",FALL,/CUP(24,40),"BASE"
ÞW /CUP(Y,X),CRAFT
Þ;Get the ASCII key press (causes screen not to echo)
ÞR /CUP(24,79),*KEYREAD:1
ÞW /CUP(Y,X)," " ;Erase craft position
ÞS:KEYREAD=65 X=X-1,FUEL=FUEL-1
ÞS:KEYREAD=83 X=X+1,FUEL=FUEL-1
ÞS:KEYREAD=87 Y=Y-2,FALL=FALL-3,FUEL=FUEL-3 ;Moving 'UP'= dec Row position
ÞS:KEYREAD=90 Y=Y+1,FALL=FALL+2,FUEL=FUEL-1 ;Moving 'DOWN'= inc Row position
Þ;Play Gravity
ÞS Y=Y+1
ÞS FUEL=FUEL-1,FALL=FALL+1
Þ;Check if craft moved off screen
ÞS:X<1 X=79
ÞS:X>79 X=1
ÞS:Y<1 Y=1
ÞS:Y=24 FLYING=0 ;Hit the ground
ÞS:FUEL<1 FLYING=0 ;Out of Fuel. Can't Fly
ÞS:FALL>50 FLYING=0 ;Too Fast. Craft tumbles to ground
ÞW /CUP(Y,X),CRAFT
ÞG L10
Þ;*** EOR ***
SCORE(FUEL,FALL,LANDPOS)
Þ;Tells User if s/he has won. The winner must still have fuel, land at a fall of less than 10 and land in position 40-43
ÞN WONGAME
ÞS WONGAME=1 ;Assume player has won
ÞS:LANDPOS<40!(LANDPOS>43) WONGAME=0
ÞS:FUEL=0 WONGAME=0
ÞS:FALL>10 WONGAME=0
ÞI WONGAME W /CUP(12,30),"YOU WON"
ÞE  W /CUP(12,30),"YOU LOST"
ÞQ

Fill in the Survey

Showcase your work here

If you would like to send in your M-related code, simply attach a description to it, zip it up and send it to us. The description should list the files in the archive, installation notes, what the program does and copyright information. Please clarify if your submission is shareware / trialware / freeware and other information you see
appropriate.

When e-mailing information for this section please set the subject line to MWM Programs. The e-mail address is
mwm@mcenter.com.

E&OE

Tell a Friend!

1