Module: Kernel

Defined in:
lib/functional/behavior.rb,
lib/functional/utilities.rb

Constant Summary collapse

BehaviorError =
Class.new(StandardError)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.behaves_asObject

Specify a #behavior_info to enforce on the enclosing class

Parameters:

  • name (Symbol)

    name of the #behavior_info being implemented

Raises:



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/functional/behavior.rb', line 77

def behavior(name)

  name = name.to_sym
  raise BehaviorError.new("undefined behavior '#{name}'") if $__behavior_info__[name].nil?

  clazz = self.method(:behavior).receiver

  unless clazz.instance_methods(false).include?(:behaviors)
    class << clazz
      def behaviors
        @behaviors ||= []
      end
    end
  end

  clazz.behaviors << name

  if self.class == Module
    (class << self; self; end).class_eval do
      define_method(:included) do |base|
        base.class_eval do
          behavior(name)
        end
      end
    end
  end

  if self.class == Class
    unless self.respond_to?(:__new)
      class << clazz
        alias_method(:__new, :new)
      end
    end
  end

  if $ENABLE_BEHAVIOR_CHECK_ON_CONSTRUCTION == true
    class << clazz
      def new(*args, &block)
        obj = __new(*args, &block)
        self.ancestors.each do |clazz|
          if clazz.respond_to?(:behaviors)
            clazz.behaviors.each do |behavior|
              valid = obj.behaves_as?(behavior, true)
            end
          end
        end
        return obj
      end
    end
  end
end

.behavior(name) ⇒ Object

Specify a #behavior_info to enforce on the enclosing class

Parameters:

  • name (Symbol)

    name of the #behavior_info being implemented

Raises:



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/functional/behavior.rb', line 24

def behavior(name)

  name = name.to_sym
  raise BehaviorError.new("undefined behavior '#{name}'") if $__behavior_info__[name].nil?

  clazz = self.method(:behavior).receiver

  unless clazz.instance_methods(false).include?(:behaviors)
    class << clazz
      def behaviors
        @behaviors ||= []
      end
    end
  end

  clazz.behaviors << name

  if self.class == Module
    (class << self; self; end).class_eval do
      define_method(:included) do |base|
        base.class_eval do
          behavior(name)
        end
      end
    end
  end

  if self.class == Class
    unless self.respond_to?(:__new)
      class << clazz
        alias_method(:__new, :new)
      end
    end
  end

  if $ENABLE_BEHAVIOR_CHECK_ON_CONSTRUCTION == true
    class << clazz
      def new(*args, &block)
        obj = __new(*args, &block)
        self.ancestors.each do |clazz|
          if clazz.respond_to?(:behaviors)
            clazz.behaviors.each do |behavior|
              valid = obj.behaves_as?(behavior, true)
            end
          end
        end
        return obj
      end
    end
  end
end

.behavior_info(name, functions = {}) ⇒ Object

Define a behavioral specification (interface).

Parameters:

  • name (Symbol)

    the name of the behavior

  • functions (Hash) (defaults to: {})

    function names and their arity as key/value pairs



9
10
11
12
# File 'lib/functional/behavior.rb', line 9

def behavior_info(name, functions = {})
  $__behavior_info__ ||= {}
  $__behavior_info__[name.to_sym] = functions.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
end

.behaviourObject

Specify a #behavior_info to enforce on the enclosing class

Parameters:

  • name (Symbol)

    name of the #behavior_info being implemented

Raises:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/functional/behavior.rb', line 76

def behavior(name)

  name = name.to_sym
  raise BehaviorError.new("undefined behavior '#{name}'") if $__behavior_info__[name].nil?

  clazz = self.method(:behavior).receiver

  unless clazz.instance_methods(false).include?(:behaviors)
    class << clazz
      def behaviors
        @behaviors ||= []
      end
    end
  end

  clazz.behaviors << name

  if self.class == Module
    (class << self; self; end).class_eval do
      define_method(:included) do |base|
        base.class_eval do
          behavior(name)
        end
      end
    end
  end

  if self.class == Class
    unless self.respond_to?(:__new)
      class << clazz
        alias_method(:__new, :new)
      end
    end
  end

  if $ENABLE_BEHAVIOR_CHECK_ON_CONSTRUCTION == true
    class << clazz
      def new(*args, &block)
        obj = __new(*args, &block)
        self.ancestors.each do |clazz|
          if clazz.respond_to?(:behaviors)
            clazz.behaviors.each do |behavior|
              valid = obj.behaves_as?(behavior, true)
            end
          end
        end
        return obj
      end
    end
  end
end

.behaviour_infoObject

Define a behavioral specification (interface).

Parameters:

  • name (Symbol)

    the name of the behavior

  • functions (Hash)

    function names and their arity as key/value pairs



14
15
16
17
# File 'lib/functional/behavior.rb', line 14

def behavior_info(name, functions = {})
  $__behavior_info__ ||= {}
  $__behavior_info__[name.to_sym] = functions.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
end

.delta(v1, v2) {|item| ... } ⇒ Float

Compute the difference (delta) between two values.

When a block is given the block will be applied to both arguments. Using a block in this way allows computation against a specific field in a data set of hashes or objects.

Parameters:

  • v1 (Object)

    the first value

  • v2 (Object)

    the second value

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • item

    each element in the data set

Returns:

  • (Float)

    positive value representing the difference between the two parameters



22
23
24
25
26
27
28
# File 'lib/functional/utilities.rb', line 22

def delta(v1, v2)
  if block_given?
    v1 = yield(v1)
    v2 = yield(v2)
  end
  return (v1 - v2).abs
end

.interfaceObject

