Facets

From WhyNotWiki
(Redirected from Ruby / Facets)
Jump to: navigation, search

Ruby Facets  edit   (Category  edit)


Ruby libraries / Core  edit   (Category  edit)


Contents

General

Should it go in Kernel or Object??

In particular, I'm curious about why the following are in Kernel:

  • Kernel#meta
  • Kernel#meta_*
  • Kernel#set_with
  • Kernel#methods
  • Kernel#singleton_class
  • ...

But these are in Object...

  • Object#metaclass
  • ...

String

http://facets.rubyforge.org/src/doc/rdoc/core/classes/String.html

bracket

I probably would've called it "enclose"...

http://facets.rubyforge.org/src/doc/rdoc/core/classes/String.html#M000946

bracket(bra, ket=nil) Return a new string embraced by given brakets. If only one bracket char is given it will be placed on either side.

  "wrap me".bracket('{')        #=> "{wrap me}"
  "wrap me".bracket('--','!')   #=> "--wrap me!"

margin

...

each_char

Iterates through each character.

# File lib/facets/core/string/each_char.rb, line 5
  def each_char  # :yield:
    split(//).each { |c|
      yield( c )
    }
  end


Array

last_index

require 'lib/facets/core/array/last_index'

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Array.html#M000157

Returns the last index of the array. Returns nil is [typo?] array has no elements.

  [1,2,3,4,5].last_index  #=> 4



Enumerable

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Enumerable.html

star_full.gif star_full.gif star_full.gif every

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Enumerable.html#M001236

Returns an elementwise Functor. This allows you to map a method on to every element. [1,2,3].every + 3 #=> [4,5,6] ['a','b','c'].every.upcase #=> ['A','B','C']

# File lib/facets/core/enumerable/every.rb, line 13
  def every
    @_functor_every ||= Functor.new do |op,*args|
      self.collect{ |a| a.send(op,*args) }
    end
  end
irb -> require 'facets/core/enumerable/every'

irb -> ['dir1/', 'dir2/'].every + '..'
    => ["dir1/..", "dir2/.."]

irb -> ['dir1/', 'dir2/'].every + 'file'
    => ["dir1/file", "dir2/file"]

irb -> ['Smith', 'Reynolds'].every + ' Mr.'
    => ["Smith Mr.", "Reynolds Mr."]

irb -> class String; def prefix(prefix); prefix + self; end; end
    => nil

irb -> ['Smith', 'Reynolds'].every.prefix 'Mr. '
    => ["Mr. Smith", "Mr. Reynolds"]

# But you may as well just use the built-in map for this:
irb -> ['Smith', 'Reynolds'].map {|a| 'Mr. ' + a}
    => ["Mr. Smith", "Mr. Reynolds"]


map_send(meth, *args) {|e.send(meth, *args)| ...}

# File lib/facets/core/enumerable/map_send.rb, line 3
  def map_send(meth, *args)
    if block_given?
      map{|e| yield(e.send(meth, *args))}
    else
      map{|e| e.send(meth, *args)}
    end
  end

I don't really know when I/you would want to use this method...

irb -> require 'facets/core/enumerable/map_send'

irb -> ['dir1/', 'dir2/'].map_send(:+, 'a') {|a| File.expand_path(a)}
    => ["/home/tyler/dir1/a", "/home/tyler/dir2/a"]

# Sure, but you could have the same thing in an even more readable manner simply using map!:

irb -> ['dir1/', 'dir2/'].map {|a| File.expand_path(a + 'a')}
    => ["/home/tyler/dir1/a", "/home/tyler/dir2/a"]

each_by(step=nil, &yld)

Iterate through slices. If slicing step is not given, the the arity if the block is used.

  x = []
  [1,2,3,4].each_by{ |a,b| x << [a,b] }
  x  #=> [ [1,2], [3,4] ]

  x = []
  [1,2,3,4,5,6].each_by(3){ |a| x << a }
  x  #=> [ [1,2,3], [4,5,6] ]


