Skip to content

Instantly share code, notes, and snippets.

@melborne
Created July 16, 2012 10:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save melborne/3121898 to your computer and use it in GitHub Desktop.
Save melborne/3121898 to your computer and use it in GitHub Desktop.
Ruby Methods Analysis
ARGF
ArgumentError
Array
BasicObject
Bignum
Binding
Class
Comparable
Complex
Data
Dir
ENV
EOFError
Encoding
Encoding::CompatibilityError
Encoding::Converter
Encoding::ConverterNotFoundError
Encoding::InvalidByteSequenceError
Encoding::UndefinedConversionError
EncodingError
Enumerable
Enumerator
Errno
Errno::E2BIG
Errno::EACCES
Errno::EADDRINUSE
Errno::EADDRNOTAVAIL
Errno::EADV
Errno::EAFNOSUPPORT
Errno::EAGAIN
Errno::EALREADY
Errno::EBADE
Errno::EBADF
Errno::EBADFD
Errno::EBADMSG
Errno::EBADR
Errno::EBADRQC
Errno::EBADSLT
Errno::EBFONT
Errno::EBUSY
Errno::ECHILD
Errno::ECHRNG
Errno::ECOMM
Errno::ECONNABORTED
Errno::ECONNREFUSED
Errno::ECONNRESET
Errno::EDEADLK
Errno::EDEADLOCK
Errno::EDESTADDRREQ
Errno::EDOM
Errno::EDOTDOT
Errno::EDQUOT
Errno::EEXIST
Errno::EFAULT
Errno::EFBIG
Errno::EHOSTDOWN
Errno::EHOSTUNREACH
Errno::EIDRM
Errno::EILSEQ
Errno::EINPROGRESS
Errno::EINTR
Errno::EINVAL
Errno::EIO
Errno::EISCONN
Errno::EISDIR
Errno::EISNAM
Errno::EL2HLT
Errno::EL2NSYNC
Errno::EL3HLT
Errno::EL3RST
Errno::ELIBACC
Errno::ELIBBAD
Errno::ELIBEXEC
Errno::ELIBMAX
Errno::ELIBSCN
Errno::ELNRNG
Errno::ELOOP
Errno::EMFILE
Errno::EMLINK
Errno::EMSGSIZE
Errno::EMULTIHOP
Errno::ENAMETOOLONG
Errno::ENAVAIL
Errno::ENETDOWN
Errno::ENETRESET
Errno::ENETUNREACH
Errno::ENFILE
Errno::ENOANO
Errno::ENOBUFS
Errno::ENOCSI
Errno::ENODATA
Errno::ENODEV
Errno::ENOENT
Errno::ENOEXEC
Errno::ENOLCK
Errno::ENOLINK
Errno::ENOMEM
Errno::ENOMSG
Errno::ENONET
Errno::ENOPKG
Errno::ENOPROTOOPT
Errno::ENOSPC
Errno::ENOSR
Errno::ENOSTR
Errno::ENOSYS
Errno::ENOTBLK
Errno::ENOTCONN
Errno::ENOTDIR
Errno::ENOTEMPTY
Errno::ENOTNAM
Errno::ENOTSOCK
Errno::ENOTTY
Errno::ENOTUNIQ
Errno::ENXIO
Errno::EOPNOTSUPP
Errno::EOVERFLOW
Errno::EPERM
Errno::EPFNOSUPPORT
Errno::EPIPE
Errno::EPROTO
Errno::EPROTONOSUPPORT
Errno::EPROTOTYPE
Errno::ERANGE
Errno::EREMCHG
Errno::EREMOTE
Errno::EREMOTEIO
Errno::ERESTART
Errno::EROFS
Errno::ERROR
Errno::ESHUTDOWN
Errno::ESOCKTNOSUPPORT
Errno::ESPIPE
Errno::ESRCH
Errno::ESRMNT
Errno::ESTALE
Errno::ESTRPIPE
Errno::ETIME
Errno::ETIMEDOUT
Errno::ETOOMANYREFS
Errno::ETXTBSY
Errno::EUCLEAN
Errno::EUNATCH
Errno::EUSERS
Errno::EWOULDBLOCK
Errno::EXDEV
Errno::EXFULL
Errno::EXXX
Errno::NOERROR
Exception
FalseClass
Fiber
FiberError
File
File::Constants
File::Stat
FileTest
Fixnum
Float
FloatDomainError
GC
GC::Profiler
Hash
IO
IOError
IndexError
Integer
Interrupt
Kernel
KeyError
LoadError
LocalJumpError
Marshal
MatchData
Math
Math::DomainError
Method
Module
Mutex
NameError
NilClass
NoMemoryError
NoMethodError
NotImplementedError
Numeric
Object
ObjectSpace
Proc
Process
Process::GID
Process::Status
Process::Sys
Process::UID
Random
Range
RangeError
Rational
Regexp
RegexpError
RuntimeError
ScriptError
SecurityError
Signal
SignalException
StandardError
StopIteration
String
Struct
Struct::Tms
Symbol
SyntaxError
SystemCallError
SystemExit
SystemStackError
Thread
ThreadError
ThreadGroup
Time
TrueClass
TypeError
UnboundMethod
ZeroDivisionError
fatal
all_methods = ObjectSpace.each_object(Module).flat_map do |c|
c.methods(false) + c.instance_methods(false)
end.reject { |m| "#{m}".start_with? '_deprecated' }
all_methods.size # => 1659
methods = all_methods.uniq
methods.size # => 937
# build a url for Google Chart API
require "gchart"
# -----------------------
# Methods by Name Length
# -----------------------
by_len = methods.group_by(&:size).sort
x, data = by_len.map { |s, m| [s, m.size] }.transpose
y = 0.step(130, 10).to_a
puts Gchart.bar(:data => data,
:max_value => 130,
:axis_with_labels => 'x,y',
:axis_labels => [x, y],
:size => '600x400',
:bar_width_and_spacing => 16,
:title => 'Methods by Name Length',
:bg => 'efefdd',
)
##> http://chart.apis.google.com/chart?chxl=0:|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|29|31|1:|0|10|20|30|40|50|60|70|80|90|100|110|120|130&chxt=x,y&chbh=16&chf=bg,s,efefdd&chd=s:HHX9641fiWULHKLHHECDCBCABAAA&chtt=Methods+by+Name+Length&cht=bvs&chs=600x400&chxr=0,15,130
avg = methods.map(&:size).tap { |ms| break ms.inject(:+) / ms.size.to_f } # => 7.924226254002135
sd = methods.map(&:size).tap do |ms|
sigmas = ms.map { |n| (avg - n)**2 }
break Math.sqrt(sigmas.inject(:+) / ms.size)
end
sd # => 4.6276072940465225
puts by_len.select { |n, _| n > 12 }
.map { |n, ms| "%d => %s (%d)" % [n, ms.sort.join(' '), ms.size] }
# -----------------------------------
# Methods by Beginning Character Type
# -----------------------------------
by_begin = methods.group_by do |m|
case m[0]
when 'a'..'z' then m[0]
when 'A'..'Z' then 'A-Z'
else 'Sym'
end
end.sort
x, data = by_begin.map { |s, m| [s, m.size] }.transpose
y = 0.step(90, 10).to_a
puts Gchart.bar(:data => data,
:axis_with_labels => 'x,y',
:axis_labels => [x, y],
:size => '600x400',
:bar_width_and_spacing => 17,
:title => 'Methods by Beginning Character Type',
:bg => 'efefdd',
)
#>> http://chart.apis.google.com/chart?chxl=0:|A-Z|Sym|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|y|z|1:|0|10|20|30|40|50|60|70|80|90&chxt=x,y&chbh=17&chf=bg,s,efefdd&chd=s:DSYKtbkUUEUADWUJFlBo9ZRDJBB&chtt=Methods+by+Beginning+Character+Type&cht=bvs&chs=600x400&chxr=0,7,120
puts by_begin.select { |c, ms| %w(s c r A-Z Sym).include?(c) }
.map { |c, ms| "%s => %s (%d)\n\n" % [c, ms.sort.join(' '), ms.size] }
# -------------------
# End Character Types
# -------------------
by_end = methods.group_by { |m| m.match /[!?=]$/; $& }
x, data = by_end.map { |s, m| ["#{s}(#{m.size})", m.size] }.transpose
puts Gchart.pie(:data => data,
:labels => x,
:size => '500x320',
:title => 'End Character Types',
:bg => 'efefdd',
)
#>> http://chart.apis.google.com/chart?chf=bg,s,efefdd&chd=s:9JDC&chl=%28763%29|%3F%28116%29|%3D%2843%29|%21%2834%29&chtt=End+Character+Types&cht=p&chs=500x320&chxr=0,763,763
puts by_end.reject { |t, ms| t.nil? }
.map { |t, ms| "%s => %s (%d)\n\n" % [t, ms.sort.join(' '), ms.size] }
# ----------------------
# Words in a Method Name
# ----------------------
by_sep= methods.group_by { |m| "#{m}".scan(/[^_]+/).size }.sort
x, data = by_sep.map { |n, m| [[n,m.size], m.size] }.transpose
x = x.map { |n,s| %w(one\ word two\ words three\ words four\ words five\ words)[n-1] + "(#{s})" }
puts Gchart.pie(:data => data,
:labels => x,
:size => '500x320',
:title => 'Words in a Method Name',
:bg => 'efefdd',
)
#>> http://chart.apis.google.com/chart?chf=bg,s,efefdd&chd=s:9UEAA&chl=one+word%28675%29|two+words%28225%29|three+words%2853%29|four+words%281%29|five+words%282%29&chtt=Words+in+a+Method+Name&cht=p&chs=500x320&chxr=0,675,675
puts by_sep.select { |n, ms| n > 2 }
.map { |t, ms| "%s => %s (%d)\n\n" % [t, ms.sort.join(' '), ms.size] }
by_sep.detect { |n, ms| n == 3 }.last
.tap { |ms| break ms.map(&:size).inject(:+) / ms.size.to_f } # => 19.15
# ---------------------
# Words used in Methods
# ---------------------
by_word = methods.flat_map { |m| "#{m}".scan(/[^_=!?~%&*<^@\[\]+\/-]+/) }
.inject(Hash.new(0)) { |h, x| h[x] +=1; h }
.select { |k, v| v >= 8 }.sort_by { |k,v| -v }
x, data = by_word.map { |k, v| ["#{k}(#{v})", v] }.transpose
puts Gchart.pie(:data => data,
:labels => x,
:size => '500x320',
:title => 'Words used in Methods',
:bg => 'efefdd',
)
#>> http://chart.apis.google.com/chart?chf=bg,s,efefdd&chd=s:993ssppllffbb&chl=each%2818%29|to%2818%29|default%2816%29|method%2813%29|instance%2813%29|encoding%2812%29|path%2812%29|load%2811%29|class%2811%29|post%289%29|methods%289%29|public%288%29|by%288%29&chtt=Words+used+in+Methods&cht=p&chs=500x320&chxr=0,18,18
puts methods.map { |m| "#{m}".scan(/[^_=!?~%&*<^@\[\]+\/-]+/) << m }
.group_by { |ws| ws.any?{ |w| w.match(/^(each|to)$/) }; $& }
.reject { |k, v| k.nil? }
.map { |k, v| "%s => %s\n\n" % [k, v.map(&:last)] }
klasses = ObjectSpace.each_object(Module)
def live(methods)
methods.reject { |m| "#{m}".start_with? '_deprecated' }
end
methods = klasses.map do |k|
[k, live(k.methods(false)).size, live(k.instance_methods(false)).size]
end
require "gchart"
# List of Class Methods
cms = methods.map { |k, cm, im| [k, cm] }.reject { |k, m| m < 5 }.sort_by { |k, m| -m }
puts cms.map { |kcm| kcm.join(" => ") }.join(", ")
x, data = cms.transpose
y = 0.step(90, 10).to_a
puts Gchart.bar(:data => data,
:max_value => 90,
:axis_with_labels => 't,y,x',
:axis_labels => [y, x.reverse, y],
:size => '600x500',
:bar_width_and_spacing => 18,
:title => 'Class Methods',
:bg => 'efefdd',
:orientation => 'horizontal',
)
#>> http://chart.apis.google.com/chart?chxl=0:|0|10|20|30|40|50|60|70|80|90|1:|Regexp|ObjectSpace|RubyVM%3A%3AInstructionSequence|Time|GC|GC%3A%3AProfiler|Process%3A%3AGID|Process%3A%3AUID|Encoding|Thread|IO|Process%3A%3ASys|Dir|Math|FileTest|Process|File|Kernel|Gem|2:|0|10|20|30|40|50|60|70|80|90&chxt=t,y,x&chbh=18&chf=bg,s,efefdd&chd=s:9onaRRLKKIHGGEEEEEE&chtt=Class+Methods&cht=bhs&chs=600x500&chxr=0,89,90
# Class methods for Wordle
puts cms.map { |k, m| "#{k}:#{m}" }
# List of Instance Methods
ims = methods.map { |k, cm, im| [k, im] }.reject { |k, m| m < 10 }.sort_by { |k, m| -m }
puts ims.map { |kim| kim.join(" => ") }.join(", ")
x, data = ims.transpose
y = 0.step(110, 10).to_a
puts Gchart.bar(:data => data,
:max_value => 110,
:axis_with_labels => 't,y,x',
:axis_labels => [y, x.reverse, y],
:size => '390x760',
:bar_width_and_spacing => 17,
:title => 'Instance Methods',
:bg => 'efefdd',
:orientation => 'horizontal',
)
#>> http://chart.apis.google.com/chart?chxl=0:|0|10|20|30|40|50|60|70|80|90|100|110|1:|Dir|File|UnboundMethod|Enumerator|NilClass|Encoding%3A%3AConverter|Process%3A%3AStatus|Method|Struct|Regexp|Proc|Range|MatchData|Symbol|Integer|Rational|Thread|Fixnum|Bignum|Complex|Numeric|File%3A%3AStat|Float|Module|Enumerable|Kernel|ARGF.class|Hash|Time|IO|Array|Pathname|String|2:|0|10|20|30|40|50|60|70|80|90|100|110&chxt=t,y,x&chbh=17&chf=bg,s,efefdd&chd=s:9zxnedcbaYXXXUUTOONNKKJJJJIHGGGGG&chtt=Instance+Methods&cht=bhs&chs=390x760&chxr=0,109,110
# Instance methods for Wordle
puts ims.map { |k, m| "#{k}:#{m}" }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment