第二十章 Caché 命令大全 QUIT 命令

第二十章 Caché 命令大全 QUIT 命令

终止循环结构或例程的执行。

重点

  1. 如果QUIT命令不接受其他任何参数,则后置条件和同一行中紧随其后的下一个命令之间必须有两个或多个空格。
  2. 如果IF代码块未嵌套在循环结构内,则QUIT终止当前例程。
  3. 如果IF代码块嵌套在循环结构(例如FOR代码块)中,则QUIT退出循环结构块并继续执行循环结构代码块后面的命令
  4. Caché在每个例程的末尾执行一个隐式QUIT,但是可以显式地包含它以提高程序的可读性。

大纲

QUIT:pc expression
Q:pc expression

QUIT n
Q n

参数

pc - 可选-后置条件表达式。
expression - 可选-返回到调用例程的值;有效表达式。
n - 仅限终端提示:要清除的节目级别数;解析为正整数的表达式。

描述

QUIT命令在两个不同的上下文中使用:

  • 在程序代码中退出
  • 在终端提示下退出

在程序代码中

QUIT命令终止当前上下文的执行,退出到包含的上下文。在例程中调用时,Quit将返回调用例程,如果没有调用例程,则终止该程序。当从FORDO WHILEWHILE控制流结构、TRYCATCH块或传统DO结构内调用时,QUIT会脱离该结构并继续执行该结构之外的下一个命令。

类似的RETURN命令可在任何点终止例程的执行,包括从FORDO WHILEWHILE循环或嵌套循环结构、TRYCATCH块或过时的DO结构中。Return始终退出当前例程,如果没有调用例程,则返回调用例程或终止程序。

QUIT命令有两种形式:

  • 无参数
  • 有参数

后置条件不被视为参数。$QUIT特殊变量指示从当前上下文退出是否需要带参数的QUIT命令。为此提供了两个错误代码:M16“不允许带参数退出”和M17“带参数需要退出”。

无参数QUIT

不带参数的QUIT从当前上下文中退出而不返回值。它用于终止以DOXECUTE命令启动的进程的执行级别,或退出FORDO WHILEWHILE控制流循环。

如果从终端提示中发出了DOXECUTE或(未嵌套的)控制流循环命令,则QUIT将控制权返回给终端。如果在QUIT之前终止的操作包含任何new命令,QUIT会自动终止受影响的变量并将其恢复为原始值。

带参数QUIT

Quit 表达式终止用户定义的函数或对象方法,并返回指定表达式的结果值。带有参数的QUIT不能用于从FORDO WHILEWHILE命令循环中退出例程。带参数的QUIT也不能用于从TRY块或CATCH块中退出。

如果在子例程中调用了带参数的QUIT,则会发生以下情况之一:

  • 如果在子例程(而不是函数)中调用带参数的QUIT,则将对QUIT参数进行求值(可能会产生副作用或引发错误),并且将丢弃参数结果。执行返回到子例程的调用者。
  • 如果该子例程由DO命令调用并且在该DO参数的范围内,则QUIT命令将计算其参数,但不会返回该参数。例如,DO调用的以Quit 4/0结尾的子例程会生成<Divide>错误。如果子例程由带参数的QUIT终止的DO调用子例程,并且子例程由$ETRAP终止,则会发生相同的行为。

在终端提示下

在终端提示下发出QUIT会从程序堆栈中清除实体。

  • QUIT n从程序堆栈中清除指定数量的级别。可以使用$ STACK特殊变量来确定程序堆栈上的当前级别数。

可以将n指定为文字,变量或算术表达式。如果n大于当前级别数,则从程序堆栈中清除所有级别,并且不会发出错误。n的小数被截断为其整数值。如果n解析为负的非零整数,则QUIT会从程序堆栈中清除所有级别。如果n解析为0(零),则系统生成<COMMAND>错误。

  • QUIT从程序堆栈中清除所有级别。

$ STACK特殊变量包含调用堆栈上当前上下文帧的数量。此数字也显示在终端提示中。

下面的示例使用带有整数参数的QUIT从程序堆栈中清除指定数量的级别,然后使用无参数QUIT清除所有剩余级别:

USER 5f0>QUIT 1
 
USER 4d0>QUIT 2
 
USER 2d0>QUIT

USER>

参数

pc

可选的后置条件表达式。如果后置条件表达式为true(计算为非零数值),则Caché执行命令。如果后置条件表达式为假(评估为零),则Caché不执行命令。如果QUIT命令不接受其他任何参数,则后置条件和同一行中紧随其后的下一个命令之间必须有两个或多个空格。

expression

任何有效的ObjectScript表达式。它只能在用户定义的函数中使用,以将评估结果返回给调用例程。

示例

以下两个示例对比了从控制流结构中发出时的QUITRETURN行为。QUIT退出FOR循环,继续MySubroutine的其余部分,然后返回MyRoutineRETURN退出MySubroutine,返回MyRoutine

