第十八章 Caché 命令大全 NEW 命令
创建空的局部变量环境。
重点
- 在程序中也就是类程序中,默认都是私有变量不能
NEW
。 - 在mac或生命过程块为true时,可以使用
NEW
命令。 n (a,b,c)
这种代表除了a,b,c
都初始化- 可以new的变量,不可以new的变量
- 尝试发出超过31个级别的独占NEW或无参数
NEW
会导致<MAXSCOPE>
错误。
大纲
NEW:pc newargument,...
N:pc newargument,...
newargument可以是:
variable,...
or
(variable,...)
参数
- pc 可选的后置表达式
- variable 可选-要添加到现有局部变量环境的变量的名称。
NEW
对现有局部变量的影响取决于变量是括在括号中(排除NEW
)还是没有括在括号中(包含NEW
)。变量必须是有效的局部变量名,但不必是已定义的变量;指定未定义的变量既不会发出错误,也不会定义该变量。
描述
NEW命令有两种形式:
- 无参数
- 有参数
不带参数的NEW
为被调用子例程或用户定义函数创建一个空的局部变量环境。现有的本地变量值在此NEW
的本地环境中不可用。它们可以通过返回到以前的当地环境来恢复。
使用参数执行的new
操作取决于使用的参数形式。
new
变量(包括new
)保留现有的局部变量环境,并向其中添加指定的变量。如果任何指定的局部变量与现有局部变量同名,则在当前环境中无法再访问该命名变量的旧值。new
(变量)(独占new
)替换本地变量环境中除指定变量之外的所有现有变量。
NEW的限制
NEW
命令(包含或排除)不能用于以下内容:
- Globals 全局变量
- Process-Private Globals 私有进程全局变量
- Local variable subscripts 局部变量下标
- Private variables 私有变量
- 特殊变量,
$ESTACK
、$ETRAP
、$NAMESPACE
和$ROLES
除外
尝试在这些上下文中的任何上下文中使用NEW都会导致<SYNTAX>
错误。
参数
pc
可选的后置条件表达式。如果后置条件表达式为TRUE(计算结果为非零数值),则Caché执行NEW
命令。如果后置条件表达式为假(计算结果为零),则Caché不执行该命令。
variable
单个变量的名称或逗号分隔的变量名列表。虽然可以新建整个数组(即不带下标的数组名称),但只能指定无下标的变量名。可以指定未定义的变量名称,也可以重用现有局部变量的名称。对于包含式NEW
,当指定现有局部变量时,Caché会在本地环境中重新初始化该变量,但会将其当前值保存在程序堆栈上,并在子例程或函数终止后恢复该变量。
当变量名或以逗号分隔的变量名列表括在括号中(不包括new
)时,Caché执行相反的操作。也就是说,所有局部变量都被重新初始化,但指定的变量名除外,它们保留了以前的值。Caché保存程序堆栈中所有变量的当前值,并在子例程或函数终止后恢复它们。
示例
下面的示例说明了一个包含性NEW
,它保留现有的局部变量a
、b
和c
,并添加变量d
和e
(在本例中,覆盖先前的d值)。
Main1
SET a=7,b=8,c=9,d=10
WRITE !,"Before NEW:",!,"a=",a,!,"b=",b,!,"c=",c,!,"d=",d
DO Sub1
WRITE !,"返回到以前的上下文:"
WRITE !,"a=",a,!,"b=",b,!,"c=",c,!,"d=",d
QUIT
Sub1
NEW d,e
SET d="big number"
WRITE !,"After NEW:",!,"a=",a,!,"b=",b,!,"c=",c,!,"d=",d
QUIT
DHC-APP>d Main1^PHA.TEST.Command
Before NEW:
a=7
b=8
c=9
d=10
After NEW:
a=7
b=8
c=9
d=big number
Returned to prior context:
a=7
b=8
c=9
d=10
下面的示例说明了独占NEW
,它删除除指定变量a
和c
之外的所有现有局部变量。
Sub2
SET a=7,b=8,c=9,d=10
NEW (a,c)
WRITE
DHC-APP>d Sub2^PHA.TEST.Command
a=7
c=9
注意
使用NEW
功能的位置
New
允许将当前进程的局部变量环境与子例程、用户定义函数或XECUTE
字符串所做的更改隔离。NEW
最常在do
命令调用的子例程中使用。
NEW
命令的基本目的是重新定义被调用子例程或用户定义函数内的局部变量环境。 未传递参数而被调用的子例程或用户定义函数从调用例程继承其局部变量环境。要重新定义子例程或函数的此环境,可以将new
用于所有局部变量(无参数new
)、命名局部变量(包含new
)或除命名变量之外的所有局部变量(排除new
)。
在过程(类程序中)中,变量可以是私有的,也可以是公共的:
- 默认情况下,局部变量是该过程的私有变量。过程块使用私有变量,该私有变量不与过程块外部具有相同名称的变量交互。不能对私有变量执行
NEW
;尝试对过程块内的私有变量执行包含式或排他性NEW
会导<SYNTAX>
错误。 - 声明过程时,可以将局部变量显式列为公共变量。可以对过程块内的公共变量执行
NEW
。此NEW
功能仅影响该过程中的变量值。可以在过程中重复NEW建公共变量。
new
和kill
NEW
创建的变量不需要显式且相应的KILL
命令。当被调用的子例程或用户定义的函数终止时,Caché会对该子例程或函数中由NEW
命令初始化的每个变量执行隐式KILL
。
Inclusive NEW
包含NEW
Inclusiv NEW
-NEW
变量-保留现有的局部变量环境,并将指定的变量添加到该环境中。如果现有变量已命名,则“new
”变量将替换现有变量,该变量将保存在堆栈中,然后在子例程或函数终止时恢复。
Inclusive NEW
不限制可以指定为逗号分隔列表的变量数量。Inclusive NEW
也不限制本地变量环境级别的数量(发出NEW
的次数)。
在下面的示例中,假设调用例程(Main
)的局部变量环境由变量a
、b
和c
组成。当DO
调用Subr1
时,new
命令将Subr1
的局部变量环境重新定义为新变量c
并添加变量d
。在new
之后,子例程的环境由现有变量a
和b
加上新变量c
和d
组成。变量a
和b
被继承并保留其现有值。新变量c
和d
被创建为未定义。因为c
是现有局部变量的名称,所以Caché将现有值保存在堆栈上,并在Subr1
退出时恢复它。请注意,Subr1
中的第一个set
命令引用a
和b
为d
赋值。请注意,此上下文中的变量c
未定义。
Main3
SET a=2,b=4,c=6
WRITE !,"c in Main before DO: ",c
DO Subr1(a,b,c)
WRITE !,"c in Main after DO: ",c
QUIT
Subr1(a,b,c)
NEW c,d
IF $DATA(c) {WRITE !,"c=",c}
ELSE {WRITE !,"c in Subr1 is undefined"}
SET d=a*b
SET c=d*2
WRITE !,"c in Subr1: ",c
QUIT
执行此代码时,将生成以下结果:
DHC-APP>d Main3^PHA.TEST.Command
c in Main before DO: 6
c in Subr1 is undefined
c in Subr1: 16
c in Main after DO: 6
无论是按值传递参数(如上例所示),还是按引用传递参数,结果都是相同的:
Main4
SET a=2,b=4,c=6
WRITE !,"c in Main before DO: ",c
DO Subr4(.a,.b,.c)
WRITE !,"c in Main after DO: ",c
QUIT
Subr4(&a,&b,&c)
NEW c,d
IF $DATA(c) {WRITE !,"c=",c}
ELSE {WRITE !,"c in Subr1 is undefined"}
SET d=a*b
SET c=d*2
WRITE !,"c in Subr1: ",c
QUIT
DHC-APP>d Main4^PHA.TEST.Command
c in Main before DO: 6
c in Subr1 is undefined
c in Subr1: 16
c in Main after DO: 6
请注意,变量c
被传递给Subr1
,然后立即使用new
重新定义。在这种情况下,不需要传递变量c
;无论是否传递c
,程序结果都是相同的。如果新建任何在子例程的形参列表中指定的变量,则会将它们呈现为未定义,并使其传递的值不可访问。
Exclusive NEW
独占NEW
exclusive new-new(var1,var2)
-替换除指定变量之外的整个现有局部变量环境。如果现有变量已命名,则会保留该变量,并可在新环境中引用该变量。但是,当函数或子例程终止时,对此类变量所做的任何更改都会反映在现有变量中。
独占NEW
最多可以指定255个变量作为逗号分隔的列表。 超过此数字会导致Caché发出<SYNTAX>
错误。
XCLUSIVE NEW (NEW (x,y,z))
临时从当前作用域中删除局部变量。这可能会影响Caché对象创建的局部变量。例如,Caché维护%objcn
,它是用于Caché对象查询的游标指针。将其从当前作用域中删除可能会导致与其他内部结构发生冲突。因此,不要在任何可能影响系统结构的上下文中使用独占NEW
。
尝试发出超过31个级别的独占NEW或无参数NEW
会导致<MAXSCOPE>
错误。
在FOR
代码块中使用EXCLUSIVE NEW
时,必须将FOR COUNT
变量指定为排除变量。
在下面的示例中,假设调用例程(Start
)的局部变量环境由变量a
、b
和c
组成。当DO
调用Subr1
时,NEW
命令会重新定义Subr1
的局部变量环境,以排除除c
和d
之外的所有变量。
在new
之后,子例程的环境仅由new
变量c
和d
组成。NEW
变量c
从调用例程的环境中保留,并保持其现有值。创建未定义的新变量d
。
Subr1
中的第一个set
命令引用c
为d
赋值。第二个set
命令将新值(24)分配给c
。当子例程退出时,c
将在调用例程的环境中拥有这个更新值(而不是原始值6)。
Start SET a=2,b=4,c=6
DO Subr1
WRITE !,"c in Start: ",c
QUIT
Subr1 NEW (c,d)
SET d=c+c
SET c=d*2
WRITE !,"c in Subr1: ",c
QUIT
```java
执行此代码时,将生成以下结果:
c in Subr1: 24
c in Start: 24
# 无参`NEW`
无参数`NEW`为被调用子例程或用户定义函数提供了一个空的局部变量环境。现有的局部变量环境(在调用例程中)被保存,然后在子例程或函数终止时恢复。当子例程或函数终止时,在NEW之后创建的任何变量都会被删除。
**如果命令在同一行上跟在`new`之后,请确保将`new`命令与它后面的命令分隔(至少)两个空格。**
**不应在`for`循环体内或在可能影响Caché对象的上下文中使用无参数`new`。**
尝试发出超过31个级别的独占NEW或无参数NEW会导致`<MAXSCOPE>`错误。
# 特殊变量:`$ESTACK、$ETRAP、$NAMESPACE`和`$ROLES`
不能对大多数特殊变量使用`NEW`;尝试这样做会导致`<SYNTAX>`错误。有四个例外:`ESTACK、$ETRAP、$NAMESPACE`和`$ROLES`。
- `$ETRAP`:当发出命令`new $ETRAP`时Caché会为错误捕获创建一个新的上下文。然后,可以使用所需的错误捕获命令在此新上下文中设置`$ETRAP`。保留前一个上下文中的`$ETRAP`值。如果在没有首先发出`NEW $ETRAP`命令的情况下设置`$ETRAP`,则Caché会在所有上下文中将`$ETRAP`设置为此值。因此,建议在设置`$ETRAP`特殊变量之前始终使用`NEW`变量。
- `$NAMESPACE`:当发出命令`new $NAMESPAC`E时,Caché会创建一个新的名称空间上下文。在此上下文中,可以更改名称空间。当退出此上下文时(例如,使用`QUIT`),Cché将恢复到以前的名称空间。
# 带参数传递的子例程
如果调用带有参数传递的子例程,则Caché会为该子例程的形参列表中指定的每个变量发出一个隐式`new`命令。然后,它将`DO`命令的实际参数列表中传递的值(按值或按引用)赋给这些变量。
如果`do`命令使用按值传递的参数,并且如果正式列表命名了任何现有的局部变量,则Caché会将现有变量及其值放入堆栈。当子例程终止(显式或隐式退出)时,Caché会为每个正式列表变量发出隐式`kill`命令,以便从堆栈恢复它们。