Daily Code Reading #6 – Facets Array#pad

This week I’m looking at Facets’ Array extensions. Hash, Array, String, and Integer objects are used frequently in Rails so I can take advantage of them faster than more complex classes.

The Code

1
2
3
4
5
6
7
8
9
# File lib/core/facets/array/pad.rb, line 14
  def pad(len, val=nil)
    return dup if self.size >= len.abs
    if len < 0
      Array.new((len+size).abs,val) + self
    else
      self + Array.new(len-size,val)
    end
  end

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/ruby -wKU
#
# Code Reading #6
require '../base'
require "facets/array/pad"
 
class Example
  def self.create
    last_ten_transactions = [
                             52.25,
                             100.25,
                             0.45
                            ]
    last_ten_transactions.pad(10, 0)
  end
end
 
ap Example.create
 
class ArrayPadTest < Test::Unit::TestCase
  def test_should_pad_the_array_to_10_elements
    result = Example.create
 
    assert_equal 10, result.length
  end
 
  def test_should_pad_to_the_end_of_the_array
    result = Example.create
 
    assert_equal [
                  52.25,
                  100.25,
                  0.45,
                  0,
                  0,
                  0,
                  0,
                  0,
                  0,
                  0
                 ], result
  end
end

On github

Review

Array#pad‘s concept is pretty easy to understand, since padding is used with strings a lot. The implementation is a bit terse so I’ll break it up a little bit to help understanding. Array#pad has three different exit conditions:

  1. The array is already bigger than the padding.
  2. #pad is called with a positive padding length.
  3. #pad is called with a negative padding length.

The first exit condition is from the guard clause, return dup if self.size >= len.abs. The reason it’s using dup is because Array#pad is returning a new array for all the other conditions. If this case was different, the caller might accidentally use the Array without knowing that’s it’s the same Array they passed in.

The second exit condition is when #pad is called with a positive padding length. This will create a new array that is prepopulated with val and append it to the calling array, making sure the total length is equal to the len.

The third exit condition is when #pad has a negative padding length. Like before it creates a new array that is prepopulated with val, but this time it prepends the new array onto the calling array.

Prepopulate an Array with values

To prepopulate an array with values, just pass the size and value to Array#new. It can also take a block if you need something more dynamic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>> Array.new(10, 'ten element array')
[
    [0] "ten element array",
    [1] "ten element array",
    [2] "ten element array",
    [3] "ten element array",
    [4] "ten element array",
    [5] "ten element array",
    [6] "ten element array",
    [7] "ten element array",
    [8] "ten element array",
    [9] "ten element array"
]
>> Array.new(10) { rand(100) }
[
    [0] 93,
    [1] 11,
    [2] 81,
    [3] 84,
    [4] 14,
    [5] 16,
    [6] 6,
    [7] 40,
    [8] 77,
    [9] 88
]