第五章 Caché 運(yùn)算符和表達(dá)式(一)
Caché支持許多不同的運(yùn)算符,這些運(yùn)算符執(zhí)行各種操作驴一,包括數(shù)學(xué)操作驯嘱、邏輯比較等。運(yùn)算符作用于表達(dá)式陕靠,表達(dá)式是最終計(jì)算為某個(gè)值的變量或其他實(shí)體驳遵。
運(yùn)算符和表達(dá)式簡介
運(yùn)算符是指定要對(duì)其關(guān)聯(lián)操作數(shù)執(zhí)行的操作的符號(hào)字符谷炸。每個(gè)操作數(shù)由一個(gè)或多個(gè)表達(dá)式或表達(dá)式原子組成胸懈。一起使用時(shí)剃幌,運(yùn)算符及其關(guān)聯(lián)的操作數(shù)具有以下形式:
[操作數(shù)]運(yùn)算符操作數(shù)
有些運(yùn)算符只接受一個(gè)操作數(shù),稱為一元運(yùn)算符税肪;另一些運(yùn)算符只接受兩個(gè)操作數(shù)溉躲,稱為二元運(yùn)算符。
運(yùn)算符及其任何操作數(shù)加在一起構(gòu)成表達(dá)式寸认。這樣的表達(dá)式產(chǎn)生的結(jié)果是運(yùn)算符對(duì)操作數(shù)的影響签财。它們根據(jù)它們包含的運(yùn)算符的類型進(jìn)行分類。
- 算術(shù)表達(dá)式包含算術(shù)運(yùn)算符偏塞,對(duì)操作數(shù)進(jìn)行數(shù)值解釋唱蒸,并生成數(shù)值結(jié)果。
- 字符串表達(dá)式包含字符串運(yùn)算符灸叼,為操作數(shù)提供字符串解釋神汹,并生成字符串結(jié)果。
- 邏輯表達(dá)式包含關(guān)系運(yùn)算符和邏輯運(yùn)算符古今,對(duì)操作數(shù)進(jìn)行邏輯解釋屁魏,并生成布爾結(jié)果:
TRUE(1)
或FALSE(0)
。
運(yùn)算符符號(hào)表
ObjectScript包括以下運(yùn)算符:
操作符 | 執(zhí)行的操作 | ||||
---|---|---|---|---|---|
. |
對(duì)象屬性或方法訪問捉腥。 | ||||
() |
數(shù)組索引或函數(shù)調(diào)用參數(shù)氓拼。 | ||||
+ |
加法(二進(jìn)制)、正(一元) | ||||
– |
減法(二進(jìn)制)抵碟、負(fù)數(shù)(一元) | ||||
* |
乘法 | ||||
/ |
出發(fā) | ||||
\ |
整除 | ||||
** |
指數(shù) | ||||
# |
余數(shù) | ||||
_ |
連接符 | ||||
' |
邏輯補(bǔ)碼(NOT) | ||||
= |
測試相等性桃漾、賦值 | ||||
'= |
不相等 | ||||
> |
大于 | ||||
'> ,<=
|
不大于(小于或等于) | ||||
< |
小于 | ||||
'< 拟逮,>=
|
不小于(大于或等于) | ||||
[ |
包含 | ||||
] |
遵循 | ||||
]] |
排序后 | ||||
& 撬统,&&
|
邏輯AND(&& 是AND) |
||||
! ,` |
` | 邏輯或(` | `是或) | ||
@ |
間接 | ||||
? |
模式匹配 |
運(yùn)算符優(yōu)先
ObjectScript中的運(yùn)算符優(yōu)先級(jí)嚴(yán)格從左到右敦迄;在表達(dá)式中恋追,操作按出現(xiàn)的順序執(zhí)行凭迹。這與其他語言不同,在其他語言中苦囱,某些運(yùn)算符具有比其他運(yùn)算符更高的優(yōu)先級(jí)嗅绸。可以在表達(dá)式中使用顯式括號(hào)沿彭,以強(qiáng)制某些操作先于其他操作進(jìn)行朽砰。
WRITE "1 + 2 * 3 = ", 1 + 2 * 3,! // returns 9
WRITE "2 * 3 + 1 = ", 2 * 3 + 1,! // returns 7
WRITE "1 + (2 * 3) = ", 1 + (2 * 3),! // returns 7
WRITE "2 * (3 + 1) = ", 2 * (3 + 1),! // returns 8
1 + 2 * 3 = 9
2 * 3 + 1 = 7
1 + (2 * 3) = 7
2 * (3 + 1) = 8
一元負(fù)運(yùn)算符
CachéObjectScript使一元負(fù)運(yùn)算符優(yōu)先于二元算術(shù)運(yùn)算符尖滚。CachéObjectScript首先掃描數(shù)字表達(dá)式并執(zhí)行任何一元負(fù)操作喉刘。然后,CachéObjectScript對(duì)表達(dá)式求值并生成結(jié)果漆弄。
WRITE -123 - 3,! // returns -126
WRITE -123 + -3,! // returns -126
WRITE -(123 - 3),! // returns -120
-126
-126
-120
括號(hào)和優(yōu)先順序
可以通過使用匹配的圓括號(hào)將表達(dá)式相互嵌套來更改計(jì)算順序睦裳。圓括號(hào)將包含的表達(dá)式(算術(shù)表達(dá)式和關(guān)系表達(dá)式)分組,并控制CachéObjectScript對(duì)表達(dá)式執(zhí)行操作的順序撼唾。
SET TorF = ((4 + 7) > (6 + 6)) // False (0)
WRITE TorF
0
這里廉邑,由于括號(hào)的原因,添加了4和7倒谷,就像6和6一樣蛛蒙;這導(dǎo)致邏輯表達(dá)式11>12
,這是假的渤愁。請(qǐng)將其與以下內(nèi)容進(jìn)行比較:
SET Value = (4 + 7 > 6 + 6) // 7
WRITE Value
7
在本例中牵祟,優(yōu)先級(jí)從左到右,因此添加了4和7抖格。它們的總和11與6相比較诺苹;因?yàn)?1大于6,所以此邏輯運(yùn)算的結(jié)果是1(True)
雹拄。然后將1與6相加收奔,結(jié)果是7。
請(qǐng)注意滓玖,優(yōu)先級(jí)甚至決定了結(jié)果類型坪哄,因?yàn)榈谝粋€(gè)表達(dá)式的最終運(yùn)算結(jié)果是布爾值,而第二個(gè)表達(dá)式的最后運(yùn)算結(jié)果是數(shù)值势篡。
下面的示例顯示了多個(gè)級(jí)別的嵌套:
WRITE 1+2*3-4*5,! // returns 25
WRITE 1+(2*3)-4*5,! // returns 15
WRITE 1+(2*(3-4))*5,! // returns -5
WRITE 1+(((2*3)-4)*5),! // returns 11
25
15
-5
11
從最里面的嵌套表達(dá)式開始翩肌,逐級(jí)向前,在每個(gè)級(jí)別從左到右求值殊霞。
提示:對(duì)于除最簡單的ObjectScript表達(dá)式之外的所有表達(dá)式摧阅,最好使用完全括號(hào)括起表達(dá)式。這是為了消除對(duì)順序的任何模棱兩可的地方绷蹲,也是為了消除將來對(duì)代碼初衷的任何疑問棒卷。
例如顾孽,由于“&&
”運(yùn)算符與所有運(yùn)算符一樣具有從左到右的優(yōu)先順序,因此下面代碼片段中的最后一條語句的計(jì)算結(jié)果為0:
SET x = 3
SET y = 2
IF x && y = 2 {
WRITE "True",! }
ELSE {
WRITE "False",! }
False
這是因?yàn)榘慈缦路绞竭M(jìn)行:
- 第一個(gè)操作是檢查x是否已定義并且是否具有非零值比规。由于x等于3若厚,因此評(píng)估將繼續(xù)。
- 接下來蜒什,檢查y是否已定義并且是否具有非零值测秸。由于y等于2,因此評(píng)估將繼續(xù)灾常。
- 接下來霎冯,計(jì)算3&2的值。由于3和2都不等于0钞瀑,因此此表達(dá)式為真沈撞,計(jì)算結(jié)果為1。
- 下一個(gè)操作是將返回值與2進(jìn)行比較雕什。由于1不等于2缠俺,因此此計(jì)算返回0。
對(duì)于那些習(xí)慣了許多編程語言的人來說贷岸,這是一個(gè)意想不到的結(jié)果壹士。如果意圖是返回True(如果x定義為非零值,并且y等于2)偿警,則需要使用括號(hào):
SET x = 3
SET y = 2
IF x && (y = 2) {
WRITE "True",! }
ELSE {
WRITE "False",! }
True
函數(shù)和優(yōu)先級(jí)
某些類型的表達(dá)式(如函數(shù))可能會(huì)有副作用躏救。假設(shè)有以下邏輯表達(dá)式:
IF var1 = ($$ONE + (var2 * 5)) {
DO ^Test
}
CachéObjectScript首先計(jì)算var1
,然后計(jì)算函數(shù)$$one
户敬,然后計(jì)算var2
落剪。然后它將var2
乘以5。最后尿庐,CachéObjectScript測試加法結(jié)果是否等于var1中的值如果是忠怖,它將執(zhí)行do
命令來調(diào)用Test例程
。
作為另一個(gè)示例抄瑟,請(qǐng)考慮以下邏輯表達(dá)式:
SET var8=25,var7=23
IF var8 = 25 * (var7 < 24) {
WRITE !,"True" }
ELSE {
WRITE !,"False" }
True
Caché嚴(yán)格從左到右對(duì)表達(dá)式求值凡泣。程序員必須使用括號(hào)來建立任何優(yōu)先級(jí)。在本例中皮假,Caché首先計(jì)算var8=25
鞋拟,結(jié)果為1。然后將此1乘以括號(hào)中表達(dá)式的結(jié)果惹资。因?yàn)関ar7小于24贺纲,所以括號(hào)中的表達(dá)式的計(jì)算結(jié)果為1。因此Caché與1*1
相乘褪测,結(jié)果為1(真)猴誊。
表達(dá)式
ObjectScript表達(dá)式是一個(gè)或多個(gè)“tokens”潦刃,可以對(duì)其求值以產(chǎn)生值。最簡單的表達(dá)式只是一個(gè)文字或變量:
SET expr = 22
SET expr = "hello"
SET expr = x
可以使用數(shù)組懈叹、運(yùn)算符或眾多ObjectScript函數(shù)之一創(chuàng)建更復(fù)雜的表達(dá)式:
SET expr = +x
SET expr = x + 22
SET expr = array(1)
SET expr = ^data("x",1)
SET expr = $Length(x)
```java
表達(dá)式可以由或包括對(duì)象屬性乖杠、實(shí)例方法調(diào)用或類方法調(diào)用組成:
```java
SET expr = person.Name
SET expr = obj.Add(1,2)
SET expr = ##class(MyApp.MyClass).Method()
通過將$$放在例程調(diào)用之前,可以直接調(diào)用表達(dá)式中的ObjectScript例程調(diào)用:
SET expr = $$MyFunc^MyRoutine(1)
表達(dá)式可以根據(jù)它們返回的值的類型進(jìn)行分類:
- 算術(shù)表達(dá)式包含算術(shù)運(yùn)算符澄成,對(duì)操作數(shù)進(jìn)行數(shù)值解釋胧洒,并生成數(shù)值結(jié)果:
SET expr = 1 + 2
SET expr = +x
SET expr = a + b
請(qǐng)注意,算術(shù)表達(dá)式中使用的字符串被計(jì)算為數(shù)字值(如果它不是有效的數(shù)字值墨状,則計(jì)算為0)卫漫。還要注意,使用一元加法運(yùn)算符(+)將隱式地將字符串值轉(zhuǎn)換為數(shù)字值歉胶。
- 字符串表達(dá)式包含字符串運(yùn)算符汛兜,為操作數(shù)提供字符串解釋,并生成字符串結(jié)果通今。
SET expr = "hello"
SET expr = "hello" _ x
- 邏輯表達(dá)式包含關(guān)系運(yùn)算符和邏輯運(yùn)算符,對(duì)操作數(shù)進(jìn)行邏輯解釋肛根,并生成布爾結(jié)果:
TRUE(1)
或FALSE(0)
:
SET expr = 1 && 0
SET expr = a && b
SET expr = a > b
- 因此辫塌,對(duì)象表達(dá)式會(huì)生成對(duì)象引用:
SET expr = object
SET expr = employee.Company
SET expr = ##class(Person).%New()
邏輯表達(dá)式
邏輯表達(dá)式使用邏輯運(yùn)算符、數(shù)字關(guān)系運(yùn)算符和字符串關(guān)系運(yùn)算符派哲。它們計(jì)算表達(dá)式并產(chǎn)生布爾值:1(True)
或0(False)
臼氨。邏輯表達(dá)式最常用于:
if命令
$select函數(shù)
- 后置條件表達(dá)式
在布爾測試中,任何計(jì)算結(jié)果為非零數(shù)值的表達(dá)式都返回布爾值1(True)
芭届。任何計(jì)算結(jié)果為零數(shù)值的表達(dá)式都返回布爾值0(FALSE)
储矩。Caché將非數(shù)字字符串計(jì)算為具有零數(shù)值。
可以使用邏輯運(yùn)算符組合多個(gè)布爾邏輯表達(dá)式褂乍。與所有Caché表達(dá)式一樣持隧,它們嚴(yán)格按照從左到右的順序進(jìn)行計(jì)算。這里有兩種類型的邏輯運(yùn)算符:常規(guī)邏輯運(yùn)算符(&
和逃片!
)屡拨。和短路邏輯運(yùn)算符(&&
和||
)。
當(dāng)使用正則邏輯運(yùn)算符組合邏輯表達(dá)式時(shí)褥实,Caché會(huì)計(jì)算所有指定的表達(dá)式呀狼,即使布爾結(jié)果在所有表達(dá)式求值之前已知。這確保了所有表達(dá)式都是有效的损离。
當(dāng)使用短路邏輯運(yùn)算符組合邏輯表達(dá)式時(shí)哥艇,Caché只計(jì)算確定布爾結(jié)果所需的表達(dá)式。例如僻澎,如果有多個(gè)AND測試貌踏,則返回0的第一個(gè)表達(dá)式確定總體布爾結(jié)果瓮增。不計(jì)算此表達(dá)式右側(cè)的任何邏輯表達(dá)式×螅可以避免不必要的表達(dá)式計(jì)算耗時(shí)绷跑。
某些命令允許將逗號(hào)分隔的列表指定為參數(shù)值。在本例中凡资,Caché將每個(gè)列出的參數(shù)作為獨(dú)立的命令語句進(jìn)行處理砸捏。因此,如果x=7
隙赁,y=4
垦藏,z=2
被解析為x=7
,那么如果y=4
伞访,則如果z=2
掂骏,這在功能上與短路邏輯運(yùn)算符語句IF(x=7)&&(y=4)&&(z=2)
相同。
在下面的示例中厚掷,IF測試使用常規(guī)邏輯運(yùn)算符(&
)弟灼。因此,即使第一個(gè)函數(shù)返回0(FALSE)
冒黑,這會(huì)自動(dòng)使整個(gè)表達(dá)式的結(jié)果為FALSE
田绑,也會(huì)執(zhí)行所有函數(shù):
LogExp
IF $$One() & $$Two() {
WRITE !,"Expression is TRUE." }
ELSE {
WRITE !,"Expression is FALSE." }
One()
WRITE !,"one"
QUIT 0
Two()
WRITE !,"two"
QUIT 1
one
two
Expression is FALSE.
在下面的示例中,IF測試使用短路邏輯運(yùn)算符(&&
)抡爹。因此掩驱,執(zhí)行第一個(gè)函數(shù)并返回0(False)
,這會(huì)自動(dòng)使整個(gè)表達(dá)式的結(jié)果為false
冬竟。不執(zhí)行第二個(gè)函數(shù):短路邏輯運(yùn)算符(&&)
欧穴。
LogExp
IF $$One() && $$Two() {
WRITE !,"Expression is TRUE." }
ELSE {
WRITE !,"Expression is FALSE." }
One()
WRITE !,"one"
QUIT 0
Two()
WRITE !,"two"
QUIT 1
one
Expression is FALSE.
在下面的示例中,if測試指定逗號(hào)分隔的參數(shù)泵殴。逗號(hào)不是邏輯運(yùn)算符涮帘,但與指定短路&&邏輯運(yùn)算符的效果相同。執(zhí)行第一個(gè)函數(shù)并返回0(False)
袋狞,這會(huì)自動(dòng)使整個(gè)表達(dá)式的結(jié)果為false
焚辅。不執(zhí)行第二個(gè)函數(shù):
LogExp
IF $$One(),$$Two() {
WRITE !,"Expression is TRUE." }
ELSE {
WRITE !,"Expression is FALSE." }
One()
WRITE !,"one"
QUIT 0
Two()
WRITE !,"two"
QUIT 1
one
Expression is FALSE.
/// w ##class(PHA.TEST.ObjectScript).TestComma()
ClassMethod TestComma()
{
s firstName = "Yao"
s lastNmae = "Xin"
i firstName = "Yao",lastNmae = "Xin" d
.w "true",!
e d
.w "false",!
i firstName = "Yao",lastNmae = "X" d
.w "true",!
e d
.w "false",!
i firstName = "Y",lastNmae = "Xin" d
.w "true",!
e d
.w "false",!
i firstName = "Y",lastNmae = "X" d
.w "true",!
e d
.w "false",!
q ""
}
DHC-APP>w ##class(PHA.TEST.ObjectScript).TestComma()
true
false
false
false
賦值
在ObjectScript中,set
命令與賦值運(yùn)算符(=
)一起使用苟鸯,為變量賦值同蜻。賦值命令的右側(cè)是一個(gè)表達(dá)式:
SET value = 0
SET value = a + b
在ObjectScript中,還可以使用賦值命令左側(cè)的某些函數(shù):
SET pies = "apple,banana,cherry"
WRITE "Before: ",pies,!
// set the 3rd comma-delimited piece of pies to coconut
SET $Piece(pies,",",3) = "coconut"
WRITE "After: ",pies
Before: apple,banana,cherry
After: apple,banana,coconut
字符串到數(shù)字的轉(zhuǎn)換
字符串可以是數(shù)字早处、部分?jǐn)?shù)字或非數(shù)字湾蔓。
- 數(shù)字字符串完全由數(shù)字字符組成。例如砌梆,"
123
", "+123"
, ".123
", "++0007
", "-0
". - 部分?jǐn)?shù)字字符串是以數(shù)字符號(hào)開頭默责,后跟非數(shù)字字符的字符串贬循。例如,"
3 blind mice
", "-12 degrees
". - 非數(shù)字字符串以非數(shù)字字符開頭桃序。例如 "
123
", "the 3 blind mice
", "three blind mice
".
數(shù)字字符串
在算術(shù)表達(dá)式中使用數(shù)字字符串或部分?jǐn)?shù)字字符串時(shí)杖虾,它將被解釋為數(shù)字。此數(shù)值是通過從左向右掃描字符串以查找可解釋為數(shù)字文字的最長前導(dǎo)字符序列來獲得的媒熊。允許使用以下字符:
- 數(shù)字0到9奇适。
- PlusSign和MinusSign屬性值。默認(rèn)情況下芦鳍,這些是“
+
”和“-
”字符嚷往,但取決于區(qū)域設(shè)置。使用%SYS.NLS.Format.GetFormatItem()
方法返回當(dāng)前設(shè)置柠衅。 -
DecimalSeparator
屬性值皮仁。默認(rèn)情況下,這是“”
菲宴。字符贷祈,但取決于區(qū)域設(shè)置。使用%SYS.NLS.Format.GetFormatItem()
方法返回當(dāng)前設(shè)置裙顽。 - 字母“
e
”和“E
”在表示科學(xué)記數(shù)法的序列(例如4E3
)中時(shí)可以作為數(shù)字字符串的一部分包括在內(nèi)付燥。
請(qǐng)注意,NumericGroupSeparator
屬性值(默認(rèn)情況下為“愈犹,”
字符)不被視為數(shù)字字符。因此闻丑,字符串“123漩怎,456”
是解析為數(shù)字“123
”的部分?jǐn)?shù)字字符串。
數(shù)字字符串和部分?jǐn)?shù)字字符串在算術(shù)運(yùn)算(如加法和減法)和大于/小于比較運(yùn)算(<嗦嗡、>勋锤、<=、>=)
之前轉(zhuǎn)換為規(guī)范形式侥祭。在相等比較(=叁执,‘=)
之前谈宛,不會(huì)將數(shù)字字符串轉(zhuǎn)換為規(guī)范形式吆录,因?yàn)檫@些運(yùn)算符還用于字符串比較操作(<恢筝,>撬槽,<=侄柔,>=)
和大于/小于比較操作(<勋拟,>敢靡,<=啸胧,>=)
。
以下示例顯示數(shù)字字符串的算術(shù)比較:+贝椿,<=陷谱,>=
烟逊。
WRITE "3" + 4,! // returns 7
WRITE "003.0" + 4,! // returns 7
WRITE "++--3" + 4,! // returns 7
WRITE "3 blind mice" + 4,! // returns 7
7
7
7
7
以下示例顯示數(shù)字字符串的小于(<)
比較:
WRITE "3" < 4,! // returns 1
WRITE "003.0" < 4,! // returns 1
WRITE "++--3" < 4,! // returns 1
WRITE "3 blind mice" < 4,! // returns 1
1
1
1
1
以下示例顯示<=
數(shù)字字符串的比較:
WRITE "4" <= 4,! // returns 1
WRITE "004.0" <= 4,! // returns 1
WRITE "++--4" <= 4,! // returns 1
WRITE "4 horsemen" <= 4,! // returns 1
1
1
1
1
下面的示例顯示數(shù)字字符串的相等比較宪躯。將非規(guī)范數(shù)字字符串作為字符串進(jìn)行比較,而不是將其作為數(shù)字進(jìn)行比較详瑞。請(qǐng)注意,-0是一個(gè)非規(guī)范的數(shù)字字符串驳庭,因此將其作為字符串進(jìn)行比較饲常,而不是將其作為數(shù)字進(jìn)行比較:
WRITE "4" = 4.00,! // returns 1
WRITE "004.0" = 4,! // returns 0
WRITE "++--4" = 4,! // returns 0
WRITE "4 horsemen" = 4,! // returns 0
WRITE "-4" = -4,! // returns 1
WRITE "0" = 0,! // returns 1
WRITE "-0" = 0,! // returns 0
WRITE "-0" = -0,! // returns 0
1
0
0
0
1
1
0
0
非數(shù)字字符串
如果字符串的前導(dǎo)字符不是數(shù)字字符柒竞,則對(duì)于所有算術(shù)運(yùn)算播聪,字符串的數(shù)值均為0。對(duì)于<、>霎俩、‘>打却、<=谎倔、’<和>=
比較,非數(shù)字字符串也被視為數(shù)字0片习。因?yàn)榈忍?hào)同時(shí)用于數(shù)字等式運(yùn)算符和字符串比較運(yùn)算符捌肴,所以字符串比較優(yōu)先用于=
和‘=
運(yùn)算藕咏。可以追加PlusSign屬性值(默認(rèn)情況下為+
)侈离,以強(qiáng)制對(duì)字符串進(jìn)行數(shù)字計(jì)算。當(dāng)x和y是不同的非數(shù)字字符串(例如筝蚕,x=“Fred”,y=“Wilma”
)時(shí)起宽,這會(huì)產(chǎn)生以下邏輯值坯沪。
列 | 列 | 列 | 列 | |
---|---|---|---|---|
x=y is FALSE | x=x is TRUE | +x=y is FALSE | +x=+y is TRUE | +x=+x is TRUE |
x'=y is TRUE | x'=x is FALSE | +x'=y is TRUE | +x'=+y is FALSE | +x'=+x is FALSE |
x < y is FALSE | x < x is FALSE | +x < y is FALSE | +x<+y is FALSE | +x<+x is FALSE |
x <= y is TRUE | x <=x is TRUE | +x <=y is TRUE | +x<=+y is TRUE | +x<=+x is TRUE |