filter_collect( {|| ...}

Collects/Maps and filters items out in one single step. You can use throw(:skip) in the supplied block to indicate that the current item should not end up in the resulting array. # Return names of all person with an age of at least 18. persons.filter_collect do |person| throw(:skip) if person.age < 18 person.name end


none?( {|e| ...}

Enumerable#none? is the logical opposite of the builtin method Enumerable#any?. It returns true if and only if none of the elements in the collection satisfy the predicate. If no predicate is provided, Enumerable#none? returns true if and only if none of the elements have a true value (i.e. not nil or false).

uniq_by( {|| ...}

Like uniq, but determines uniqueness based on a given block. (-5..5).to_a.uniq_by {|i| i*i } produces [-5, -4, -3, -2, -1, 0]



Kernel

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Kernel.html

__self__

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.

  require 'facets/core/kernel/__self__'

  class A
    def object_id ; "OBTUSE" ; end
  end

  c = C.new
  c.object_id             #=> "OBTUSE"
  c.__self__.object_id    #=> 6664875832
# File lib/facets/core/kernel/__self__.rb, line 24
  def __self__
    @__self__ ||= Functor.new do |meth, *args|  # &blk|
      Object.instance_method(meth).bind(self).call(*args) # ,&blk)
    end
  end

as( ancestor, &blk )

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
# File lib/facets/core/kernel/as.rb, line 39
  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


with / returning

require 'facets/core/kernel/with'       # returning

new()

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"

object_send(name,*args,&blk) star_full.gif star_full.gif star_empty.gif

Send only to public methods.

meta()

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Kernel.html#M001160

Provides access to an object’s metaclass (ie. singleton) bypassing [typo] access provisions. So for example:

  class X
    meta.attr_accesser :a
  end

  X.a = 1
  X.a #=> 1
# File lib/facets/core/kernel/meta.rb, line 15
  def meta
    @_meta_functor ||= Functor.new do |op,*args|
      (class << self; self; end).send(op,*args)
    end
  end

This apparently created an instance variable for the class object X (rather than for instances of X).

Hmm, I'm not sure I trust it very much after observing this weirdness...

> irb
irb -> require 'facets/core/kernel/meta'
    => false

irb -> o = Object.new
    => #<Object:0xb7dd2a68>

irb -> o.class.send(:class_variable_set, :@@v, 'value!')
    => "value!"

irb -> o.class
    => Object

irb -> o.class.send(:class_variable_get, :@@v)
    => "value!"

irb -> o.class.meta.class_variable_set(:@@v, 'new value')
    => "new value"

irb -> o.class.meta.class_variable_get(:@@v)
    => "new value"

irb -> o.class.send(:class_variable_get, :@@v)
    => "new value"

> irb
Welcome!
irb -> require 'facets/core/kernel/meta'
    => true

irb -> o = Object.new
    => #<Object:0xb7e71794>

irb -> o.class.meta.class_variable_set(:@@v, 'value')
    => "value"

irb -> o.class.send(:class_variable_get, :@@v)
NameError: uninitialized class variable @@v in Object
        from (irb):4:in `class_variable_get'
        from (irb):4:in `send'
        from (irb):4
        from :0
irb -> o.class.meta.class_variable_get(:@@v)
    => "value"

irb -> o.class.send(:class_variable_set, :@@v, 'new value')
    => "new value"

irb -> o.class.meta.class_variable_get(:@@v)
    => "value"

irb -> o.class.send(:class_variable_get, :@@v)
    => "new value"


pp_exception(ex)

set_with(*args) {|| ...}

require 'facets/core/kernel/set_with'

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 This method does not check to make sure the object responds [typo] to the setter method [ambiguous!]. For that see populate (which just adds rescue nil).

populate( data=nil, &yld )

Similar [typo] to set_with, but ignores missing setters [rescues errors].


Misc

Why isn't qua_class simply an alias to meta??

Object

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Object.html



Module

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Module.html

class_extension(&block)

http://facets.rubyforge.org/src/doc/rdoc/core/classes/Module.html#M000510

Normally when including modules, class/module methods are not extended. To achieve this behavior requires some clever Ruby Karate. Instead class_extension provides an easy to use and clean solution. Simply place the extending class methods in a block of the special module method class_extension.

  module Mix
    def inst_meth
      puts 'inst_meth'
    end

    class_extension do
      def class_meth
        "Class Method!"
      end
    end
  end

  class X
    include Mix
  end

  X.class_meth  #=> "Class Method!"
require 'facets/core/module/class_extension'

attr_tester(*args)

Create an "tester" attribute. This creates two methods for each given variable name. One (a?) is used to test the attribute and the other (a!) is used to set or toggle it.

Documentation revision: Add underlined.


star_full.gif star_empty.gif star_empty.gif basename() / dirname()

 module Example
   class Demo
   end
 end
 Example::Demo.name       #=> "Example::Demo"
 Example::Demo.basename   #=> "Demo"
 Example::Demo.dirname    #=> "Example"

[documentation incorrect (category)]: Doesn't work unless Example:: is added.


star_full.gif star_empty.gif star_empty.gif by_name(name)

Note: the following documentation uses "class" because it’s more common, but it applies to modules as well.

Given the name of a class, returns the class itself (i.e. instance of Class). [...]

Examples:

 Class.by_name("String")             # -> String
 Class.by_name("::String")           # -> String
 Class.by_name("Process::Sys")       # -> Process::Sys
 Class.by_name("GorillaZ")           # -> (ArgumentError)
 Class.by_name("Enumerable")         # -> Enumerable
 Module.by_name("Enumerable")        # -> Enumerable


equate_on(*fields)

Generates identity/key methods based on specified attributes.

equate_on :a, :b

_is equivalent to_

 def ==(o)
   self.a == o.a && self.b == o.b
 end
 def eql?(o)
   self.a.eql?(o.a) && self.b.eql?(o.b)
 end
 ...


include_and_extend(*mods)

Both includes and extends a module.


star_full.gif star_full.gif star_empty.gif include_as( h )

Include a module via a specified namespace.

 module T
   def t ; "HERE" ; end
 end
 class X
   include_as :test => T
   def t ; test.t ; end
 end
 X.new.t  #=> "HERE"


star_full.gif star_full.gif star_full.gif initializer(*attributes, &block)

Automatically create an initializer assigning the given arguments.

 class MyClass
   initializer(:a, "b", :c)
 end

_is equivalent to_

 class MyClass
   def initialize(a, b, c)
     @a,@b,@c = a,b,c
   end
 end

Downside: Initializers defined like this can’t take blocks. This can be fixed when Ruby 1.9 is out. [How?? You can pass multiple blocks in 1.9?????]

The initializer will not raise an Exception when the user does not supply a value for each instance variable. In that case it will just set the instance variable to nil. You can assign default values or raise an Exception in the block.

# File lib/facets/core/module/initializer.rb, line 27
  def initializer(*attributes, &block)
    define_method(:initialize) do |*args|
      attributes.zip(args) do |sym, value|
        instance_variable_set("@#{sym}", value)
      end

      instance_eval(&block) if block
    end
  end

Why would you want to pass in a block? Here's one reason: to initialize those instance variables that aren't passed in to the constructor/initialize.

    initializer :name do
      @running_total = 0
      @internal_counter = 0
      @message = ''
      ...
    end

An alternative to using initializer would be to write your own initialize(*args) but then call set_with(args)...


using block...

wrap_method( sym, &blk )/code>


Creates a new method wrapping the previous of the same name. Reference to the old method is passed into the new definition block as the first parameter.

  wrap_method( sym ) { |old_meth, *args|
    old_meth.call
    ...
  }

Keep in mind that this can not be used to wrap methods that take a block.

# File lib/facets/core/module/wrap_method.rb, line 22
  def wrap_method( sym, &blk )
    old = instance_method(sym)
    define_method(sym) { |*args| blk.call(old.bind(self), *args) }
  end



instance_methods(*args)

Provides an improved method lookup routine. It returns a list of methods according to symbol(s) given.

Recognized symbols are:

  •  :public include public methods
  •  :private include private methods
  •  :protected include protected methods
  •  :ancestors include all ancestor’s methods
  •  :inherited (same as above)
  •  :local include non-ancestor methods
  •  :all include all of the above

This method also uses the symbol-not system. So you can specify the inverse of all of the above. For instance ~:public would mean :private, :protected (see facets/core/symbol/not).

If no symbol is given then :public, :local is assumed. Unrecognized symbols raise an error.

 module Demo
   def test
     puts("Hello World!")
   end
 end
 Demo.instance_methods(:local)    #=> ['test']

To maintain backward compatibility true as an intitial argument is converted to :local, :ancestors (i.e. it includes both).


==is?(base)

Built-in: obj.is_a?(class)

Returns true if class is the class of obj, or if class is one of the superclasses of obj or modules included in obj.

Only works for instances

irb -> Y.is_a?(X)
    => false
irb -> Y.new.is_a?(X)
    => true

Facets' is? works for modules/classes as well...

irb -> require 'facets/core/module/is'
    => true

irb -> Y.is?(X)
    => true


memoize(*meths)

Directive for making your functions faster by trading space for time. When you "memoize" a method/function its results are cached so that later calls with the same arguments returns results in the cache instead of recalculating them.

 class T
   def initialize(a)
     @a = a
   end
   def a
     "#{@a ^ 3 + 4}"
   end
   memoize :a
 end
 t = T.new
 t.a.__id__ == t.a.__id__  #=> true



star_full.gif star_empty.gif star_empty.gif modspace()

Returns the module’s container module.

 module Example
   class Demo
   end
 end
 Demo.modspace    #=> Example



star_full.gif star_full.gif star_full.gif namespace( name, mod=nil, &blk )

require 'facets/core/module/namespace'

Define a simple method namespace.

 class A
   attr_writer :x
   namespace :inside do
     def x; @x; end
   end
 end
 a = A.new
 a.x = 10
 a.inside.x #=> 10
 a.x  # no method error


star_full.gif star_empty.gif star_empty.gif new(*args,&blk)

Lets you "instantiate" a module!

Never use class again! ;)

  1. File lib/facets/core/module/new.rb, line 6
 def new(*args,&blk)
   mod = self
   klass = Class.new{include mod}
   klass.new(*args,&blk)
 end

[documentation needs cleanup]: "Never you a class agian!"


on_included(code)

A useful macro for dynamic modules.

  1. File lib/facets/core/module/on_included.rb, line 11
 def on_included(code)
   tag = caller[0].split(' ').first.split(/\/|\\/).last.gsub(/:|\.|\(|\)/, '_')
   old = "__included_#{tag}"
   module_eval %{
     class << self
       alias_method :#{old}, :included
       def included(base)
         #{old}(base)
         #{code}
       end
     end
   }
 end




star_full.gif star_full.gif star_full.gif class_extension(&block)

Normally when including modules, class/module methods are not extended. To achieve this behavior requires some clever Ruby Karate. Instead class_extension provides an easy to use and clean solution. Simply place the extending class methods in a block of the special module method class_extension.

 module Mix
   def inst_meth
     puts 'inst_meth'
   end
   class_extension do
     def class_meth
       "Class Method!"
     end
   end
 end
 class X
   include Mix
 end
 X.class_meth  #=> "Class Method!"

Method dependencies

http://facets.rubyforge.org/src/doc/rdoc/more/classes/Module.html

This module is included in Object and allows methods to be given prerequisite dependencies, i.e. methods that must be run before they are. A dependency will only ever be run once per method call.

  include MethodDependency

  def one; @str << '1'; end
  def two; @str << '2'; end

  def show; @str ; end

  depend :show => [ :one, :two ]

  show  #=> '12'

[documentation incorrect (category)]: depend :show => [ :x, :y ] => depend :show => [ :one, :two ]?

Module: method aliasing, etc.

star_full.gif star_full.gif star_full.gif alias_accessor( name, target )

I finally found an answer to this long-standing question of mine...

If you override attribute my_attr, will it also override my_attr= for you? alias_method :date_placed, :creation_date I think the answer is no, you'd need to override that separately: alias_method :date_placed=, :creation_date= Is there/should there be another method that does both of these for you?

As with alias_method, but alias both reader and writer.

 attr_accessor :x
 self.x = 1
 alias_accessor :y, :x
 y #=> 1
 self.y = 2
 x #=> 2

star_full.gif star_full.gif star_full.gif alias_method_chain(target, feature)

Encapsulates the common pattern of:

 alias_method :foo_without_feature, :foo
 alias_method :foo, :foo_with_feature

With this, you simply do:

 alias_method_chain :foo, :feature

And both aliases are set up for you.

Also works for methods ending in ? or !. The method aliases keep the same punctuation (for instance, :foo_with_feature?).

[documentation incorrect (category)]:

 alias_method :foo?, :foo_without_feature?

should be:

 alias_method :foo?, :foo_with_feature?

See also: Ruby / Method aliasing

star_full.gif star_full.gif star_empty.gif redirect_method( method_hash )

Redirect methods to other methods. This simply defines methods by the name of a hash key which calls the

method with the name of the hash’s value.

 class Example
   redirect_method :hi => :hello, :hey => :hello
   def hello(name)
     puts "Hello, #{name}."
   end
 end
 e = Example.new
 e.hello("Bob")    #=> "Hello, Bob."
 e.hi("Bob")       #=> "Hello, Bob."
 e.hey("Bob")      #=> "Hello, Bob."

So basically a Hash-based equivalent to alias_method ??

redefine_method( sym, aka=nil, &blk )

Creates a new method for a pre-existing method.

If aka is given, then the method being redefined will first be aliased to this name.

 class Greeter
   def hello ; "Hello" ; end
 end
 Greeter.new.hello   #=> "Hello"
 class Greeter
   redefine_method( :hello, :hi ) do
     hi + ", friend!"
   end
 end
 Greeter.new.hi      #=> "Hello!"
 Greeter.new.hello   #=> "Hello, friend!"


shadow_method( name, old_name=name )

Define a shadow alias for a method.

 class X
   shadow_method( :class )
 end    # creates __class__ method
 X.new.__class__  #=> X

I'm not sure when I'd ever want to use this. Usually when I create a method_alias, I want to give it a unique prefix based on the functionality I'm about to override it with... See on_included, redefine_method...

[documentation incomplete]




[Aspect-oriented programming (category)]

Module#prepend( aspect )

Prepend an aspect module to a module.

  module X
    def x; "x"; end
  end

  module U
    def x; '{' + super + '}'; end
  end

  X.prepend U

  X.x  # => "{x}"



Typos to fix

Anywhere this appears in rendered RDocs: _is equivalent to_ : change to is equivalent to

lib/facets/core/module/attr.rb

show [should] always have a reader and a writer.

Do a spell-check.

exclimation

/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/more/nackclass.rb: scaler -> scalar

Documentation problems to fix

The (nil) documentation in "/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/kernel/nack.rb" overwrites the (completel documentation for "/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/more/nackclass.rb"

Two versions of attr_tester: /usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/module/attr_query.rb, /usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/module/attr_tester.rb

See also

...


Change log: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/240173


Aliases: Ruby Facets, Ruby / Facets

Ads
Personal tools