2016-01-21 52 views
3

匿名子我是新来的Ruby和试图复制这个perl,它调用的匿名子,在红宝石:Perl的像红宝石

#!/usr/bin/perl 

use strict; 
use warnings; 
use feature 'say'; 

# Make a reference to a subroutine 
my $codes = { 
    one => sub { 
     say "This is code block one"; 
     say "And this is code block one's line two" 
    }, 
}; 

for my $next_code (keys %{ $codes }) { 
    # Execute anonymous subroutine 
    &{ $codes->{ $next_code } }; 
} 

我尝试这样做:

#!/usr/bin/ruby -w 

codes = { 
    one: puts "This is code block one" 
     puts "And this is code block one's line two", 
} 
codes.each do |next_code| 
    next_code 
end 

但是,我得到语法错误。这是可能的,还是有另一种首选的红宝石方式?

更新:是的,这就像一个调度表。我将代码存储在一个散列中,稍后再运行该代码。

+1

看起来你可能试图实现一个调度表。如果是这样,在你的问题中提到避免XY问题是很好的。在Ruby中可能有更好的方法,它采用与Perl完全不同的方法。 – ThisSuitIsBlackNot

+1

你能用普通词(不是perl代码)解释你想做什么? –

+4

'最好写成'$ code - > {$ next_code} - >()' – Borodin

回答

7

红宝石有Proc s作为匿名头等子程序对象。 Proc s可以通过将一个块传递给Proc::newKernel#procKernel#lambda或者使用“stabby lambda”lambda文字语法来创建。

#!/usr/bin/env ruby 

# Make a reference to a subroutine 
codes = { 
    one: -> { 
    puts "This is code block one" 
    puts "And this is code block one's line two" 
    } 
} 

codes.each do |name, code| 
    # Execute anonymous subroutine 
    code.() 
end 

在红宝石匿名码块的最广泛使用的形式是被称为构建体,这实际上不是一个对象,而只是一个语法构造。 Ruby中的每个方法都只有一个可选的块参数,它可以通过大括号或在普通方法参数后面使用关键字对来传递。您可以在上面的代码中看到正在执行的块,并将其传递给迭代方法Hash#each

如果您有兴趣,这里是我的一个小型玩具项目,演示了使用各种语言的一流的闭包,包括Perl5和Perl6,Ruby,PHP,Python,ECMAScript,Smalltalk,Clojure, Scheme和其他许多方面:http://joergwmittag.github.io/lambdaconscarcdr/

+1

有趣的事情有一点特别有趣的是它们可以被调用(至少?)五方法。假设'f = - > s {放置“说#{s}!” }'。然后'f.call('hey')','f ['hey']','f。('hey')','f.yield('hey')'和'f ===“嘿” '全部打印'“说嘿!”'。 –

+1

虽然“正常”的方式是使用'call'或者它的语法糖'。()'。 '[]'是'call'的过时别名,用于通过使用括号作为假圆括号来调用'Proc'更像方法调用。从Ruby 1.9开始,我们使用'。()'符号,这更符合IMO的需要。 'yield'我不知道,我想这是为了API与Fibre的兼容性? '==='在'case'表达式和'Enumerable#grep'中使用'Proc'很有用,但可能不应该直接调用。注意:除了'('''''''''''''''''''''''是'call'的语法糖之外,它们都是'call'的别名。 –