Module: Kernel

Defined in:
lib/more/facets/basicobject.rb,
lib/more/facets/cut.rb,
lib/more/facets/lazy.rb,
lib/more/facets/yaml.rb,
lib/more/facets/timer.rb,
lib/more/facets/random.rb,
lib/core/facets/boolean.rb,
lib/core/facets/proc/fn.rb,
lib/more/facets/capsule.rb,
lib/more/facets/memoize.rb,
lib/more/facets/behavior.rb,
lib/more/facets/daemonize.rb,
lib/more/facets/eventhook.rb,
lib/more/facets/interface.rb,
lib/more/facets/nackclass.rb,
lib/more/facets/nullclass.rb,
lib/more/facets/prototype.rb,
lib/more/facets/reference.rb,
lib/core/facets/kernel/ask.rb,
lib/core/facets/kernel/dir.rb,
lib/core/facets/kernel/tap.rb,
lib/core/facets/kernel/val.rb,
lib/more/facets/autoreload.rb,
lib/more/facets/reflection.rb,
lib/core/facets/kernel/ergo.rb,
lib/more/facets/association.rb,
lib/core/facets/binding/here.rb,
lib/core/facets/kernel/super.rb,
lib/core/facets/kernel/metaid.rb,
lib/core/facets/kernel/object.rb,
lib/core/facets/kernel/op_esc.rb,
lib/core/facets/kernel/report.rb,
lib/core/facets/string/regesc.rb,
lib/core/facets/1stclassmethod.rb,
lib/core/facets/kernel/require.rb,
lib/core/facets/kernel/respond.rb,
lib/core/facets/kernel/silence.rb,
lib/core/facets/module/include.rb,
lib/core/facets/integer/bitmask.rb,
lib/core/facets/kernel/constant.rb,
lib/core/facets/kernel/deepcopy.rb,
lib/core/facets/kernel/instance.rb,
lib/core/facets/kernel/populate.rb,
lib/core/facets/kernel/callstack.rb,
lib/core/facets/kernel/returning.rb

Overview

TITLE:

Verbosity Reporting Extensions

DESCRIPTION:

Kernel extensions dealing with verbosity of warnings
and error messages.

AUTHORS:

- David Heinemeier Hansson
- TransSilentNight

LOG:

- trans 07.09.01 Deprecated #silently as alias of slience_warnings.

Constant Summary collapse

