Written by

Senior Startups and Community Programs Manager at InterSystems Corporation
Discussion Evgeny Shvarov · Feb 14

Quit or Return?

Hi developers!

I'm testing vibecoding with ObjectScript and my silicon friend created a code-block that got me thinking "what's wrong"?

Here is the piece of code:

for i=0:1:(json.%Size()-1) {

set p = json.%Get(i)

if (p="value1")!(p="value2") {

quit 1
}

 

AI wanted to quit from a method with a return value. Good intention, but bad use of the command.

And ObjectScript compiler compiles this code with no error(?) (syntax linter in VSCode says it's a syntax, kudos @Brett Saviano ).

But in action, it produces <COMMAND>, of course.

Wanted to share with you as this is a good case where return command is better than quit, so if we change the snippet to use return, everything will be fine:

for i=0:1:(json.%Size()-1) {

set p = json.%Get(i)

if (p="value1")!(p="value2") {

return 1
}

So I told my AI-companion to go with return further while returning method results.

Do you use return? Or quit? 

Do you use return or quit?
VoteShow results

Comments

DC AI Bot · Feb 14 Bot

QUIT and RETURN are both commands used to terminate execution in ObjectScript code. However, they behave differently depending on their context:

  1. QUIT Command:

    • It exits only the current structure and continues execution outside of it. For example, when used within a FOR or WHILE loop, QUIT will exit the loop and continue with the code after the block.
    • When issued outside of a structure or within an IF, ELSEIF, or ELSE block, QUIT exits the current routine and returns to the caller with or without arguments. With an argument, it provides a return value [1].
  2. RETURN Command:

    • It directly exits the entire routine or method, regardless of whether it's within a loop or a block structure, and returns control to the calling context or ends the program.
    • RETURN is particularly useful for readability when you intend to terminate execution and return a value from methods or nested structures [1][2].

In your example:

0
Evgeny Shvarov  Feb 16 to DC AI Bot
  • The compiler does not return an error for the QUIT usage as it exits the routine correctly.

BTW, DC AI is wrong here - quit with argument within for loop is not correct.

0
Julius Kavay · Feb 14

Maybe you send your new companion back to the school or maybe better, you look for a real companion with brain.
A docu for return is here By the way, did you know, AI is the shortcut for... no, no, it means Absent Intelligence!

0
Evgeny Shvarov  Feb 14 to Julius Kavay

Ha-ha, @Julius Kavay ! I still have hopes with my one :) He/she/it is trying and sometimes is quite helpful indeed )

0
Ali Nasser · Feb 14

Whether I use Quit or Return depends on what I'm trying to do. If the aim is to just terminate a method and/or return a value then I go for Return. But if I'm within a code block that I'm trying to escape out of, then I use Quit (as long as that block isn't an if/else statement then I need to resort to trickery to get out of it without ending the routine)

Quit also has a neat feature when used to debug from the terminal in that it allows you to go back up the call stack by giving it a numeric argument.

0
Evgeny Shvarov  Feb 14 to Ali Nasser

Thanks @Ali Nasser ! Very interesting about quit's debugging stack level option. Could you share some examples?
 

0
Pietro Di Leo  Feb 16 to Evgeny Shvarov

I agree with Ali and do the same. Quit is to escape out of a code block, while return is at the end of the code to return a value. Moreover, I use a lot the Try-Catch statement and Quit is not valid inside the Try block to return values but only inside other statements to escape out of them. 

0
Ali Nasser  Feb 17 to Evgeny Shvarov

Sure, let's create a class like this:

Class Sample.DC
{
ClassMethod RunMe() As %Status
{
        Set x = 1
        do ..NestedOne()
}
ClassMethod NestedOne() As %Status
{
        Set y = 2
        do ..NestedTwo()
}
ClassMethod NestedTwo() As %Status
{
        set z = 3
        set err = z / 0
}
}

If you go to your terminal and do ##class(Sample.DC).RunMe() then you will get this error:

<DIVIDE>NestedTwo+2^Sample.DC.1

Your terminal will also show this prompt:

USER 4d1>

You can examine the variables in the NestedTwo classmethod to determine what went wrong by printing variables in that stack frame, for example: write z. However, you can't print out the values of y and x because they are in a parent stack frame. Instead, you use quit <number> to go back up to the NestedOne and RunMe frames where you can print out the values of y and x. For example, quit 1 will go to NestedOne where the var y is defined.

0
Evgeny Shvarov  Feb 17 to Ali Nasser

Thanks @Ali Nasser! Very interesting, I'll take a look - and "Yes", I still debug with B "L" sometimes. 

0
Robert Barbiaux · Feb 14

Hi Evgeny,
In ISOS, the "quit" command is inherited from MUMPS ("Q[UIT]") and has two forms (see the documentation for details) : 

  • with arguments : terminates a method, function or routine, returning it's arguments as value
  • without arguments : exits the current context (e.g. for, while, ...)

The "return" command was introduced by InterSystems, I think in Caché 2016.2  (@all please, correct me if I'm wrong).  It was added to avoid confusion, making ISOS clearer and also more aligned with 'modern' programming conventions.
"return" is equivalent to "quit" with argument, thus is has only one form and one, clear meaning : returning a value.
When the code intent is to return a value, nowadays I favor using "return".

p.s. IMHO, generative AIs, while useful in some contexts, are nor artificial, because they are trained with human sourced corpus, nor intelligent, because they are not able of any real creativity and are not doing any reasoning (even if they can mimic both rather well) 😇

0
Evgeny Shvarov  Feb 14 to Robert Barbiaux

Thank you, @Robert Barbiaux ! Love the historic review! It's great to see you find the utility for return command.

p.s. IMHO, generative AIs, while useful in some contexts, are nor artificial, because they are trained with human sourced corpus, nor intelligent, because they are not able of any real creativity and are not doing any reasoning (even if they can mimic both rather well) 😇

Agree! In fact humans can mimic the reasoning perfectly too :)

