4
$\begingroup$

Is it problematic to teach students to use an empty while loop to create an until loop? If so, what learning progressions avoid the problem? The question is an empirical one, but reasoned hypotheses and evidence would both be welcome.

Background and Context

Several thousand US middle schools and several thousand US high schools have VEX robotics equipment and RobotC licenses as contractual vestiges of Project Lead The Way (PLTW) engineering programs for middle and high schools. RobotC is a proprietary language from an institute associated with Carnegie Mellon University.

RobotC does not have an until (condition) do {} structure. http://www.robotc.net/forums/viewtopic.php?f=55&t=3059 . The PLTW curriculum uses a "Natural Language" module of RobotC that includes wait-until functions like waitUntilDistanceSensorLessThan(200), but these cause the robot to be incapable of responding to input during the wait-until statement.

In the middle school where I am teaching, my predecessor assembled the VEX kits into "squareBots," a design suggested by VEX and RobotC. The robot is equipped with two motors driving left and right sides of an eight-inch square chassis, equipped with a set of sensors. The robotics equipment engages kids, but the RobotC language has inherent problems pedagogically; this question is about one such problem in particular because I think the question is more broadly applicable than just RobotC.

The problem

To implement a wait-until algorithm capable of executing other code while waiting, I've tried teaching the idea to use

while (waiting-condition) {
  //empty loop
}

I have wondered if more students stumble with later more complex programs when I introduce the empty loop as the students' first experience of while statements. I intend to set up an experiment to verify this anecdotal observation and am fishing for ideas about the two treatments to compare.

One example of a learning progression that seems to do better

For example, I think students do better with later, more complex programs if, before using the empty while as a wait-until, they modify an infinite while loop such as

sensorValue[LED] = 0; 
//VEX uses LEDs in sensor ports and configures & assigns them as an output
while (true) {
    if (sensorValue[alertButton]) {
        sensorValue[LED] = 1; 
    }
}
$\endgroup$
  • 1
    $\begingroup$ I guess I'm confused. Your first example doesn't seem to allow other robot actions unless "waiting_condition" is quite complex. It reads like a blocking wait. The second example doesn't seem to have any break at all, unless an exception (or similar) happens elsewhere. Can you clarify? Do I need to get the RobotC specs to understand this? $\endgroup$ – Buffy Feb 21 '18 at 17:36
  • $\begingroup$ I confess that I am also a bit confused about what you're asking. $\endgroup$ – Ben I. Feb 21 '18 at 20:25
  • 1
    $\begingroup$ It looks more like you're trying to create event-driven functionality using flow-control statements. It also looks like you are trying to take the vestigial components of one program and extend them into something more than they can do. When the tool no longer serves your purposes, find a better tool. $\endgroup$ – Gypsy Spellweaver Feb 22 '18 at 0:04
  • $\begingroup$ I'm looking for the right example and practice tasks to create a guided inquiry cycle that will optimize student understanding of loop and conditional constructs using this platform. I'm also looking for greater insight (or something in the literature) to understand how this paradigm and context affects students new to CS. $\endgroup$ – Bennett Brown Feb 22 '18 at 3:00
  • $\begingroup$ Gypsy helps me understand what to look for; the tasks that students come up with are state-based and event-driven. An example task might be, "after a button is pushed, drive forward until a line taped on the floor is reached, then follow the line to the right." Students who first learn about loops and conditionals using this approach (I think) conceive of loops and conditional differently than the students who first learn about loop and conditional structures, say, traversing and conditionally altering image pixels. $\endgroup$ – Bennett Brown Feb 22 '18 at 3:00
6
$\begingroup$

To add some context from the chat room conversation: This is part of a larger course that introduces technology in an applied fashion. The segment with the robot is 10 days and the students have not necessarily programmed elsewhere.

Empty while loops

I would recommend against beginning with any empty loops for your students.

All the looping constructs are best understood when presented in manner that fulfills the purpose they were created for. An empty loop, using any of the available constructs, is using the loop for a purpose other than what it was designed for. If the loop is being placed so that you can add functionality later, at least replace the comment so that it is clear something is planned for inside the loop later. If you are using the PLTW "Natural Language" module, and start with the function

waitUntilDistanceSensorLessThan(200)

you can expand the lesson by replaceing that with the loop:

while (sensorValue[distanceSensor] >= 200) {
  // Things to do while the robot moves closer
}

That way you are not presenting an "empty" loop, but one that is planned for a purpose, and that purpose just happens to be "to be determined." Don't leave it that way either, but fill it with something real before executing the program. The comment line is showing the development process of changing the first version into a useful version. The next step is to then put something there, even if it just flashes the LED as the robot advances to the target.

