以下代码可以运行. 意味着可以使用回调函数

Function f1(x,y)
    return x + y
end Function
Function f2(x,y)
    return x - y 
End Function
Function a(f)
    Log.Info(f(1,2))
End Function
a(f1)
a(f2)

并且函数名除了作为形参,还可以作为普通变量以及对象的值

Dim f = f2
f('from f')

dim o = {
    'f': f1
}
dim o_f = o['f']
o_f('from o_f')

Function f1(s)
    Log.Info('f1')
    Log.Info(s)
End Function

Function f2(s)
    Log.Info('f2')
    Log.Info(s)

End Function

上面的用法,意味着可以创造类似于接口的功能,使用同一接口函数抽象调用,实际实现可以不同。
另外,也可以实现类似于面向对象的开发,在一个object中除了定义变量还可以定义函数。只是在对象中的函数不能直接写在对象里,也不能匿名,需要在外面写好,在对象里赋值。
同样的,对象里的函数也不能通过o['f']()的方式调用,需要先赋值给变量,再通过变量调用。

另外,发现在函数中使用这种方法会报错,似乎和编译有关:

Function a()
  dim f = f1
  f()
End Function

Function f1()
  log.info(f1)
End Function

报错: 后端错误 unexpected symbol near ')'
这种情况只要将dim f放到全局就会正常,不知道为何,似乎是回调函数名称必须为全局变量(常量), 如下:

dim f
Function a()
  f = f1
  f()
End Function

Function f1()
  log.info(f1)
End Function

另外,始终没有找到根据字符串常量表示的函数名调用对应函数的方法。

回调的坑: 跨文件调用回调会丢失全局环境(包括全局变量)

有一个主文件为test.task, 一个作为提供函数的模块文件tools.task, 如果在主文件中调用模块文件中的函数, 并给其提供的回调函数位于主文件中, 那么此回调函数不能访问主文件中的全局变量.
调用关系: 主文件->调用模块文件的函数(主文件的回调函数名)->调用主文件回调函数->丢失主文件全局变量. 示意如下:

/* tools.task 模块文件 */
Function funcInTools(cb)
    Log.Info('funcInTools')
    gCallback = cb
    gCallback()
End Function

/* test.task 主文件 */
Import tools
Dim gCallback
Dim gLost = 11 
funcInMain(cbInMain) // 通过主文件的函数调用主文件的回调函数, 不会丢失全局变量
tools.funcInTools(cbInMain) // 通过模块文件的函数调用主文件的回调函数, 丢失全局变量

Function cbInMain() //主文件中的回调
    Log.Info(gLost)
End Function

Function funcInMain(cb)
    Log.Info('funcInMain')
    gCallback = cb
    gCallback()
End Function

运行后输出如下:

[2024-4-24 11:42:04] [INFO] 流程 test.task 开始运行
[2024-4-24 11:42:04] [INFO] test.task 第15行:funcInMain
[2024-4-24 11:42:04] [INFO] test.task 第11行:11
[2024-4-24 11:42:04] [INFO] tools.task 第7行:funcInTools
[2024-4-24 11:42:04] [INFO] test.task 第11行:null

可以看到回调函数第一次调用可以输出全局变量, 而第二次调用则不可以.
这种情况建议将全局变量通过形参传入:

/* tools.task 模块文件 */
Function funcInTools(cb, 传入变量)
    Log.Info('funcInTools')
    gCallback = cb
    gCallback(传入变量)
End Function

/* test.task 主文件 */
Import tools
Dim gCallback
Dim gLost = 11 
tools.funcInTools(cbInMain, gLost) // 通过模块文件的函数调用主文件的回调函数, 丢失全局变量

Function cbInMain(传入变量) //主文件中的回调
    Log.Info(传入变量)
End Function

标签: none 阅读量: 837

添加新评论