Difference between DO and GOTO in a macro procedure?

ObjectScript, Caché
selecttype ; select gateway or ihe
     read "Deployment Type? (G)ateway or (I)HE: ", dtype

dataentry ; first data entry routine
     if (dtype="G") {
          set dtypeFull = "Gateway"
     elseif (dtype="I") {
          set dtypeFull = "IHE"
     else {
          write !,"Invalid Choice",!
          goto selecttype
     }
     Write !, "Starting ", dtypeFull," deployment..."

 

This was what I first wrote.  Here is the test, first putting in an invalid value:

Deployment Type? (G)ateway or (I)HE: F
Invalid Choice
Deployment Type? (G)ateway or (I)HE: G
Starting Gateway deployment...

 

Then I saw this tutorial page where they call a method with "do".  So, I changed my "TODO" to a "DO".  Absolutely no other changes, now if I do the same test, here are the results:

Deployment Type? (G)ateway or (I)HE: F
Invalid Choice
Deployment Type? (G)ateway or (I)HE: G
Starting Gateway deployment...
Starting Gateway deployment...

 

Why does it output the last line twice with "DO"?

 

 

  • 0
  • 0
  • 406
  • 18
  • 1

Answers

Answered in comments.

You're really trying to get those Global Masters points, aren't you?

Just trying to make the "no answer" view more useful...

Comments

"GOTO label" jumps to a specified label in the same context frame.

"DO label" adds a new context frame. Code at the specified label will execute until a QUIT/RETURN or the end of the routine, then execution will resume at the next line after the DO command.

So in this case it's running through the whole routine (including everything under the dataentry label, with dtype already set to something valid), including printing the message at the end. Then it proceeds to the next thing after the DO command, which is printing that line again.

For what it's worth, if you're building command-line tools, %Library.Prompt may save you a lot of time. See the class reference for more informatioan.

For example:

#include %syPrompt
    New options,dtype
    Write "Deployment Utility"
    Set options(1) = "Gateway"
    Set options(2) = "IHE"
    Do ##class(%Prompt).GetArray("Deployment Type?",.dtype,.options,,,,$$$InitialDisplayMask+$$$MatchArrayMask)
    Write !, "Starting ", dtype," deployment..."
    Quit

Thanks for explaining the original issue.


As for the Prompt thing, can you explain the advantages of that over what I had?  What is $$$MatchArrayMask? It's not in the documentation.

It is in the 2015.2 documentation (you linked to 2010.1):

$$$MatchArrayMask - Only entries from the array of options are allowed, not case sensitive

Update: It looks like it first showed up in 2013.1.

So I don't really understand the "context frame" thing.  Should I treat these like BATCH files or like OOP (Javascript, C#, VB, etc)?  Do you know of any good examples of routines?  I don't have access to the SAMPLES namespace.

edit: looks like this might be my answer? http://docs.intersystems.com/cache20152/csp/docbook/DocBook.UI.Page.cls?KEY=TCOS_PassByRef1

But the "functions" have to be at the bottom?

Scott - even though you may not have access to the SAMPLES namespace, you can still look at Caché samples.  Go to download.InterSystems.com and pull down a free single-user version of Caché and then you will have full access to everything that ships with Caché in your own local playspace ;)

Looking at the docs and it says "Handles prompting for chui applications."

 

What is CHUI?

or COS CLI (Caché objectscript command line interface) :-o

 

FWIW, having looked at the internals of a lot of our classes and routines, I have hardly ever come across GOTO.

In fact, most COS programming guidelines that I have seen expressly forbid the use of GOTO since it makes the code harder to support.

One of the very first things I learned about programming as a wee lad taking Computer Science in high school is that GOTOs should be avoided, as they lead to what the textbook called "spaghetti code".

 

XKCD agrees, but for a different reason:

https://www.xkcd.com/292/

Scott, another comment, if I may...

The best practice, in routines, is to use curly braces to define procedure blocks and thus control scope, e.g.

selecttype() {

stuff

}

dataentry() {

stuff

}