while vs until

Some programming languages have an until control statement, others do not. Many of those which have both a while and an until separate their usage by having the while test the condition before the loop executes, and the until tests its condition after the loop executes. In hypothetical syntax they are commonly like this:

set(testCondition);
while (testCondition == TRUE) {
    doThisFunction();
    doSomeOtherFunction();
    update(testCondition);
}

do {
    doThisFunction();
    doSomeOtherFunction();
    update(testCondition);
} until (testCondition == TRUE)

Syntactically, the until loop is guaranteed to execute at least once and the while loop may not execute ever.

Many languages which do not have an until control statement still provide for testing before or after execution of the loop. In the case or RobotC, the language of this question, the syntax is like this:

while(SensorValue(sonarSensor) > 20)  // while the Sonar Sensor reads data greater than '20':
{
    motor[rightMotor] = 50;               // run 'rightMotor' at power level 50
    motor[leftMotor]  = 50;               // run 'leftMotor' at power level 50
}

and

do
{
    motor[rightMotor] = 50;  // run 'rightMotor' at power level 50
    motor[leftMotor]  = 50;  // run 'leftMotor' at power level 50
    bursts = bursts + 1;     // increment 'bursts' by 1
    wait1Msec(3000);         // wait for 3000 milliseconds before continuing
}while(bursts < 3)         // while 'bursts' is less than 3:

Source RobotC Wiki: Control Structures

That still leaves the testCondition as an issue, however. Based on the English usage, from which most programming languages derive their meaning, "while" and "until" are opposites. "While" implies that something is not done unless the test is true. "Until" implies that something is done unless the test is true. The while loop exits when the test condition is false (fails), the until loop exits when the test condition is true (passes). Using that, for a language which lacks the until control statement, the same functionality can be created by using a negative test. Thus until (done) becomes while (notDone), or if the language uses this syntax, while ( ! done). Thus until's usage can be created when needed. In the case of RobotC it's even possible to create the common version of a tail-test by using do {} while (! done)

Note: Perl has taken the while vs until concept and extended it into the realm of the if statement by creating an unless test:

unless (testCondition) {
    say "testCondition is FALSE";
}
else {
    say "testCondition is TRUE";
}

Limited prior programming exposure

All the above, absent the motor and sensor parts, really applies to any programming related course. It can even help prepare students for what they will encounter "in the wild" with other languages not covered by the course. The specifics of this question, however, with its short duration and unknown, but probably limited, prior programming by the students, creates extra concerns.

As made clear in one comment in chat, the students may not even understand the concept of statement block and there is precious little time to explain all the details of programming, let along all the possible variations. With the objectives of awareness/excitement about career paths in mind, planning ahead and having some of the desired variations pre-built might be helpful. For example, the first two code segments could be saved, and quickly "built" with the students. A third variation, which might be attractive to the students, is to have the LED flash faster as the distance closes with the target. Using guessed numbers for examples here, with numbers found to be useful in the lab replacing mine, the original waitUntilDistance.... line could be replaced with something like this:

int totalDistance = 500;
while (sensorValue[distanceSensor] > (totalDistance/25)) {
  sensorValue[LED] = 1;
  delay(300 * sensorValue[distanceSensor] / totalDistance);
  sensorValue[LED] = 0;
  delay(200 * sensorValue[distanceSensor] / totalDistance);
}
sensorValue[LED] = 1;

That will give a duty-cycle of 60% and an initial frequency of 2 flashes per second, and a final frequency of 50Hz. Another chance to reinforce some math and science, increase the engagement with the robot, and not introduce new programming concepts.

In consideration of the limited time and limited programming exposure before this segment, I think that introducing the empty loop

while (waiting-condition) {
  //empty loop
}

will cause more students to stumble, and not necessarily later. The emptiness might make apprehending the statement block concept more difficult than it already is. I'm also not so sure you should even divert into the infinite loop of while (true) {} at all. If you do use the LED-alertButton combination you presented in the question, modify it to respond as a toggle rather than a one-shot that turns on and then appears to ignore all future button presses. The program might loop forever, but it will look to the students like it turns on the LED and then stops responding.

$\endgroup$
  • 1
    $\begingroup$ I think the 'while' and 'do until' examples need to have the termination condition flipped ...? The first does a task while a condition remains true, the other does a task until the condition becomes true. $\endgroup$ – Mr Bradley Feb 22 '18 at 15:14
  • $\begingroup$ @MrBradley If the "examples" you refer to involve the motor movement, then they were copied as-is from the referenced web site. If you're referring to a different section, then I don't understand what you think should be "flipped". $\endgroup$ – Gypsy Spellweaver Feb 22 '18 at 16:41
  • $\begingroup$ the first code block following while vs until above. $\endgroup$ – Mr Bradley Feb 22 '18 at 20:03
  • $\begingroup$ @MrBradley with the possible exception of Python, which I don't know, the two loops are correctly written. $\endgroup$ – Gypsy Spellweaver Feb 22 '18 at 20:53
  • $\begingroup$ @philipxy If either one has its test reversed then they they become operationally equivalent except for the timing of the test. The example then looses its demonstration of opposite effects for the same test condition. $\endgroup$ – Gypsy Spellweaver Feb 23 '18 at 21:56
2
$\begingroup$

This answer will be a bit different, I hope, and more general.

Programming physical robots is inherently different from simple procedural test and command driven programming. It is essentially event driven with events happening outside the program but needing to be handled by it. Some of this sort of thing occurs in, say, Java when you write GUI code that must respond to external events asynchronously.

So, the first bit of advice, given this situation, is to teach them robot programming driven by asynchronous events. The RobotC language, while a small subset of C structurally, has an extensive library to handle such events. So, teach that, rather than trying to teach something else that sort of works.

My advice in general, is that if you have chosen, or been given, a language to teach, then teach that language, not some other thing. For example, don't try to teach Python thinking of it as just Java without braces. It is a different thing.

However, if you don't like the language you have then one alternative, assuming you have a bit of time and freedom, is to create a different language that is more to your liking. You can't do this in the next few days, as it takes a while to build the infrastructure, but it isn't impossible. You can define a language and write a compiler for it. The target (output) language could be RobotC so that you get automatic access to the libraries provided. High level to high level compilation is a bit easier, in fact, than high to low level language compilation as you can take advantage of the (higher level) features of the target language in your "code generator". It adds a step to program creation (compiling the resulting RobotC code) but that can be automated. If your language is well defined then you can use standard compiler building tools to make the job easy. Scanners and Parsers are standardized building blocks.


However, (the final however) if you can't make that work for you and you have limited time, then first focus on the language as given, respecting the intent of the creators of the language and teaching students how to use it well. Make sure that they understand the concepts of that language and the environment for which it is intended. But save a day or two at the end for a "beyond the horizon" look at programming. In that final wrap up session, you can talk about the limitations that were imposed by the language you've been using and some ideas (for their future study) that can be used to remove those limitations. So you close by opening another door for them. And this has much less chance of confusing them or burdening them with awkward constructs.

Your students won't be happy with you if they later learn that you were using a given language badly, even if you have good intentions. You can't teach them everything they will need to know in just a few days, but you can do a few things well. KISS = Keep it simple, students.


An easy to use compiler builder suite is CoCo/R. You define a language as an Attribute Grammar (ATG) and the tool creates a scanner and parser from the ATG. You need to provide a semantic analyzer and code generator, but you can annotate the ATG to simplify this. The input language defined in the ATG needs to be (largely) LL(1), but a learning language should have that characteristic in any case. The tool will give you an analysis of your language as well. I've made extensive use of CoCo/R both in teaching and in building such "bridge" languages. And building your first compiler is a joy beyond joy.

$\endgroup$
1
$\begingroup$

What you are looking for is "old style" macintosh like event driven programming. It's still there under the covers in Windows, but the high level libraries tend to hide the implementation.

Your main event loop:

quit = false;
while (!quit) {
    event = getNextEvent();
    dispatchEvent (event);
}

An event is a data structure that contains what, where, and when, plus supporting data. For example keystroke from USB keyboard at 16:01:00.000, or packet received from network at ... .

getNextEvent () simply pulls the next available event off of a queue. In the original macintosh I believe they used a circular queue implemented on an array of pointers.

getNextEvent may actually call polling routines, or the event queue may be populated by asynchronously.

dispatchEvent is a wrapper around a big "switch" statement. A typical form would be something like this:

switch (event.source)
{
case KEYBOARD: 
    dispatchKeys(event);
    break;
case MOUSE:
    dispatchMouse(event);
    break;
case ....

}
$\endgroup$
1
$\begingroup$

On a different note, it is much more effective to use simulated robot environments when first introducing programming to students. The addition of the H/W elements in physical robots (along with more complicated software environments) make the combination more difficult. This would only be exacerbated with a short time line.

You could even replicate the physical nature of the robots in code before they work directly with them - giving them a sort of preview of the issues they will encounter.

Alternatively there are more user friendly robot development kits available today that you can look into.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.