Modules Methods and Recursion

From Real Software Documentation

Jump to: navigation, search

Aim

In this lesson, we will learn the basics of using Modules, Methods, and Recursion. Modules and Methods are ways of breaking a complex project into manageable pieces. Methods also allow us to re-use code in a special way. Recursion is a way of repeating actions within a program.


Contents

Repeat a String

We’re going to create a project that repeats a string a certain number of times.

  1. Launch Real Studio, if it is not already running. If it was already running, choose New Project from the File menu and create a new Desktop Application.
    You should now have a new project.
  2. Click on the Project Editor tab.
    Before we create a method we will first create a new module to put it in.
  3. Click on the Add Module button in the Project Editor.
    A module is a place to put project items that you can use from anywhere in the program.
  4. Change the module’s name in the Properties pane to “StringLibrary”.
    Renaming the module.

    Whenever you’re naming something in Real Studio, remember that you can never have any spaces in the name.
  5. Double-click on the module to open its code editor window, and click on the Add Method button.
    Real Studio will display a Code Editor in which you can provide the information about the method.
    The Method Editor.

A method must have a Method Name. You may also provide a list of arguments for the method in the Parameters box (parameters is another name for arguments). If there is more than one argument, you must separate the arguments with commas. The definition of each argument takes exactly the same form you would use with a Dim command. In this case, this method has two arguments: the first is a string called s, and the second is an integer called n.
Finally, you can turn the method into a function by declaring a single Return Type. In this case, this method is a function that returns a String.
As you will see in a moment, functions in Real Studio are exactly like functions in mathematics: they have a Domain (the set of possible arguments to the function — in this case, the set of pairs of string and integer values) and a Range (the set of possible results — in this case, the set of all strings).
Once you have created a method or function in a Module like this, you can call it just as you called the built-in methods or functions like the CDbl function we used in previous lessons.

  1. Name the function RepeatString and give it the parameters “s as String” and “n as Integer”. Set the Return Type to “String”.
  2. Click the Globe icon on the right side of the editor.
    This sets the scope of the module to Public. That means the methods is available to the whole application.
  3. After you declare the new method, enter the following code:
    Dim resultText As String
    Dim counter As Integer
    For counter = 1 to n
    resultText = resultText + s + EndOfLine
    Next
    Return resultText

    This is similar to other code we have seen before, except for the Return command, which ends the method and sends a value out to whatever expression the function was called from.
    Your code editor window should now look like this:
    The RepeatString function.

    The data type that you used as the Return Type in the declaration must match the data type of the variable “resultText”.
  4. Open the default Window1, and add a TextField, a slider, and a TextArea like this.
    The String Repeater window.

  5. Set the names of the objects, from top to bottom to the values shown in the following table:
Control Name Properties
Source Width=224, Height = 22
Repetitions Width=224, Height=16, Minimum = 0, Value = 0, Maximum = 100
Result Width=224, Height=182, Multiline = True (checked)