Define a behavioral specification (interface).

Parameters:

  • name (Symbol)

    the name of the behavior

  • functions (Hash)

    function names and their arity as key/value pairs



15
16
17
18
# File 'lib/functional/behavior.rb', line 15

def behavior_info(name, functions = {})
  $__behavior_info__ ||= {}
  $__behavior_info__[name.to_sym] = functions.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
end

.object_countsObject



146
147
148
149
150
151
152
# File 'lib/functional/utilities.rb', line 146

def object_counts # :nodoc:
  counts = Hash.new{ 0 }
  ObjectSpace.each_object do |obj|
    counts[obj.class] += 1
  end
  return counts
end

.pp_s(*objs) ⇒ Object



157
158
159
160
161
162
163
164
# File 'lib/functional/utilities.rb', line 157

def pp_s(*objs) # :nodoc:
  s = StringIO.new
  objs.each {|obj|
    PP.pp(obj, s)
  }
  s.rewind
  s.read
end

.repeatedly(count, initial = nil) {|previous| ... } ⇒ Array

Perform an operation numerous times, passing the value of the previous iteration, and collecting the results into an array.

Parameters:

  • count (Integer)

    the number of times to perform the operation

  • initial (Object) (defaults to: nil)

    the initial value to pass to the first iteration

Yields:

  • iterates over each element in the data set

Yield Parameters:

  • previous

    the initial value (or nil) for the first iteration then the value of the previous iteration for all subsequent iterations

Returns:

  • (Array)

    the results of the iterations collected into an array



43
44
45
46
47
48
49
# File 'lib/functional/utilities.rb', line 43

def repeatedly(count, initial = nil)
  return [] if (count = count.to_i) == 0
  return count.times.collect{ nil } unless block_given?
  return count.times.collect do
    initial = yield(initial)
  end
end

.repl?Boolean

Returns:

  • (Boolean)


168
169
170
# File 'lib/functional/utilities.rb', line 168

def repl? # :nodoc:
  return ($0 == 'irb' || $0 == 'pry' || $0 == 'script/rails' || !!($0 =~ /bin\/bundle$/))
end

.retro(tries, *args) { ... } ⇒ Boolean

Try an operation. If it fails (raises an exception), wait a second and try again. Try no more than the given number of times.

Parameters:

  • tries (Integer)

    The maximum number of times to attempt the operation.

  • args (Array)

    Optional block arguments

Yields:

  • Tries the given block operation

Returns:

  • (Boolean)

    true if the operation succeeds on any attempt, false if none of the attempts are successful



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/functional/utilities.rb', line 62

def retro(tries, *args)
  tries = tries.to_i
  return false if tries == 0 || ! block_given?
  yield(*args)
  return true
rescue Exception
  sleep(1)
  if (tries = tries - 1) > 0
    retry
  else
    return false
  end
end

.safe(*args) ⇒ Object

Sandbox the given operation at a high $SAFE level.

Parameters:

  • args (Array)

    zero or more arguments to pass to the block

Returns:

  • (Object)

    the result of the block operation

Raises:

  • (ArgumentError)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/functional/utilities.rb', line 82

def safe(*args)
  raise ArgumentError.new('no block given') unless block_given?
  if RbConfig::CONFIG['ruby_install_name'] =~ /^ruby$/i
    result = nil
    t = Thread.new do
      $SAFE = 3
      result = yield(*args)
    end
    t.join
    return result
  else
    return yield(*args)
  end
end

.slurp(file) ⇒ String

Open a file, read it, close the file, and return its contents.

Parameters:

  • file (String)

    path to and name of the file to open

Returns:

  • (String)

    file contents

See Also:



105
106
107
# File 'lib/functional/utilities.rb', line 105

def slurp(file)
  File.open(file, 'rb') {|f| f.read }
end

.slurpee(file, safe_level = nil) ⇒ String

Open a file, read it, close the file, run the contents through the ERB parser, and return updated contents.

Parameters:

  • file (String)

    path to and name of the file to open

  • safe_level (Integer) (defaults to: nil)

    when not nil, ERB will $SAFE set to this

Returns:

  • (String)

    file contents

See Also:



119
120
121
# File 'lib/functional/utilities.rb', line 119

def slurpee(file, safe_level = nil)
  ERB.new(slurp(file), safe_level).result
end

.strftimer(seconds) ⇒ Object



174
175
176
# File 'lib/functional/utilities.rb', line 174

def strftimer(seconds) # :nodoc:
  Time.at(seconds).gmtime.strftime('%R:%S.%L')
end

.timer(*args) ⇒ Integer, Object

Run the given block and time how long it takes in seconds. All arguments will be passed to the block. The function will return two values. The first value will be the duration of the timer in seconds. The second return value will be the result of the block.

Parameters:

  • args (Array)

    zero or more arguments to pass to the block

Returns:

  • (Integer, Object)

    the duration of the operation in seconds and the result of the block operation



133
134
135
136
137
138
139
# File 'lib/functional/utilities.rb', line 133

def timer(*args)
  return 0,nil unless block_given?
  t1 = Time.now
  result = yield(*args)
  t2 = Time.now
  return (t2 - t1), result
end

.write_object_counts(name = 'ruby') ⇒ Object



184
185
186
187
# File 'lib/functional/utilities.rb', line 184

def write_object_counts(name = 'ruby')
  file = "#{name}_#{Time.now.to_i}.txt"
  File.open(file, 'w') {|f| f.write(pp_s(object_counts)) }
end

Instance Method Details

#timestampObject



180
181
182
# File 'lib/functional/utilities.rb', line 180

def timestamp # :nodoc:
  return Time.now.getutc.to_i
end