【风格】传统形式与表达式

作者:amnesiac 首发:官方论坛中文版
本篇中主要专注于 AutoHotkey 中容易引起困惑的传统形式和表达式两种风格,进行比较并提供一些建议,以尽可能去除在学习或使用过程中的困惑。

从示例开始

有人在论坛中提问(加不加括号,效果截然不同 • AHKScript),在帮助文档 ListView 的一个示例中(注:这里只是片段,完整代码请参阅帮助 ListView 页面):

GuiContextMenu:
if A_GuiControl <> MyListView
    return

Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
return

然后他做了点小小的修改(把 If 后的部分加在括号中):

GuiContextMenu:
if (A_GuiControl <> MyListView)
    return

Menu, MyContextMenu, Show, %A_GuiX%, %A_GuiY%
return 

运行时他发现效果完全不同了:修改前在 ListView 控件上点击才显示右键菜单,而修改后则是在窗口的空白处点击才显示菜单,很不理解。

为什么会这样呢?因为他在不理解 If 传统型和 If(表达式)就加上括号,这是产生问题的根源,加上括号则成了表达式(在修改后的脚本中),同时 MyListView 成了变量,但该脚本中不存在这个变量,实际上换成任何一个脚本中不存在的变量名效果都一样(不过这里的名称有迷惑性,让人误解它有特定意义)。为什么还能运行?这必须提到 AutoHotkey 的变量机制:使用即存在,换句话说,大部分情况下当我们需要变量时直接使用就行了。如果是其他语言,一般会出现变量不存在的提示。

从另一角度看,困惑的来源是为什么会存在容易引起误解的两种风格呢?AutoHotkey 最初参照自典型命令式语言 AutoIt v2,这是传统型存在的历史原因,因为有些情况下传统型无法解决,在开发过程中加强了表达式型,所以目前形成并存的局面。

传统赋值与表达式赋值

str = 这是个字符串。 ; 传统赋值
str := "这是个字符串。" ; 表达式赋值

上面这两个赋值语句是等效的,可以看到传统赋值在变量名后使用等号接着是作为赋值内容的字符串。而表达式赋值使用冒号等号,后面的赋值内容括在引号中。看起来似乎传统赋值简单一些,这里确实如此,然而它只适用于赋值字符串、数字、变量或它们组合的内容,并且在包含变量时变量名称必须括在百分号中。现在在看看赋值内容包含字符串和变量的例子:

str = 这是个字符串,后面跟着 Var 变量的内容:%var%
str := "这是个字符串,后面跟着 Var 变量的内容:" var

这时可以发现传统赋值和表达式赋值复杂度上接近,进一步的,如果只赋值变量,显然表达式方式简单了。它们的区别主要不在这里,请看这个例子:

var = 1 + 1
var := 1 + 1

保存为脚本,运行看看结果。这里说明了它们的主要区别,表达式赋值时可以进行运算,操作数可以为数字、字符串、函数调用等。这种情况时无法用传统形式代替。

如果能明确它们的区别,可以两者都用。如果担心会混淆,那么只能采用表达式赋值了,这是我对初学者建议的方法。

If 传统型与 If 表达式型

这里包含好几个命令及等价的比较结构,除了 If 表达式型外我唯一建议使用的是下面这种形式:

If var
    MsgBox, var 变量既不为零也不为空。

这里 If 语句中的 var 是使用这个变量的值,而 MsgBox 命令中则使用这个变量的名称。下面是其他一些句式:

IfEqual, var, value (等同于: if var = value)
IfNotEqual, var, value (等同于: if var <> value) (可以使用 != 代替 <>)
IfGreater, var, value (等同于: if var > value)
IfGreaterOrEqual, var, value (等同于: if var >= value)
IfLess, var, value (等同于: if var < value)
IfLessOrEqual, var, value (等同于: if var <= value)

这些命令都很简单,名称的含义也显而易见。第一个变量是不需要百分号括住的变量,第二个是原义的值。可以使用两种形式:

IfEqual, var, value
    MsgBox, 变量 var 的值为:value。

if var = value
    MsgBox, 变量 var 的值为:value。

这两种形式完全相同,后一种形式虽然含有等号,但这里不是表达式。现在看看使用表达式的形式:

if (var = "value")
    MsgBox, 变量 var 的值为:value。

传统形式比较简单,但也只能比较最简单的情况。下面这个例子则无法使用传统形式代替了:

if (Mod(intYear, 100) ? Mod(intYear, 400) : Mod(intYear, 4))
    MsgBox, % intYear "不是润年。"

还有很多情况无法使用传统形式代替,同时接受两种很可能产生混淆,一是变量什么时候应括在百分号中,二是值什么时候要加引号。

两种同时使用不行吗?

在只赋值字符串时使用传统形式,而需要运算时则通过表达式,两者都很简单,为什么非要两者选一呢?这样的问题不是“行不行”,既然语言自身提供了,当然不会不行。主要问题在于如果没有理解,那么会给您带来困惑,即让您的脚本增加出错的可能。

请看这个例子:

if Var = ""
    MsgBox, 变量 Var 为空。

请闭上眼睛几秒钟,想想什么时候会显示消息框?

【=====================分隔区域,请暂停往下看=====================】

您刚才是否在想当 Var 变量为空时这个 If 语句结果为真呢?这样就错了,实际是只有在 Var 包含一对双引号时才为真。如果要判断一个变量是否为空,正确的传统形式和表达式形式应该这样:

; 传统形式
if Var =
    MsgBox, 变量 Var 为空。

; 表达式形式
if (Var = "")
    MsgBox, 变量 Var 为空。

所以建议完全使用表达式形式,当然在理解的基础上一起用是没问题的。

小结

最后,从 AutoHotkey Basic 到 AutoHotkey_L 中表达式型一直在加强,个人猜测 AutoHotkey v2 版本可能完全转向表达式型(目前测试版中尚未实现,但在 Thoughts for v2.0 中 Lexikos 有这种倾向),所以不论从目前的理解或以后的学习、过渡而言,建议采用表达式型。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容