/// d ##class(PHA.TEST.Command).TestQUIT()
ClassMethod TestQUIT()
{
MyMain
	WRITE "在主要程序中",!
	DO MySubroutine
	WRITE "返回主程序",!
	QUIT
MySubroutine
	WRITE "在MySubroutine",!
	FOR i=1:1:5 {
		WRITE "FOR loop:",i,!
		IF i=3 QUIT
		WRITE "  loop again",!
	}
	WRITE "用QUIT显示MySubroutine行",!
	QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestQUIT()
在主要程序中
在MySubroutine
FOR loop:1
  loop again
FOR loop:2
  loop again
FOR loop:3
用QUIT显示MySubroutine行
返回主程序
/// d ##class(PHA.TEST.Command).TestQUIT2()
ClassMethod TestQUIT2()
{
MyMain
	WRITE "在主要程序中",!
	DO MySubroutine
	WRITE "返回主程序",!
	QUIT
MySubroutine
	WRITE "在MySubroutine",!
	FOR i=1:1:5 {
	WRITE "FOR loop:",i,!
		IF i=3 RETURN
		WRITE "  loop again",!
	}
	WRITE "MySubroutine行未与RETURN一起显示",!
	QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestQUIT2()
在主要程序中
在MySubroutine
FOR loop:1
  loop again
FOR loop:2
  loop again
FOR loop:3
返回主程序

在下面的示例中,第一个QUIT命令的执行由后置条件(:x> 46)控制。如果随机生成的数字大于46,则Caché不执行Cube过程;第一个QUIT采用后置条件,将字符串作为num返回到调用例程。如果随机生成的数字小于或等于46,则第二个QUIT返回num的表达式x * x * x的结果。

/// d ##class(PHA.TEST.Command).TestQUITCube()
ClassMethod TestQUITCube()
{
Main
	SET x = $RANDOM(99)
	WRITE "Number is: ",x,!
	SET num=$$Cube(x)
	WRITE "Cube is: ",num
	QUIT
Cube(x) QUIT:x>46 "一个六位数的数字."
	WRITE "计算cube",!
	QUIT x*x*x
}

DHC-APP>d ##class(PHA.TEST.Command).TestQUITCube()
Number is: 23
计算cube
Cube is: 12167
DHC-APP>d ##class(PHA.TEST.Command).TestQUITCube()
Number is: 55
Cube is: 一个六位数的数字.

以下两个示例将QUITRETURN行为与TRYCATCH进行了对比。TRY块尝试除以零的操作,调用CATCH块。该CATCH块包含一个嵌套的TRY块,该块由QUITRETURN退出。

QUIT将嵌套的TRY块退出到封闭块,并继续执行CATCH块的其余部分。完成CATCH块后,它将在TRY / CATCH结构之外执行fall-through行:

/// d ##class(PHA.TEST.Command).TestQUITTry()
ClassMethod TestQUITTry()
{
	TRY {
		WRITE "在TRY块中",!
		SET x = 5/0
		WRITE "此行永远不会显示"
	}
	CATCH exp1 {
		WRITE "在CATCH块中",!
		WRITE "Error Name: ",$ZCVT(exp1.Name,"O","HTML"),!
		TRY {
			WRITE "在嵌套的TRY块中",!
			QUIT
		}
		CATCH exp2 {
			WRITE "在嵌套的CATCH块中",!
			WRITE "Error Name: ",$ZCVT(exp1.Name,"O","HTML"),!
		}
		WRITE "QUIT显示此外部CATCH块行",!
	}
	WRITE "在程序结束时fall-through"
}
DHC-APP>d ##class(PHA.TEST.Command).TestQUITTry()
在TRY块中
在CATCH块中
Error Name: &lt;DIVIDE&gt;
在嵌套的TRY块中
QUIT显示此外部CATCH块行
在程序结束时fall-through

RETURN退出例程。因此,它退出嵌套的TRY块和所有封闭的块,并且不执行TRY / CATCH结构外部的fall-through行:

/// d ##class(PHA.TEST.Command).TestQUITRet()
ClassMethod TestQUITRet()
{
	TRY {
		WRITE "在TRY块中",!
		SET x = 5/0
		WRITE "此行永远不会显示"
	}
	CATCH exp1 {
		WRITE "在CATCH块中",!
		WRITE "Error Name: ",$ZCVT(exp1.Name,"O","HTML"),!
		TRY {
			WRITE "在嵌套的TRY块中",!
			RETURN
		}
		CATCH exp2 {
			WRITE "在嵌套的CATCH块中",!
			WRITE "Error Name: ",$ZCVT(exp1.Name,"O","HTML"),!
		}
		WRITE "RETURN不显示此外部CATCH块行",!
	}
	WRITE "在程序结束时fall-through"
}
DHC-APP>d ##class(PHA.TEST.Command).TestQUITRet()
在TRY块中
在CATCH块中
Error Name: &lt;DIVIDE&gt;
在嵌套的TRY块中

在此示例中,QUIT命令的参数是一个对象方法。 Caché终止方法的执行,并将控制权返回给调用例程。

QUIT inv.TotalNum()

注意

QUIT恢复变量

如果终止的进程在QUIT之前包含NEW命令,则QUIT会自动杀死受影响的变量并将其恢复为原始值。

QUIT和控制流结构

QUIT可用于中断FOR循环,DO WHILE循环或WHILE循环。执行将继续执行循环结构末尾的命令。如果这些循环结构是嵌套的,则QUIT会从调用它的内部循环中跳出到下一个封闭的外部循环。

如果在IF代码块(或ELSEIF代码块或ELSE代码块)中遇到QUIT命令,则QUIT的行为就像常规的QUIT命令一样,好像该代码块不存在:

  • 如果IF代码块嵌套在循环结构(例如FOR代码块)中,则QUIT退出循环结构块并继续执行循环结构代码块后面的命令。
  • 如果IF代码块未嵌套在循环结构内,则QUIT终止当前例程。

QUIT可用于退出旧语法的DO结构(无参数DO,后跟代码行,每行代码前加一个句点)。使用无参数DO结构代码块后面的命令继续执行。这种无参数的DO语法被认为已过时,不应用于新的编码。

与不确定的FOR循环一起使用

不确定的FOR循环是没有参数的FOR;除非打破它,否则它将无限循环。要控制不确定的FOR循环,必须在循环结构中包括带有后置条件的QUIT或调用QUITIF命令。IF中的QUIT终止了封闭的FOR循环。如果没有这些QUIT之一,则该循环将是无限循环,并且将无限执行。

在以下示例中,使用带后置条件的QUIT退出不确定的FOR循环。只要用户输入一些值以响应 "Text ="提示,循环就会继续执行。仅当用户输入空字符串(即,只需按ReturnEnter)时,QUIT才会执行,并且循环终止。

/// d ##class(PHA.TEST.Command).TestQUITEnter()
ClassMethod TestQUITEnter()
{
Main
	FOR   {
		READ !,"文本 =",var1 
		QUIT:var1=""  DO Subr1
	}
Subr1
	WRITE "感谢您的输入", !
	QUIT
}
DHC-APP>d ##class(PHA.TEST.Command).TestQUITEnter()
 
文本 =1感谢您的输入
 
文本 =2感谢您的输入
 
文本 =3感谢您的输入
 
文本 =感谢您的输入

该命令在QUIT命令上的后置条件与同一行上的后续DO命令之间至少需要两个空格。这是因为Caché将后置条件视为命令修饰符,而不是参数。

隐式QUIT

在以下情况下,不需要QUIT命令,因为Caché自动发出隐式QUIT,以防止执行“陷入”单独的代码单元。

  • Caché在例程结束时执行隐式QUIT
  • 当Caché遇到带有参数的标签时,将执行隐式QUIT。即使括号中包含零个参数,带有参数的标签也被定义为带有括号的一个。所有过程均以带有参数的标签开头(即使未定义任何参数)。许多子例程和函数还带有带有参数的标签。

当然,在任何这些情况下,都可以编写显式QUIT

DO的行为

当在由DO命令调用的子例程中遇到时,QUIT终止该子例程,并将控制权返回给DO命令之后的命令。

XECUTE的行为

当遇到正在执行的代码行时,QUIT终止该行的执行,并将控制权返回给XECUTE命令之后的命令。不允许有参数。

与用户定义功能的行为

在用户定义的函数中遇到QUIT时,它将终止该函数并返回从指定表达式得出的值。表达式参数是必需的。

在使用中,用户定义的函数类似于带有参数传递的DO命令。但是,它们与此类DO命令的不同之处在于它们直接返回表达式的值,而不是通过变量返回。要调用用户定义的函数,请使用以下格式:

$$name(parameters)

其中,name是函数的名称。可以将其指定为label,^ routine或label ^ routine

parameters是要传递给函数的参数的逗号分隔列表。与功能关联的标签还必须具有参数列表。被调用函数上的参数列表称为实际参数列表。功能标签上的参数列表称为形式参数列表。

在下面的示例中,FOR循环使用READ命令首先获取要平方的数字并将其存储在num变量中。(请注意,无参数FOR和后置条件QUIT之后的两个空格。)然后,它使用WRITE命令调用Square标准函数,并将num指定为函数参数。

该函数的唯一代码是QUIT命令,后跟一个表达式以计算平方。当遇到QUIT命令时,Caché会对表达式求值,终止函数,并将结果值直接返回到WRITE命令。 num的值保持不变。

/// d ##class(PHA.TEST.Command).TestQUITCal()
ClassMethod TestQUITCal()
{
Test WRITE "计算一个数字的平方",!
	FOR   {
		READ !,"Number:",num QUIT:num="" 
		WRITE !,$$Square(num),!
		QUIT
	}
Square(val) 
	QUIT val*val
}
DHC-APP>d ##class(PHA.TEST.Command).TestQUITCal()
计算一个数字的平方
 
Number:3
9

使用QUIT提高程序可读性

Caché在每个例程的末尾执行一个隐式QUIT,但是可以显式地包含它以提高程序的可读性。

猜你喜欢

转载自blog.csdn.net/yaoxin521123/article/details/107456603
今日推荐