0
Enrico Parisi  Feb 16 to Robert Barbiaux

@Robert Barbiaux 


"return" is equivalent to "quit" with argument, thus is has only one form and one, clear meaning : returning a value.

Both Quit and Return can be used with or without an argument (returned value),  see the documentation for details.

RETURN and QUIT differ when issued from within a FOR, DO WHILE, or WHILE flow-of-control structure, or a TRY or CATCH block.

You can use RETURN to terminate execution of a routine at any point, including from within a FOR, DO WHILE, or WHILE loop or nested loop structure.

In the context of the main post/question example Quit and Return can be used and there is no difference, the behave the same way.

Personally I never use Return simply because I don't consider a good practice to exit a method in the middle of a FOR, DO WHILE, or WHILE flow-of-control structure, or a TRY or CATCH block, to me it's like, or worst, than using a GOTO command. In my opinion good code should have one exit point at the end of a method, not a random number of exit point in the middle of nested structure inside the method, therefore the newly introduced Return command is of no use for me. Again, this is my very personal opinion.

0
Evgeny Shvarov  Feb 16 to Enrico Parisi

Thanks @Enrico Parisi ! I'm not that strict about return inside FOR and DO WHILE, as I see it as the clearest difference over the quit.

0
Herman Slagman  Feb 16 to Robert Barbiaux

Return was implemented in 2012 in the Cache 2013 FieldTest.
I know because I proposed it to ISC in my yearly wishlist to Joe DeSantis and Robert Nagle.
The documentation in that FT was literally the text of my proposal ;-)

0
Herman Slagman  Feb 16 to Evgeny Shvarov

I found the Quit ambiguous; it's not very clear what it does.
But especially within nested for-loops, once you found what you were looking for, you needed several Quits (one for each level) and a flag such as 'Found'.
Return is unambiguous and does exactly what it says.
 

0
Dmitrii Baranov · Feb 15

Is your account hacked or what. This is the second or third month in a row that you've been asking strange questions (almost) every day.

* * *

Essentially, I would recommend always using Return to exit a function (as in all other programming languages) and Quit to exit a loop.

0
Evgeny Shvarov  Feb 16 to Dmitrii Baranov

Thank you, @Dmitrii Baranov !

Just want to assure you, the account is not hacked, yet ;) 

Yes, it may be a strange question (though it is a discussion), but if we put a poll (maybe not a bad idea too), I bet the majority of developers don't use the return command at all. And I remember times when it was introduced to a language (not that long ago). 

That's why AI is not using it in code generation, as it relies on the common practices in the publicly available source codes.

Essentially, I would recommend always using Return to exit a function (as in all other programming languages) and Quit to exit a loop.

Yes, makes sense, thank you. 

0
Robbie Luman · Feb 17

It's definitely situational for me. I generally try to avoid using Quit for situations where I am trying to exit the method or program entirely, and opt for Return in these cases (a habit which took a lot of retraining since I'd been used to using quit for everything coming from a heavy MUMPS-coded software base in the past). I really only use Quit these days for terminating a loop when needed, but it's still a common enough usage for me. 
In short, these days I use these rules:

  • Return - Exit program/method (with or without return value)
  • Quit - Loop terminator
0
Eduard Lebedyuk · Feb 17

I use return where it's important that we exit (middle of the loop, etc) immediately, in all other cases I use quit.

0
Steven Hobbs  Feb 17 to Evgeny Shvarov

As mentioned above, ObjectScript was originally based on ANSI MUMPS.  However, that ANSI standard has been retired but I believe there still exists an ISO M language standard which is identical to the ANSI M[UMPS} standard.  ObjectScript still supports the ancient MUMPS/M standard but InterSystems no longer documents many of the legacy features of MUMPS/M.

There is no warning for a QUIT with expression statement in a FOR loop because it is possible that a QUIT expr could be legal in a FOR loop and that legality/illegality cannot not be detected until run-time.

Here is a messy example containing both legacy M and modern ObjectScript.  It contains a quit x+3 statement that is legal when first encountered and illegal when encountered the second time.

InterSystems supports ugly legacy M features so customers do not need to rewrite ancient code.  New code should not look like this ugly example as avoiding certain legacy features is strongly recommended.

USER>zp
foo(a,b) 
         for i=1:1:10 {
         set x=$$foo2(a)  zw x
         goto foo3
foo2(y)  
foo3     set z=a
         zw a,x,y,z
         zw "about to quit y+3"
         quit x+3
         }

USER>zw $$foo(5,9)                    
a=5
x=14
y=5
z=5
"about to quit y+3"
x=17
a=5
x=17
z=5
"about to quit y+3"

 quit x+3
   ^
<COMMAND>foo3+3^foo
USER 6f2>

Note that <COMMAND> was signaled 3 lines after label foo3 and then we interactively get a prompt from the debugger.

BTW: Evgeny might ask strange questions but the properties of legacy M/MUMPS can be much weirder.
 

0
Steven Hobbs  Feb 17 to Steven Hobbs

The initial value of x=14 in the above ugly example happened because I ran it 3 times while I has debugging and modifying it.  As the comment says, I originally did quit y+3 but I had to change it to quit x+3 because the second execution of the quit statement got an <UNDEFINED> *y signal before it got to the <COMMAND> signal.

0
Evgeny Shvarov  Feb 19 to Steven Hobbs

"Oh my god!"  Thanks for sharing @Steven Hobbs !

And thanks god we don't have a need to use goto anymore, as it is quite a legal way to shoot yourself in both feet.

0