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

17

最近我在阅读一些 Lua 源文件时经常遇到这种语法,特别是第二对方括号是什么意思?下面是一个例子,位于第8行的https://github.com/karpathy/char-rnn/blob/master/model/LSTM.lua

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 的源代码https://github.com/torch/nn/blob/master/Identity.lua

********** 更新 **************

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

例如,y = nn.Linear(2,4)(x) 表示 x 连接到 y,转换是从 1*2 到 1*4 的线性变换。 我只理解了使用方法,它的连接方式好像已经在下面的答案之一中得到了回答。

无论如何,接口的使用方法在下面有详细的文档说明。 https://github.com/torch/nngraph/blob/master/README.md


如果遇到疑问,解决问题的好方法是使用表达式 nn.Identity() 并给它一个有意义的名称。例如(但由于我不知道该如何称呼它,所以这里只用了一个几乎没有意义的名称):local identityProvider = nn.Identity() - Tom Blodget
3个回答

14
不,()()在Lua中没有特殊含义,它只是两个调用运算符()放在一起。
操作数可能是一个返回函数的函数(或者实现了call元方法的表)。例如:
function foo()
  return function() print(42) end
end

foo()()   -- 42

13

除了Yu Hao的回答外,让我提供一些与Torch相关的细节:

  • nn.Identity()创建一个身份模块,
  • 在此模块上调用()会触发nn.Module __call__(感谢Torch类系统正确地将其钩入元表),
  • 默认情况下,此__call__方法执行前向/后向传递,
  • 但是这里使用了torch/nngraph,因此nngraph覆盖了此方法,您可以在这里看到。

因此,每个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,并且参数指定了它在图中的父级。

2
  • The first () calls the init function and the second () calls the call function
  • If the class doesn't posses either of these functions then the parent functions are called .
  • In the case of nn.Identity()() the nn.Identity has neither init function nor a call function hence the Identity parent nn.Module's init and call functions called .Attaching an illustration

    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()()

输出

    inside __init of A
    inside __call__ of A

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接