Under the hood – Ruby methods Array#map, Array#inject

In the spirit or writing some Ruby methods I’m going to add three in this post. We’ll begin with mapping elements of an Array.

class Array
    def rb_map
        n_array = []
        self.each { |elm| n_array << yield(elm) }
        n_array
    end
end

Then we do Inject,

class Array
    def rb_inject initial = nil
        value = initial
        self.each { |elm| value = yield(value,elm) }
        value
    end
end

And finally, let’s revisit map using our inject:

class Array
    def new_map_using_inject
        rb_inject([]) { |set, elm| set << elm }
    end
end

You’ll notice I did not do any error handling. That’s not the point of the exercise; we want to know what the methods we call daily do behind the scenes.

Hanging in the Treetops

I wanted to find a way to parse short urls without making any database calls. Since I have a pattern for short urls I figured, for a bit of fun, a parser would make this possible.

Enter Treetop: Treetop is a language for describing languages. Combining the elegance of Ruby with cutting-edge parsing expression grammars, it helps you analyze syntax with revolutionary ease.” Treetop

The grammar defined is straight forward: (FILE: message_grammar.treetop)

grammar MessageGrammar
 rule message
   [0-9] / 'X' message / ('Y' / 'Z') message message
 end
end

So here are some valid codes: 0, X0, XY00, XX0, XY09
Invalid codes: T0, P, PPPPP0, X0X0X00

Make sure you’ve got treetop installed. Drop into terminal in the directory of the grammar file and run
tt message_grammar.treetop
This will result in a file called message_grammar.rb which you can include in another file to use as your parser…

File: message_parser.rb

require "rubygems"
require "treetop"
require "polyglot"
require "message_grammar"
 
# MessgeGrammarParser is a generated Parsing class based on the grammar
# defined in message_grammar.treetop
parser = MessageGrammarParser.new
 
STDIN.each do |string|
 
 # for each string, split on whitespace
 string.split(" ").each do |message|
   # print status of whether the message could be parsed or not
   puts "#{message} #{parser.parse(message) ? 'VALID' : 'INVALID'}"
 end
end

And we’re Done-zo Washington. Parse away.