Difference between DO and GOTO in a macro procedure?
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"?
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.
I blame Google!
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…
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 ;)
You could probably download the single-user evaluation version of Caché to get a look at the SAMPLES namespace, go through tutorials, etc - see https://download.intersystems.com/
For understanding routines in general, I'd recommend this part of the documentation.
Looking at the docs and it says "Handles prompting for chui applications."
What is CHUI?
"Character-based user interface"
Oh, I call it a terminal! :)
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:
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
}
Yes, thank you, I have started doing that.
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...