As well as adding methods to modules, we can add methods to the objects in our program. In this case, we’re going to add a method to the window.

  1. Switch to Window1’s Code Editor and click on the Add Method button in the Code Editor toolbar. Name the Method “Update” and leave its Parameters and Return Type blank.
    Notice how the new Method is listed in the Methods group in the left pane of the window.
  2. Enter the code shown below.
    Result.Text = RepeatString(Source.Text, Repetitions.Value)

    Note that there must be no spaces on either side of the periods. The Code Editor should now look like this:
    The Update method.

  3. Expand the Controls item in the browser and then expand the Repetitions item. Enter the following code into the ValueChanged event handler of Repetitions:
    Update

    This calls the Update method of the window whenever the value of the slider changes. That is, whenever the user slides the slider to the left or right.
  4. Run the program, type something into the top TextField, and move the slider around.
  5. Put a Breakpoint in the ValueChanged event handler, and run the program again.
  6. By clicking on the Step button, follow through as the program executes the event handler, which calls Update, which calls RepeatString.
    Notice how each method eventually exits back to the method that called it. You might also like to examine the pop-up menu above the code in the debugger, which shows the methods that haven’t yet exited, in order.
    If you select one of these, the debugger will switch to showing the code in that method, which lines is being executed there, and the variables for that method.
    You will probably find the Step Out button helpful. This finishes running the current method and then re-activates the debugger as soon as it gets back to the calling method. The Step Over command is also useful: it runs a method without stepping through any of it, and resumes debugging on the next line past the method.
  7. How Real Studio Executes a Method or Function

    It is important to understand what is going on when Real Studio executes (we also say “calls”) a method:

    • Real Studio finds some unused memory to hold the arguments to the method and any variables you Dim inside the method. The variables declared as arguments to the method are allocated and named just as if they’d been Dimmed inside the method.
    • Real Studio copies the values of the arguments from the calling method into the argument variables inside the method.
    • Real Studio makes a note of the line of the calling method it needs to execute after the method is called.
    • Real Studio executes the code inside the method.

    When the method is finished, if the method is a function, the result is copied back out to the expression from which the function is called. After exiting from a method, before it resumes the calling method, Real Studio marks the space empty that was allocated for the variables and arguments of the method that just finished.

    About Scope for Local Variables

    It is important to understand that any variables you Dim or declare as arguments in a method exist only within the method. It will be quite common for one method to Dim a variable called, say, counter and for this method to call another method which also Dims a variable called counter. These are two separate variables, and neither can see the other’s variable. So if either method modifies their counter variable, it will have no effect on the other one.

    These local variables are destroyed when the method finishes running. By “destroyed” we mean that any values these variables held are lost, and the space those variables occupied is reclaimed and available for re-use to store a different variable.
    Since the local variables a method will use are allocated and destroyed each time the method is called, their values are not retained between calls to the method.

    When you declare the data type of counter within the For line, it exists only as long as the For loop executes. It is cleared from memory after the last iteration of the loop finishes and Real Studio executes the next line of code within the method.
    The part of the program in which a variable, method, or property is visible is called its scope. We have used two levels of scope so far: the scope of variables Dimmed inside a method is limited to that method (or the loop inside the method) and Global scope within modules. Global scope, which is available only in modules, makes items available to the entire application. We will encounter other rules about scope as we learn more about Real Studio’s various features.

    Note that you can modify the arguments to a method within that method, but you’re only modifying a copy of the value that was provided in the method call; when the method ends, the value passed in is unchanged. You can put the keyword ByRef in front of the parameter declaration (as in: ByRef x As String), in which case you’re working with the original value, and can change it. This is mainly useful for sending back multiple values from a method.

    Recursion

    We saw the For-Next loop in an earlier lesson. Now we’re going to look at a very different way of repeating an action, called recursion.

    1. Open the Window Editor for Window1 and select the slider control. Change the Maximum for the Repetitions slider to 5. Also, make sure its LiveScroll checkbox is unchecked.
      These will both make tracing through the execution easier.
    2. Create a new method in the StringLibrary module with the same arguments and return types as RepeatString. Call it RepeatString2.
    3. Set RepeatString2’s code to this:
    Function RepeatString2 (s As String, n As Integer) As String
    If n<=0 then
    Return "" //no spaces between the ““
    Else
    Return s+RepeatString2(s, n-1)+EndOfLine
    End if

    You may find this code disturbing because the method is calling itself in the second Return line).
    A recursive method is similar to a mathematical proof by induction:

    • It has a recursion condition, which is an if-then (or similar) statement, to determine which of the following two things it does;
    • It has a base case, which causes it to stop calling itself, and do some final step; and
    • It has a recursive case, which causes it to:
    • perform a not-last step;
    • change whatever the recursion condition is so it’s closer to whatever makes it execute the base case; and finally
    • call itself.
    In our example, the recursion condition is:
    n <= 0
    (note that <= means less than or equal to). The base case is:
    The recursive case is:
    Return s+RepeteatString2(s, n-1)+EndOfLine

    The last step is to return an empty string; and the not-last case is to return a copy of the string, concatenated with a one-shorter duplication of the string.

    Notice here that each time the recursive case calls back into the method, it reduces by 1 the value being passed into the next invocation of the method as its n.

    Remember what we said about what happens when a method is called: it creates a brand new copy of all the variables it’s working with. The old copy is still there, waiting to finish running. And each time we call back into the same method, we get closer to the condition that will make it execute the base case and finish. Once it gets to the base condition, it all unwinds through each of the unfinished methods, finishing the evaluation of the expressions that called the method, adding one copy of the string and returning that into the evaluation of the earlier method at each stage.

    When to use Recursion

    Recursion is a little strange and probably counterintuitive to someone who hasn’t encountered it before.
    You should consider using recursion any time you want to write code that carries out some process in which, after you have carried out one step of the process, whatever is left over has to be put through the same process. Some examples:

    • Making n copies of a string involves putting together one copy with n-1 more copies;
    • Eating a sandwich involves swallowing the whole sandwich if it’s only bite-sized; otherwise, you take a bite and then repeat the whole process; and
    • To draw a tree, you draw a branch if that branch is really short; otherwise, you draw a branch and then draw a number of shorter branches attached to it.

    Once you get used to using recursive code, it’s often the easiest way to solve a problem.
    By the way, notice that in our method, we could have had n =1 as our base case (and just returned the string), but then our code wouldn’t have been able to handle being asked for zero copies of the string. That might have been alright, but if you’re not sure, it’s best to write your code so it’s the most general possible.

    Trace it

    You should change the code in Update so it calls RepeatString2 rather than RepeatString, and trace through it enough times so you’re comfortable with what the recursive code is doing. Notice how n is reduced by one each time the method calls itself, and notice how the unfinished calls to the method build up in the Stack window as you go.

    Experiment

    There are many things you could do from here, combining the things we’ve learned so far:

    • Call Update from the TextChange event in TextField, so everything gets updated when you change the text;
    • Try changing the range of the slider to go up to several thousand. Notice that things start to slow down at this level. You should be able to see that RepeatString2 starts to slow down considerably earlier than RepeatString does. This is because creating and destroying all those variables makes your program do extra work to get to the same result.
    • Try creating a different version of Update that only adds or removes enough copies of the string to make it match the slider, as a way of making it handle a larger number of repetitions more efficiently.

    An example: if the result string is 2000 characters long, our source string is 2 characters long, and the user moves the slider to 1001, rather than generating the entire 2002-character-long string, we could work out that we need to just add one more copy of the source string to the end. If the user instead moves the slider to 999, we can work out that we only need to delete the last 2 characters.

    Hint: To shorten a string, use the Left function. You already know how to lengthen it. Also notice that if the user instead changes the source string, you can’t use this shortcut: you have to build the whole string again, so you’ll probably need two different update methods.

    • Try adding a second slider (call it Repetitions2). Get the Results box to display Repetitions1.value copies of the string as a “paragraph”, followed by a couple of returns, then have Repetitions2 copies of the paragraph. You should only need to modify the single line in update to do this, and it will involve building an expression that calls RepeatString twice (so somewhere inside one of the arguments to RepeatString will be another call to RepeatString).
    • If you think this is all too easy, try to write a RepeatString3 method that can take two strings (we’ll call them the string and the delimiterdelimiter is a computer term for “separator”), and two numbers. The method will return the first number of copies of the string, followed by the delimiter, and will repeat this the second number of times.
Personal tools