Lua中的()()语法有特殊含义吗?

我最近在阅读 Lua 源文件时经常看到这种语法,它是什么意思,特别是第二对方括号是什么意思?以LSTM.lua文件为例,第8行实例如下:

local LSTM = {}
function LSTM.lstm(input_size, rnn_size, n, dropout)
  dropout = dropout or 0

  -- there will be 2*n+1 inputs
  local inputs = {}
  table.insert(inputs, nn.Identity()())  -- line 8
  -- ...

nn.Identity 的源代码如下:Identity.lua

\*\*\*\*\*\*\*\*\*\* 更新 **************

模式 ()() 在 Torch 库 nn 中经常被使用。第一对括号创建一个容器/节点的对象,第二对括号引用依赖节点。

例如,y = nn.Linear(2,4)(x) 表示 x 连接到 y,变换是从 1*2 到 1*4 的线性变换。

我只理解了使用方法,关于它的连线方式,似乎在下面的一个答案中已经得到了回答。

无论如何,这个接口的使用方法在下面的文档中有很好的记录:README.md

点赞
用户1009479
用户1009479

不,()() 在 Lua 中没有特殊含义,它只是两个调用运算符 () 接在一起。

操作数可能是一个返回函数的函数(或者一个实现了 call 元方法的表)。例如:

function foo()
  return function() print(42) end
end

foo()()   -- 42
2015-06-22 15:14:32
用户1688185
用户1688185

作为对于Yu Hao答案的补充,让我给出一些与Torch相关的细节:

  • nn.Identity()创建一个标识模块,
  • 对该模块进行的()调用会触发nn.Module __call__ (感谢Torch类系统的适当钩子将其连接到元表中),
  • 默认情况下,该__call__方法会执行前向/后向操作,
  • 但在这里,使用了 torch/nngraphnngraph 覆盖了这个方法,你可以在 这里 看到。

因此,在这里每个 nn.Identity()() 调用的作用是返回一个 nngraph.Node({module=self}) 节点,其中self指的是当前的 nn.Identity() 实例。

--

更新:可以在LSTM-s的语境下,找到这种语法的示例,详见此处

local i2h = nn.Linear(input_size, 4 * rnn_size)(input)  -- input to hidden

如果您不熟悉 nngraph,那么我们构造模块并使用一个图形节点再次调用它可能看起来很奇怪。实际上,第二个调用将 nn.Module 转换为 nngraph.gModule,参数指定其在图形中的父级

2015-06-24 10:29:18
用户2036809
用户2036809
  • 第一个()调用init函数,第二个()调用call函数

  • 如果类没有这两个函数,则调用父函数。

  • 在nn.Identity()()的情况下,nn.Identity既没有init函数也没有call函数,因此调用Identity父nn.Module的init和call函数。附上示意图

    require 'torch'
    
    -- define some dummy A class
    local A = torch.class('A')
    function A:__init(stuff)
      self.stuff = stuff
      print('inside __init of A')
    end
    
    function A:__call__(arg1)
    print('inside __call__ of A')
    end
    
    -- define some dummy B class, inheriting from A
    local B,parent = torch.class('B', 'A')
    
    function B:__init(stuff)
      self.stuff = stuff
      print('inside __init of B')
    end
    
    function B:__call__(arg1)
    print('inside __call__ of B')
    end
    a=A()()
    b=B()()
    

    Output

    inside __init of A
    inside __call__ of A
    inside __init of B
    inside __call__ of B
    

另一个代码示例

    require 'torch'

    -- define some dummy A class
    local A = torch.class('A')
    function A:__init(stuff)
      self.stuff = stuff
      print('inside __init of A')
    end

    function A:__call__(arg1)
    print('inside __call__ of A')
    end

    -- define some dummy B class, inheriting from A
    local B,parent = torch.class('B', 'A')

    b=B()()

Output

    inside __init of A
    inside __call__ of A
2016-05-18 15:56:16