ASSOCIATIONS =
Hash.new{ |h,k,v| h[k]=[] }
OPERATORS =
%w{ +@ -@ + - ** * / % ~ <=> << >> < > === == =~ <= >= | & ^ []= [] }
OPERATORS_REGEXP =
Regexp.new( '(' << OPERATORS.collect{ |k| Regexp.escape(k) }.join('|') << ')' )
OPERATORS_ESC_TABLE =
{
    "+@"   => "op_plus_self",
    "-@"   => "op_minus_self",
    "+"    => "op_plus",
    "-"    => "op_minus",
    "**"   => "op_pow",
    "*"    => "op_mul",
    "/"    => "op_div",
    "%"    => "op_mod",
    "~"    => "op_tilde",
    "<=>"  => "op_cmp",
    "<<"   => "op_lshift",
    ">>"   => "op_rshift",
    "<"    => "op_lt",
    ">"    => "op_gt",
    "==="  => "op_case_eq",
    "=="   => "op_equal",
    "=~"   => "op_apply",
    "<="   => "op_lt_eq",
    ">="   => "op_gt_eq",
    "|"    => "op_or",
    "&"    => "op_and",
    "^"    => "op_xor",
    "[]="  => "op_store",
    "[]"   => "op_fetch"
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.ask(question, answers = nil) ⇒ Object

Very simple convenience method to get a console reply.

ask "Are you happy?", "Yn"

On the command line one would see.

$ Are you happy? [Yn]

Responding:

$ Are you happy? [Yn] Y <ENTER>

The ask method would return “Y”.



19
20
21
22
23
24
# File 'lib/core/facets/kernel/ask.rb', line 19

def ask(question, answers=nil)
  print "#{question}"
  print " [#{answers}] " if answers
  until inp = $stdin.gets ; sleep 1 ; end ; puts
  inp.strip
end

.d(*x) ⇒ Object

Like #p but gives file and line number.

d("hi")

produces

/home/dave/projects/foo.rb, 38
"hi"


38
39
40
41
42
# File 'lib/core/facets/kernel/report.rb', line 38

def d(*x)
  puts "#{__FILE__}, #{__LINE__}"
  x.each{ |e| puts e.inspect } #p(*x)
  x.size > 1 ? x : x.last #x.last
end

.demo(out = $stdout, &block) ⇒ Object

For debugging and showing examples. Currently this takes an argument of a string in a block.

demo {%{ a = [1,2,3] }}
demo {%{ a.slice(1,2) }}
demo {%{ a.map { |x| x**3 } }}

Produces:

a = [1,2,3]             #=>  [1, 2, 3]
a.slice(1,2)            #=>  [2, 3]
a.map { |x| x**3 }      #=>  [1, 8, 27]

TODO: Is there a way to do this without the eval string in block?
      Preferably just a block and no string.


77
78
79
# File 'lib/core/facets/kernel/report.rb', line 77

def demo(out=$stdout,&block)
  out << sprintf("%-25s#=>  %s\n", expr = block.call, eval(expr, block.binding).inspect)
end

.enable_warningsObject

Sets $VERBOSE to true for the duration of the block and back to its original value afterwards.



61
62
63
64
65
66
# File 'lib/core/facets/kernel/silence.rb', line 61

def enable_warnings
  old_verbose, $VERBOSE = $VERBOSE, true
  yield
ensure
  $VERBOSE = old_verbose
end

.pp_exception(ex) ⇒ Object

Pretty prints an exception/error object, useful for helpfull debug messages.

Input: The Exception/StandardError object

Output: The pretty printed string.

TODO: Deprecate in favor of Exception#detail.

CREDIT: George Moschovitis


57
58
59
# File 'lib/core/facets/kernel/report.rb', line 57

def pp_exception(ex)
  return %{#{ex.message}\n  #{ex.backtrace.join("\n  ")}\n  LOGGED FROM: #{caller[0]}}
end

.silence_stderrObject

For compatibility.



39
40
41
# File 'lib/core/facets/kernel/silence.rb', line 39

def silence_stderr #:nodoc:
  silence_stream(STDERR) { yield }
end

.silence_stream(stream) ⇒ Object

Silences any stream for the duration of the block.

silence_stream(STDOUT) do
  puts 'This will never be seen'
end

puts 'But this will'

CREDIT: David Heinemeier Hansson


28
29
30
31
32
33
34
35
# File 'lib/core/facets/kernel/silence.rb', line 28

def silence_stream(stream)
  old_stream = stream.dup
  stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
  stream.sync = true
  yield
ensure
  stream.reopen(old_stream)
end

.silence_warningsObject

Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.

silence_warnings do
  value = noisy_call # no warning voiced
end

noisy_call  # no warning is voiced


52
53
54
55
56
57
# File 'lib/core/facets/kernel/silence.rb', line 52

def silence_warnings
  old_verbose, $VERBOSE = $VERBOSE, nil
  yield
ensure
  $VERBOSE = old_verbose
end

.suppress(*exception_classes) ⇒ Object

Supress errors while executing a block, with execptions.

CREDIT: David Heinemeier Hansson


72
73
74
75
76
77
# File 'lib/core/facets/kernel/silence.rb', line 72

def suppress(*exception_classes)
  begin yield
  rescue Exception => e
    raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
  end
end

.warn_with_line(msg = "", fulltrace = nil) ⇒ Object

Like #warn produces the current line number as well.

warn_with_line("You have been warned.")

produces

3: Warning: You have been warned.

Note that this method depends on the output of #caller.



91
92
93
94
95
96
# File 'lib/core/facets/kernel/report.rb', line 91

def warn_with_line(msg="", fulltrace=nil)
  trace = caller(1)
  where = trace[0].sub(/:in.*/,'')
  STDERR.puts "#{where}: Warning: #{msg}"
  STDERR.puts trace.map { |t| "\tfrom #{t}" } if fulltrace
end

Instance Method Details

#>>(to) ⇒ Object

Define an association with self.



116
117
118
119
# File 'lib/more/facets/association.rb', line 116

def >>(to)
  ASSOCIATIONS[self] << to
  Association.new(self, to)
end

#__assign__(name, value) ⇒ Object

Universal assignment. This is a meta-programming method, which allows you to assign any type of variable.

CREDIT: Trans


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/core/facets/kernel/metaid.rb', line 131

def __assign__(name, value)
  k = name.to_s
  v = value
  /^([@$]{0,2})/ =~ k
  case $1
  when '$', '@@'
    instance_eval %Q{ #{k} = v }
  when '@'
    instance_variable_set( k, v )
  else
    return __send__( "#{k}=", v ) if respond_to?("#{k}=")
    # No accessor? What to do? Assume instance var, or error? ...
    self.instance_variable_set( "@#{k}", v )
  end
  return value
end

#__real__Object

Returns a Functor that allows one to call any Kernel or Object method bound to self, making it possible to bypass overrides of Kernel and Object methods.

class A
  def object_id ; "OBTUSE" ; end
end

c = C.new
c.object_id         #=> "OBTUSE"
c.__real__.object_id    #=> 6664875832

NOTE: This has been through a couple of renamings, including #__object__, #__self__, and #self.



41
42
43
44
45
# File 'lib/core/facets/kernel/super.rb', line 41

def __real__
  @__real__ ||= Functor.new do |meth, *args|  # &blk|
    Object.instance_method(meth).bind(self).call(*args) # ,&blk)
  end
end

#as(ancestor, &blk) ⇒ Object

Returns a As-functor that allows one to call any ancestor’s method directly of the given object.

class A
  def x ; 1 ; end
end

class B < A
  def x ; 2 ; end
end

class C < B
  def x ; as(A).x ; end
end

C.new.x  #=> 1


64
65
66
67
68
69
70
71
72
# File 'lib/core/facets/kernel/super.rb', line 64

def as(ancestor, &blk)
  @__as ||= {}
  unless r = @__as[ancestor]
    r = (@__as[ancestor] = As.new(self, ancestor))
  end
  r.instance_eval(&blk) if block_given?
  #yield(r) if block_given?
  r
end

#assign_from(*args) ⇒ Object

For backward compatability (TO BE DEPRECATED).



104
105
106
107
# File 'lib/core/facets/kernel/instance.rb', line 104

def assign_from(*args)
  warn "use instance_assume for a future version"
  instance_assume(*args)
end

#associationsObject



121
122
123
# File 'lib/more/facets/association.rb', line 121

def associations
  ASSOCIATIONS[self]
end

#autoimport(mod, file) ⇒ Object

Calls Object.autoimport



250
251
252
# File 'lib/more/facets/capsule.rb', line 250

def autoimport(mod, file)
  Object.autoimport(mod, file)
end

#autoreload(*args) ⇒ Object

Autoreload feature files.

Automatically reload, at regular intervals, any previously loaded features, and/or other files not already loaded, if they have been modified since the last interval check. A numeric parameter sets the reload interval in seconds and the file parameter can either be a glob string or an array of file paths. If a glob string, it is expanded only once on the initial method call. Supplying a boolean parameter of ‘false’ will force autreload to skip previously loaded features and only reload the specified files. Also keeps a “dirty” flag.



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
75
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
# File 'lib/more/facets/autoreload.rb', line 43

def autoreload( *args )

  check_interval=10
  include_features = true
  files = nil

  args.each do |arg|
    case arg
    when Numeric
      check_interval = arg
    when String
      files = Dir.glob( arg )
    when Array
      files = arg
    when TrueClass, FalseClass
      include_features = arg
    end
  end

  file_mtime = {}

  Thread.new(Time.now) do |start_time|
    loop do
      sleep check_interval

      if include_features
        feature_files = $LOADED_FEATURES.collect { |feature|
          $LOAD_PATH.each { |lp| file = File.join(lp, feature) }
        }.flatten

        feature_files.each { |file|
          if File.exists?(file) and (mtime = File.stat(file).mtime) > (file_mtime[file] || start_time)
            $autoreload_dirty = true
            file_mtime[file] = mtime
            STDERR.puts "File '#{ file }' reloaded"
            begin
              load(file)
            rescue Exception => e
              STDERR.puts e.inspect
            end
          end
        }
      end

      if files
        files.each do |file|
          if File.exists?(file) and (mtime = File.stat(file).mtime) > (file_mtime[file] || start_time)
            $autoreload_dirty = true
            file_mtime[file] = mtime
            STDERR.puts "File '#{ file }' changed"
          end
        end
      end

    end
  end

end

#autoreload_files(*args) ⇒ Object

Same as #autoreload, but does not include previously loaded features. This is equivalent to as adding a ‘false’ parameter to #autoreload.



105
106
107
# File 'lib/more/facets/autoreload.rb', line 105

def autoreload_files( *args )
  autoreload( false, *args )
end

#autoreload_glob(*args) ⇒ Object

deprecate



110
111
112
113
# File 'lib/more/facets/autoreload.rb', line 110

def autoreload_glob(*args)
  warn "autoreload_glob will be deprecated. Use autoreload_files instead."
  autoreload_files(*args)
end

#behaving(behavior, &body) ⇒ Object



56
57
58
59
60
61
# File 'lib/more/facets/behavior.rb', line 56

def behaving(behavior, &body)
  unless @_behaviors
    extend(@_behaviors = Behavior.new)
  end
  @_behaviors.define(behavior, &body)
end

#Bit(n) ⇒ Object

Create a single bit bitmask.

Bit(0)  #=> 1
Bit(1)  #=> 2
Bit(2)  #=> 4

This is equivalent to n-shift: “1 << n”.

CREDIT: Thomas Sawyer
CREDIT: George Moschovitis


100
101
102
# File 'lib/core/facets/integer/bitmask.rb', line 100

def Bit(n)
  1 << Integer(n)
end

#bool?Boolean

Returns true is an object is class TrueClass or FalseClass, otherwise false.

true.bool?   #=> true
false.bool?  #=> true
nil.bool?    #=> false

Returns:

  • (Boolean)


132
133
134
# File 'lib/core/facets/boolean.rb', line 132

def bool?
  (true == self or false == self)
end

#cache(m = nil) ⇒ Object

Object#cache is essentially like Module#memoize except it can also be used on singleton/eigen methods. OTOH, memoize’s implementation is arguably better for it’s use of #bind instead of #alias. Eventually the two implmenations will be reconciled with a single implmentation.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/more/facets/memoize.rb', line 91

def cache m = nil
  if m
    (Module === self ? self : (class << self; self; end)).module_eval <<-code
      alias_method '__#{ m }__', '#{ m }'
      def #{ m }(*__a__,&__b__)
        c = cache['#{ m }']
        k = [__a__,__b__]
        if c.has_key? k
          c[k]
        else
          c[k] = __#{ m }__(*__a__,&__b__)
        end
      end
    code
  end
  @cache ||= Hash::new{|h,k| h[k]={}}
end

#call_stack(level = 1) ⇒ Object

Parse a caller string and break it into its components, returning an array. Returns:

  • file (String)

  • lineno (Integer)

  • method (Symbol)

For example, from irb,

call_stack(1)

produces

[[“(irb)”, 2, :irb_binding],

["/usr/lib/ruby/1.8/irb/workspace.rb", 52, :irb_binding],
["/usr/lib/ruby/1.8/irb/workspace.rb", 52, nil]]

Note: If the user decides to redefine caller() to output data in a different format, prior to requiring this, then the results will be indeterminate.

CREDIT: Trans


32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/core/facets/kernel/callstack.rb', line 32

def call_stack( level = 1 )
  call_str_array = pp_call_stack(level)
  stack = []
  call_str_array.each{ |call_str|
    file, lineno, method = call_str.split(':')
    if method =~ /in `(.*)'/ then
      method = $1.intern()
    end
    stack << [file, lineno.to_i, method]
  }
  stack
end

#completeObject

Repeat loop until it yeilds false or nil.

 a = [3, 2, 1]
 complete do
   b << a.pop
 end
 b  #=> [3, 2, 1, nil]

CREDIT: Trans


46
47
48
# File 'lib/core/facets/kernel/returning.rb', line 46

def complete
  loop { break unless yield }
end

#constant(const) ⇒ Object

This is similar to Module#const_get but is accessible at all levels, and, unlike const_get, can handle module hierarchy.

constant("Fixnum")                  # -> Fixnum
constant(:Fixnum)                   # -> Fixnum

constant("Process::Sys")            # -> Process::Sys
constant("Regexp::MULTILINE")       # -> 4

require 'test/unit'
Test.constant("Unit::Assertions")   # -> Test::Unit::Assertions
Test.constant("::Test::Unit")       # -> Test::Unit

CREDIT: Trans


18
19
20
21
22
# File 'lib/core/facets/kernel/constant.rb', line 18

def constant(const)
  const = const.to_s.dup
  base = const.sub!(/^::/, '') ? Object : ( self.kind_of?(Module) ? self : self.class )
  const.split(/::/).inject(base){ |mod, name| mod.const_get(name) }
end

#copyObject Also known as: deep_copy

Anything that can be marshaled can be copied in totality. This is also commonly called a deep_copy.

"ABC".copy  #=> "ABC"


8
9
10
# File 'lib/core/facets/kernel/deepcopy.rb', line 8

def copy
  Marshal::load(Marshal::dump(self))
end

#cut(klass, &block) ⇒ Object

Cut convienence method.



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/more/facets/cut.rb', line 172

def cut(klass, &block)
  case klass
  when Array
    name, klass = *klass
  else
    name = nil
  end

  cut = Cut.new(klass, &block)

  # How to handle main, but not other instance spaces?
  #klass.modspace::const_set(klass.basename, cut)
  mod = (Module === self ? self : Object)
  mod.const_set(cutname, cut)  # <<- this is what we don't have in Cut.new

  return cut
end

#daemonizeObject

Turns the current script into a daemon process that detaches from the console. It can be shut down with a TERM signal.



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/more/facets/daemonize.rb', line 38

def daemonize
  exit if fork                   # Parent exits, child continues.
  Process.setsid                 # Become session leader.
  exit if fork                   # Zap session leader. See [1].
  Dir.chdir "/"                  # Release old working directory.
  File.umask 0000                # Ensure sensible umask. Adjust as needed.
  STDIN.reopen "/dev/null"       # Free file descriptors and
  STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
  STDERR.reopen STDOUT           # STDOUT/ERR should better go to a logfile.
  trap("TERM") { exit }
end

#deep_clone(obj = self, cloned = {}) ⇒ Object

Adds deep_clone method to an object which produces deep copy of it. It means if you clone a Hash, every nested items and their nested items will be cloned. Moreover deep_clone checks if the object is already cloned to prevent endless recursion.

obj = []
a = [ true, false, obj ]
b = a.deep_clone
obj.push( 'foo' )
p obj   # >> [ 'foo' ]
p b[2]  # >> []

CREDIT: Jan Molic


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
# File 'lib/core/facets/kernel/deepcopy.rb', line 27

def deep_clone( obj=self, cloned={} )
  if cloned.has_key?( obj.object_id )
    return cloned[obj.object_id]
  else
    begin
      cl = obj.clone
    rescue Exception
      # unclonnable (TrueClass, Fixnum, ...)
      cloned[obj.object_id] = obj
      return obj
    else
      cloned[obj.object_id] = cl
      cloned[cl.object_id] = cl
      if cl.is_a?( Hash )
        cl.clone.each { |k,v|
          cl[k] = deep_clone( v, cloned )
        }
      elsif cl.is_a?( Array )
        cl.collect! { |v|
                deep_clone( v, cloned )
        }
      end
      cl.instance_variables.each do |var|
        v = cl.instance_eval( var )
        v_cl = deep_clone( v, cloned )
        cl.instance_eval( "#{var} = v_cl" )
      end
      return cl
    end
  end
end

#demand(promise) ⇒ Object

Forces the result of a promise to be computed (if necessary) and returns the bare result object. Once evaluated, the result of the promise will be cached. Nested promises will be evaluated together, until the first non-promise result.

If called on a value that is not a promise, it will simply return it.



226
227
228
229
230
231
232
# File 'lib/more/facets/lazy.rb', line 226

def demand( promise )
  if promise.respond_to? :__result__
    promise.__result__
  else # not really a promise
    promise
  end
end

#eigenclassObject

During this trying time when no one can get their techie catchwords to stick to the refrigerator no matter how hard they slap it # with the enchanted magnetic spatula, it’s good to know that the contrived phrases really do fly, graceful and unclasped and bearing north toward chilled shrimp. I know what my Hallowe’en pumpkin is going to say.

                    -- why the lucky stiff

CREDIT: WhyTheLuckyStiff


88
89
90
# File 'lib/core/facets/kernel/metaid.rb', line 88

def eigenclass
  (class << self; self; end)
end

#ergo(&b) ⇒ Object

Yield self -or- return self.

"a".ergo.upcase #=> "A"
nil.ergo.foobar #=> nil

"a".ergo{ |o| o.upcase } #=> "A"
nil.ergo{ |o| o.foobar } #=> nil

This is like #tap, but tap yields self -and- returns self.

CREDIT: Daniel DeLorme


17
18
19
20
21
22
23
# File 'lib/core/facets/kernel/ergo.rb', line 17

def ergo &b
  if block_given?
    b.arity == 1 ? yield(self) : instance_eval(&b)
  else
    self
  end
end

#event(sym) ⇒ Object



73
74
75
76
77
78
# File 'lib/more/facets/eventhook.rb', line 73

def event(sym)
  if $!.name == sym
    yield
    $!.call
  end
end

#false?Boolean

Returns true is an object is class FalseClass, otherwise false.

true.false?   #=> false
false.false?  #=> true
nil.false?    #=> false

Returns:

  • (Boolean)


121
122
123
# File 'lib/core/facets/boolean.rb', line 121

def false?
  (false == self)
end

#future(&computation) ⇒ Object

Schedules a computation to be run asynchronously in a background thread and returns a promise for its result. An attempt to demand the result of the promise will block until the computation finishes.

As with Kernel.promise, this passes the block a promise for its own result. Use wisely.



241
242
243
# File 'lib/more/facets/lazy.rb', line 241

def future( &computation ) #:yields: result
  Lazy::Future.new(&computation)
end

#hook(sym) ⇒ Object



70
71
72
# File 'lib/more/facets/eventhook.rb', line 70

def hook(sym)
  callcc{ |c| raise EventHook.new(sym, c) }
end

#in?(other) ⇒ Boolean

Is self included in other?

5.in?(0..10)       #=> true
5.in?([0,1,2,3])   #=> false

Returns:

  • (Boolean)


36
37
38
# File 'lib/core/facets/kernel/val.rb', line 36

def in?(other)
  other.include?(self)
end

#instanceObject



99
100
101
# File 'lib/more/facets/reflection.rb', line 99

def instance
  @_instance_reflection ||= InstanceReflection.new(self)
end

#instance_assign(*args) ⇒ Object Also known as: assign_with

Set instance variables using a hash (or assoc array).

instance_assign('@a'=>1, '@b'=>2)
@a   #=> 1
@b   #=> 2

– TODO: Make a little more flexiable to allow any hash-like object. TODO: Should is also accept class variables? (eg. @@a) TODO: Should instance_assign be named instance_variable_assign?

Likewise for instance_assume. Is there a better term than 'assume'?

++



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/core/facets/kernel/instance.rb', line 145

def instance_assign(*args)
  harg = args.last.is_a?(Hash) ? args.pop : {}

  unless args.empty?
    # if not assoc array, eg. [ [], [], ... ]
    # preserves order of opertation
    unless args[0].is_a?(Array)
      i = 0; a = []
      while i < args.size
        a << [ args[i], args[i+1] ]
        i += 2
      end
      args = a
    end
  end

  args.each do |k,v|
    k = "@#{k}" if k !~ /^@/
    instance_variable_set(k, v)
  end

  harg.each do |k,v|
    k = "@#{k}" if k !~ /^@/
    instance_variable_set(k, v)
  end

  return self
end

#instance_assume(obj, *vars) ⇒ Object Also known as: __assume__

Assign instance vars using another object.

class O
  attr_accessor :d
  def initialize( a, b, c, d)
    @a = a
    @b = b
    @c = c
    @d = d
  end
end
o1 = O.new(1,2,3,4)
o2 = O.new(0,0,0,0)

o2.instance_assume( o1, '@a', '@b', '@c', '@d' )
o2.instance_eval{ @a }  #=> 1
o2.instance_eval{ @b }  #=> 2
o2.instance_eval{ @c }  #=> 3
o2.instance_eval{ @d }  #=> 4

CREDIT: Trans


87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/core/facets/kernel/instance.rb', line 87

def instance_assume(obj, *vars)
  if vars.empty?
    vars = instance_vars | obj.instance_variables
  else
    vars = vars.collect do |k|
      var.to_s.slice(0,1) == '@' ? var : "@#{var}"
    end
    vars = vars | instance_variables | obj.instance_variables
  end
  vars.each do |var|
    instance_variable_set(var, obj.instance_variable_get(var))
  end
  return self  # ???
end

#instance_assume!(obj, *vars) ⇒ Object

As with #instance_assume, but forces the setting of the object’s instance varaibles even if the reciever doesn’t have them defined.

See #instance_assume.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/core/facets/kernel/instance.rb', line 114

def instance_assume!(obj, *vars)
  if vars.empty?
    vars = obj.instance_variables
  else
    vars = vars.collect do |k|
      var.to_s.slice(0,1) == '@' ? var : "@#{var}"
    end
    vars = vars | obj.instance_variables
  end
  vars.each do |var|
    instance_variable_set(var, obj.instance_variable_get(var))
  end
  return self  # ???
end

#instance_class(&block) ⇒ Object

Easy access to an object qua class, otherwise known as the object’s metaclass or singleton class. This implemnetation alwasy returns the class, even if a block is provided to eval against it.

   It is what it is.

CREDIT: Trans


39
40
41
42
# File 'lib/core/facets/kernel/instance.rb', line 39

def instance_class( &block )
  (class << self; self; end).module_eval(&block) if block
  (class << self; self; end)
end

#instance_exec(*arguments, &block) ⇒ Object

Like instance_eval but allows parameters to be passed.

TODO: Remove for Ruby 1.9.


16
17
18
# File 'lib/core/facets/kernel/instance.rb', line 16

def instance_exec(*arguments, &block)
  block.bind(self)[*arguments]
end

#instance_valuesObject

Return instance variable values in an array.

class X
  def initialize(a,b)
    @a, @b = a, b
  end
end

x = X.new(1,2)

x.instance_values   #=> [1,2]

CREDIT: David Heinemeier Hansson


58
59
60
61
62
63
# File 'lib/core/facets/kernel/instance.rb', line 58

def instance_values
  instance_variables.inject({}) do |values, name|
  values[name[1..-1]] = instance_variable_get(name)
    values
  end
end

#interface(*args) ⇒ Object

Returns a list of methods according to symbol(s) given.

Usable symbols include:

  • :inherited or :ancestors

  • :local or :no_ancestors

  • :public

  • :private

  • :protected

  • :singleton

  • :all

It no symbol is given then :public is assumed. Unrecognized symbols raise an error.

def test
  puts("Hello World!")
end

methods(:local)    #=> ['test']


216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/more/facets/interface.rb', line 216

def interface(*args)
  args = [ :public, :local, :ancestors, :singleton ] if args.empty?
  sing = args.delete(:singleton) or args.include?(:all)
  if sing
    if args.empty?
      singleton_methods
    else
      singleton_methods | self.class.instance_interface(*args)
    end
  else
     self.class.instance_interface(*args)
  end
end

#maybe(chance = 0.5, &block) ⇒ Object

Random generator that returns true or false. Can also take a block that has a 50/50 chance to being executed.

maybe  #=> true
maybe  #=> false


41
42
43
44
45
46
47
# File 'lib/more/facets/random.rb', line 41

def maybe(chance = 0.5, &block)
  if block then
    yield if rand < chance
  else
    rand < chance
  end
end

#metaObject

Provides access to an object’s metaclass (ie. singleton) by-passsing access provisions. So for example:

 class X
   meta.attr_accesser :a
 end

 X.a = 1
 X.a #=> 1

CREDIT: Trans


17
18
19
20
21
# File 'lib/core/facets/kernel/metaid.rb', line 17

def meta
  @_meta_functor ||= Functor.new do |op,*args|
    (class << self; self; end).send(op,*args)
  end
end

#meta_alias(*args) ⇒ Object

Alias a method defined in the metaclass (ie. singleton class).

def X.y?; "y?" ; end
X.meta_alias "ynot?", "y?"
X.ynot?  #=> y?

CREDIT: Trans


31
32
33
34
35
# File 'lib/core/facets/kernel/metaid.rb', line 31

def meta_alias(*args)
  meta_class do
    alias_method(*args)
  end
end

#meta_class(&block) ⇒ Object Also known as: metaclass

Easy access to an object’s “special” class, otherwise known as it’s metaclass or singleton class.



67
68
69
70
71
72
73
# File 'lib/core/facets/kernel/metaid.rb', line 67

def meta_class(&block)
  if block_given?
    (class << self; self; end).class_eval(&block)
  else
    (class << self; self; end)
  end
end

#meta_def(name, &block) ⇒ Object

Add method to a meta-class –i.e. a singleton method.

class X; end
X.meta_def(:x){"x"}
X.x  #=> "x"

CREDIT: WhyTheLuckyStiff


58
59
60
61
62
# File 'lib/core/facets/kernel/metaid.rb', line 58

def meta_def( name, &block )
  meta_class do
    define_method( name, &block )
  end
end

#meta_eval(str = nil, &blk) ⇒ Object

Evaluate code in a metaclass. This is equivalent to ‘meta_class.instance_eval’.

CREDIT: WhyTheLuckyStiff


42
43
44
45
46
47
48
# File 'lib/core/facets/kernel/metaid.rb', line 42

def meta_eval(str=nil, &blk)
  if str
    meta_class.instance_eval(str)
  else
    meta_class.instance_eval(&blk)
  end
end

#method!(s) ⇒ Object

Easy access to method as objects, and they retain state!

def hello
  puts "Hello World!"
end

m1 = method!(:hello)   #=> <Method: #hello>

def m1.annotate
  "simple example"
end

m2 = method!(:hello)
m2.annotate  #=> "simple example"


71
72
73
# File 'lib/core/facets/1stclassmethod.rb', line 71

def method!(s)
  ( @__methods__ ||= {} )[s] ||= method(s)
end

#nackObject

This is a light version of NackClass intended for minor usecases. See mega/nack for a complete version.



40
41
42
# File 'lib/more/facets/nackclass.rb', line 40

def nack
  NackClass.new
end

#new(o = nil) ⇒ Object

Synonymous with #clone, this is an interesting method in that it promotes prototype-based Ruby. Now Classes aren’t the only things that respond to #new.

"ABC".new  => "ABC"


84
85
86
87
# File 'lib/more/facets/prototype.rb', line 84

def new(o=nil)
  return o.clone if o
  return clone
end

#not_nil?Boolean Also known as: non_nil?

The opposite of #nil?.

"hello".not_nil?     # -> true
nil.not_nil?         # -> false

CREDIT: Gavin Sinclair

Returns:

  • (Boolean)


25
26
27
# File 'lib/core/facets/kernel/val.rb', line 25

def not_nil?
  not nil?
end

#nullObject



56
57
58
# File 'lib/more/facets/nullclass.rb', line 56

def null
  NullClass.new
end

#objectObject



95
96
97
# File 'lib/more/facets/reflection.rb', line 95

def object
  @_object_reflection ||= ObjectReflection.new(self)
end

#object_hexidObject

Returns the object id as a string in hexideciaml, which is how Ruby reports them with inspect.

"ABC".object_hexid  #=> "0x402d359c"


32
33
34
# File 'lib/core/facets/kernel/object.rb', line 32

def object_hexid
  return "0x" << ('%.x' % (2*self.__id__))[1..-1]
end

#object_send(name, *args, &blk) ⇒ Object

Send only to public methods.

class X
  private
  def foo; end
end

X.new.object_send(:foo)
=> NoMethodError: private method `foo' called for #<X:0xb7ac6ba8>

CREDIT: Trans

– Which implementation is faster? ++



51
52
53
54
55
56
57
58
59
60
# File 'lib/core/facets/kernel/object.rb', line 51

def object_send(name,*args,&blk)
  #instance_eval "self.#{name}(*args)"
  if respond_to?(name)
    send(name,*args,&blk)
  else #if respond_to?(:method_missing)
    method_missing(name,*args,&blk)
  #else
  #  raise NoMethodError
  end
end

#op_esc(str) ⇒ Object

Applies operator escape’s according to OPERATORS_ESCAPE_TABLE.

op_esc('-') #=> "op_minus"

CREDIT: Trans


42
43
44
# File 'lib/core/facets/kernel/op_esc.rb', line 42

def op_esc( str )
  str.gsub(OPERATORS_REGEXP){ OPERATORS_ESC_TABLE[$1] }
end

#p(*x) ⇒ Object

Alternate to standard #p method that outputs Kernel#inspect to stdout, but also passes through the orginal argument(s).

x = 1
r = 4 + q(1)
p r

produces

1
5

DEPRECATE AS OF 1.9, if #p will then do this too.



22
23
24
25
# File 'lib/core/facets/kernel/report.rb', line 22

def p(*x)
  x.each{ |e| puts e.inspect } #p(*x)
  x.size > 1 ? x : x.last #x.last
end

#populate(data = nil, &yld) ⇒ Object

Similiar to #set_with, but ignores missing setters.



23
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
# File 'lib/core/facets/kernel/populate.rb', line 23

def populate( data=nil, &yld )
  if data
    data.each do |k,v|
      send( "#{k}=", v ) rescue nil
    end
  end

  if yld
    yld.to_h.each do |k,v|
      send( "#{k}=", v ) rescue nil
    end
  end

  # If the context of the error could be known
  # this could be used instead of converting the
  # block to a hash.

  #begin
  #  yield self
  #rescue NoMethodError => e
  #  if e.context == self and e.name.to_s =~ /=$/
  #    resume
  #  else
  #    raise e
  #  end
  #end

  self
end

#promise(&computation) ⇒ Object

The promise() function is used together with demand() to implement lazy evaluation. It returns a promise to evaluate the provided block at a future time. Evaluation can be demanded and the block’s result obtained via the demand() function.

Implicit evaluation is also supported: the first message sent to it will demand evaluation, after which that message and any subsequent messages will be forwarded to the result object.

As an aid to circular programming, the block will be passed a promise for its own result when it is evaluated. Be careful not to force that promise during the computation, lest the computation diverge.



215
216
217
# File 'lib/more/facets/lazy.rb', line 215

def promise( &computation ) #:yields: result
  Lazy::Promise.new(&computation)
end

#prototype(&block) ⇒ Object



72
73
74
# File 'lib/more/facets/prototype.rb', line 72

def prototype(&block)
  Prototype.new(&block)
end

#qua_class(&block) ⇒ Object

Easy access to an object qua class, otherwise known as the object’s metaclass or singleton class.

Yes, another one.

CREDIT: Trans


118
119
120
121
122
123
124
# File 'lib/core/facets/kernel/metaid.rb', line 118

def qua_class(&block)
  if block_given?
    (class << self; self; end).class_eval(&block)
  else
    (class << self; self; end)
  end
end

#ref(x) ⇒ Object

Shortcut reference constructor.



79
80
81
# File 'lib/more/facets/reference.rb', line 79

def ref(x)
  Reference.new(x)
end

#resc(str) ⇒ Object

Provides a shortcut to the Regexp.escape module method.

resc("H..LO")   #=> "H\\.\\.LO"

TODO: Should this be deprecated in favor of String#regesc ?

CREDIT: Trans


26
27
28
# File 'lib/core/facets/string/regesc.rb', line 26

def resc(str)
  Regexp.escape(str)
end

#respond(sym, *args) ⇒ Object Also known as: respond_with_value

Like #respond_to? but returns the result of the call if it does indeed respond.

class X
  def f; "f"; end
end

x = X.new
x.respond(:f)  #=> "f"
x.respond(:g)  #=> nil

CREDIT: Trans


16
17
18
19
# File 'lib/core/facets/kernel/respond.rb', line 16

def respond(sym, *args)
  return nil if not respond_to?(sym, *args)
  send(sym, *args)
end

#returning(obj = self) {|obj| ... } ⇒ Object Also known as: with

A Ruby-ized realization of the K combinator.

returning Book.new do |book|
  book.title = "Imperium"
  book.author = "Ulick Varange"
end

Also aliased as #with.

def foo
  with values = [] do
    values << 'bar'
    values << 'baz'
  end
end

foo # => ['bar', 'baz']

Technically, #returning probably should force the return of the stated object irregardless of any return statements that might appear within it’s block. This might differentiate #returning from #with, however it also would require implementation in Ruby itself.

CREDIT: Mikael Brockman

Yields:

  • (obj)


29
30
31
32
# File 'lib/core/facets/kernel/returning.rb', line 29

def returning(obj=self)
  yield obj
  obj
end

#send_as(ancestor, sym, *args, &blk) ⇒ Object

Call parent class/module methods once bound to self.



76
77
78
# File 'lib/core/facets/kernel/super.rb', line 76

def send_as(ancestor, sym, *args, &blk)
  ancestor.instance_method(sym).bind(self).call(*args,&blk)
end

#set_from(obj, *fields) ⇒ Object

Set setter methods using a another object.

class X
  attr_accessor :a, :b
  def initialize( a, b )
     @a,@b = a,b
  end
end

obj1 = X.new( 1, 2 )
obj2 = X.new

obj2.set_from(obj1)

obj2.a  #=> 1
obj2.b  #=> 2


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/core/facets/kernel/populate.rb', line 118

def set_from(obj, *fields)
  unless fields.empty?
    fields.each do |k|
      send( "#{k}=", obj.send("#{k}") )  #if self.respond_to?("#{k}=") && obj.respond_to?("#{k}")
    end
  else
    setters = methods.collect { |m| m =~ /=$/ }
    setters.each do |setter|
      getter = setter.chomp('=')
      if obj.respond_to?(getter)
        send( setter, obj.send(getter) )
        fields < getter
      end
    end
  end
  fields
end

#set_with(*args) {|_self| ... } ⇒ Object

Assign via setter methods using a hash, associative array or block.

object.set_with( :a => 1, :b => 2 )
object.set_with( :a, 1, :b, 2 )
object.set_with( [:a, 1], [:b, 2] )
object.set_with( *[[:a, 1], [:b, 2]] )
object.set_with{ |s| s.a = 1; s.b = 2 }

These are all the same as doing:

object.a = 1
object.b = 2

The array forms gaurentees order of operation.

This method does not check to make sure the object repsonds to the setter method. For that see #populate.

Yields:

  • (_self)

Yield Parameters:

  • _self (Kernel)

    the object that the method was called on



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/core/facets/kernel/populate.rb', line 72

def set_with(*args) #:yield:
  harg = args.last.is_a?(Hash) ? args.pop : {}

  unless args.empty?
    # if not assoc array, eg. [ [], [], ... ]
    # preserves order of opertation
    unless args[0].is_a?(Array)
      i = 0; a = []
      while i < args.size
        a << [ args[i], args[i+1] ]
        i += 2
      end
      args = a
    end
  end

  args.each do |k,v|
    self.send( "#{k}=", v )
  end

  harg.each do |k,v|
    self.send( "#{k}=", v )
  end

  yield self if block_given?

  self
end

#singletonObject

Access to an object’s “special” class, otherwise known as it’s eigenclass or metaclass, etc.

One day these names must be reconciled!



97
98
99
# File 'lib/core/facets/kernel/metaid.rb', line 97

def singleton
  (class << self; self; end)
end

#singleton_classObject Also known as: __singleton_class__

Access to an object’s “special” class, otherwise known as it’s eigenclass or metaclass or own, etc.

One day these names must be reconciled!



106
107
108
# File 'lib/core/facets/kernel/metaid.rb', line 106

def singleton_class
  (class << self; self; end)
end

#super_at(klass = self.class.superclass, *args, &blk) ⇒ Object Also known as: superior

Like super but skips to a specific ancestor module or class.

class A
  def x ; 1 ; end
end

class B < A
  def x ; 2 ; end
end

class C < B
  def x ; superior(A) ; end
end

C.new.x  #=> 1


119
120
121
122
123
124
125
# File 'lib/core/facets/kernel/super.rb', line 119

def super_at(klass=self.class.superclass, *args, &blk)
  unless self.class.ancestors.include?(klass)
    raise ArgumentError
  end
  called = /\`([^\']+)\'/.match(caller(1).first)[1].to_sym
  klass.instance_method(called).bind(self).call(*args,&blk)
end

#super_method(klass, meth) ⇒ Object Also known as: supermethod

Returns method of a parent class bound to self.



132
133
134
135
136
137
# File 'lib/core/facets/kernel/super.rb', line 132

def super_method(klass, meth)
  unless self.class.ancestors.include?(klass)
    raise ArgumentError, "Not an ancestor for super_method-- #{klass}"
  end
  klass.instance_method(meth).bind(self)
end

#tap(&b) ⇒ Object

The tap K-Combinator. This yields self -and- returns self.

CREDIT: ?


10
11
12
13
14
15
# File 'lib/core/facets/kernel/tap.rb', line 10

def tap(&b)
  if block_given?
    b.arity == 1 ? yield(self) : instance_eval(&b)
  end
  self
end

#timed {|timer = Timer.new.start| ... } ⇒ Object

Takes a block and returns the total time it took to execute.

Yields:



241
242
243
244
# File 'lib/more/facets/timer.rb', line 241

def timed
  yield( timer = Timer.new.start )
  return timer.total_time
end

#to_bObject

Boolean conversion for not being nil or false. Other classes may redefine this to suite the particular need.

"abc".to_b   #=> true
true.to_b    #=> true
false.to_b   #=> false
nil.to_b     #=> false


99
100
101
# File 'lib/core/facets/boolean.rb', line 99

def to_b
  self ? true : false
end

#true?Boolean

Returns true is an object is class TrueClass, otherwise false.

true.true?   #=> true
false.true?  #=> false
nil.true?    #=> false

Returns:

  • (Boolean)


110
111
112
# File 'lib/core/facets/boolean.rb', line 110

def true?
  (true == self)
end

#val?Boolean

Tests to see if something has value. An object is considered to have value if it is not nil? and if it responds to #empty?, is not empty.

nil.val?     #=> false
[].val?      #=> false
10.val?      #=> true
[nil].val?   #=> true

Returns:

  • (Boolean)


12
13
14
15
16
# File 'lib/core/facets/kernel/val.rb', line 12

def val?
  return false if nil?
  return false if empty? if respond_to?(:empty?)
  true
end

#yaml(*args, &blk) ⇒ Object

Convenience method for loading YAML.



18
19
20
# File 'lib/more/facets/yaml.rb', line 18

def yaml(*args,&blk)
  YAML.load(*args,&blk)
end