3

I'm new to ruby and trying to duplicate this perl, that calls anonymous subroutines, in ruby:

#!/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 } };
}

I tried this:

#!/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

But, I get syntax errors. Is this possible, or is there another preferred ruby way?

UPDATE: Yes, this is like a dispatch table. I store code in a hash and run that code later.

3
  • 1
    It looks like you might be trying to implement a dispatch table. If so, it would be good to mention that in your question to avoid the XY problem. There might be a better way to do it in Ruby that takes a completely different approach than Perl. Commented Jan 21, 2016 at 18:51
  • 1
    Can you explain in common words(not perl code) what do you want to do? Commented Jan 21, 2016 at 18:54
  • 4
    &{ $codes->{ $next_code } } is best written $codes->{ $next_code }->() Commented Jan 21, 2016 at 19:04

1 Answer 1

7

Ruby has Procs as anonymous first-class subroutine objects. Procs can be created by passing a block to Proc::new, Kernel#proc, or Kernel#lambda, or with the "stabby lambda" lambda literal syntax.

#!/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

The most widely-used form of anonymous code block in Ruby is a construct called a block, which is actually not an object, but just a syntactic construct. Every method in Ruby takes exactly one optional block argument, which can be passed either in curly braces or using a do/end keyword pair after the normal method arguments. You can see a block in action in the code above, being passed to the Hash#each iteration method.

In case you are interested, here is a small toy project of mine that demonstrates the use of first-class closures in a variety of languages, including Perl5 and Perl6, Ruby, PHP, Python, ECMAScript, Smalltalk, Clojure, Scheme, and many others: http://joergwmittag.github.io/lambdaconscarcdr/

Sign up to request clarification or add additional context in comments.

2 Comments

One thing interesting about procs is that they can be called in (at least?) five ways. Suppose f = ->s { puts "Say #{s}!" }. Then f.call('hey'), f['hey'], f.('hey'), f.yield('hey') and f === "hey" all print "Say hey!".
Although the "normal" way is to use call or its syntactic sugar .(). [] is an outdated alias for call that was used to make calling a Proc more like a method call by using the brackets as fake parentheses. As of Ruby 1.9, we have the .() notation, which serves this purpose better, IMO. yield I didn't know about, I suppose it is for API compatibility with Fibres? === is useful for using Procs in case expressions and Enumerable#grep, but probably shouldn't be called directly. Note: all of them are aliases for call, except (), which is syntax sugar for call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.