una - ruby listas
¿Cómo se enumeran los objetos actualmente disponibles en el alcance actual en ruby? (7)
Soy nuevo en ruby y estoy jugando con el IRB.
Descubrí que puedo enumerar los métodos de un objeto utilizando el método ".methods", y que el método self.methods me da lo que quiero (similar al dir de Python ( builtins )?), Pero ¿cómo puedo encontrar los métodos de un biblioteca / módulo que he cargado mediante include y require?
irb(main):036:0* self.methods
=> ["irb_pop_binding", "inspect", "taguri", "irb_chws", "clone", "irb_pushws", "public_methods", "taguri=", "irb_pwws",
"public", "display", "irb_require", "irb_exit", "instance_variable_defined?", "irb_cb", "equal?", "freeze", "irb_context
", "irb_pop_workspace", "irb_cwb", "irb_jobs", "irb_bindings", "methods", "irb_current_working_workspace", "respond_to?"
, "irb_popb", "irb_cws", "fg", "pushws", "conf", "dup", "cwws", "instance_variables", "source", "cb", "kill", "help", "_
_id__", "method", "eql?", "irb_pwb", "id", "bindings", "send", "singleton_methods", "popb", "irb_kill", "chws", "taint",
"irb_push_binding", "instance_variable_get", "frozen?", "irb_source", "pwws", "private", "instance_of?", "__send__", "i
rb_workspaces", "to_a", "irb_quit", "to_yaml_style", "irb_popws", "irb_change_workspace", "jobs", "type", "install_alias
_method", "irb_push_workspace", "require_gem", "object_id", "instance_eval", "protected_methods", "irb_print_working_wor
kspace", "irb_load", "require", "==", "cws", "===", "irb_pushb", "instance_variable_set", "irb_current_working_binding",
"extend", "kind_of?", "context", "gem", "to_yaml_properties", "quit", "popws", "irb", "to_s", "to_yaml", "irb_fg", "cla
ss", "hash", "private_methods", "=~", "tainted?", "include", "irb_cwws", "irb_change_binding", "irb_help", "untaint", "n
il?", "pushb", "exit", "irb_print_working_binding", "is_a?", "workspaces"]
irb(main):037:0>
Estoy acostumbrado a Python, donde uso la función dir () para lograr lo mismo:
>>> dir()
[''__builtins__'', ''__doc__'', ''__name__'', ''__package__'']
>>>
Escribí una joya para eso:
$ gem install method_info
$ rvm use 1.8.7 # (1.8.6 works but can be very slow for an object with a lot of methods)
$ irb
> require ''method_info''
> 5.method_info
::: Fixnum :::
%, &, *, **, +, -, -@, /, <, <<, <=, <=>, ==, >, >=, >>, [], ^, abs,
div, divmod, even?, fdiv, id2name, modulo, odd?, power!, quo, rdiv,
rpower, size, to_f, to_s, to_sym, zero?, |, ~
::: Integer :::
ceil, chr, denominator, downto, floor, gcd, gcdlcm, integer?, lcm,
next, numerator, ord, pred, round, succ, taguri, taguri=, times, to_i,
to_int, to_r, to_yaml, truncate, upto
::: Precision :::
prec, prec_f, prec_i
::: Numeric :::
+@, coerce, eql?, nonzero?, pretty_print, pretty_print_cycle,
remainder, singleton_method_added, step
::: Comparable :::
between?
::: Object :::
clone, to_yaml_properties, to_yaml_style, what?
::: MethodInfo::ObjectMethod :::
method_info
::: Kernel :::
===, =~, __clone__, __id__, __send__, class, display, dup, enum_for,
equal?, extend, freeze, frozen?, hash, id, inspect, instance_eval,
instance_exec, instance_of?, instance_variable_defined?,
instance_variable_get, instance_variable_set, instance_variables,
is_a?, kind_of?, method, methods, nil?, object_id, pretty_inspect,
private_methods, protected_methods, public_methods, respond_to?, ri,
send, singleton_methods, taint, tainted?, tap, to_a, to_enum, type,
untaint
=> nil
Estoy trabajando en una mejora de las opciones de paso y configuración predeterminada, pero por ahora sugeriría que agregue lo siguiente a su archivo .irbrc:
require ''method_info''
MethodInfo::OptionHandler.default_options = {
:ancestors_to_exclude => [Object],
:enable_colors => true
}
Esto habilita colores y oculta los métodos que tiene cada objeto, ya que generalmente no está interesado en ellos.
Para acceder a todas las instancias de objeto en ruby, usa ObjectSpace
http://www.ruby-doc.org/core-1.8.7/classes/ObjectSpace.html#M000928
Sin embargo, esto se considera lento (incluso para ruby) y puede no estar habilitado en algunos intérpretes (p. Ej. JRuby puede deshabilitar ObjectSpace ya que es mucho más rápido confiar en el jvm para gc sin necesidad de seguir esto en jRuby).
Puede pasar los mensajes .methods a la biblioteca / módulo incluso antes de cargarlo, para ver todos los métodos disponibles. Hacer self.methods
solo devuelve todos los métodos que contiene el objeto Object. Puedes ver esto haciendo self.class
. Digamos que desea ver todos los métodos en el módulo Archivo. Simplemente haga File.methods
y obtendrá una lista de todos los métodos que existen en el módulo File. Esto, quizás, no es lo que quieres, pero debería ser de alguna ayuda.
ObjectSpace.each_object podría ser lo que estás buscando.
Para obtener una lista de módulos incluidos, puede usar Module.included_modules .
También puede verificar si un objeto responde a un método caso por caso utilizando object.respond_to? .
El método dir()
no está claramente definido ...
Nota: Debido a que
dir()
se proporciona principalmente para su uso en un aviso interactivo, trata de proporcionar un conjunto interesante de nombres más de lo que intenta proporcionar un conjunto de nombres riguroso o consistentemente definido, y su comportamiento detallado puede cambiar a través de lanzamientos.
... pero podemos crear una aproximación cercana en Ruby. Hagamos un método que devuelva una lista ordenada de todos los métodos agregados a nuestro alcance por los módulos incluidos. Podemos obtener una lista de los módulos que se han incluido utilizando el método included_modules
.
Al igual que dir()
, queremos ignorar los métodos "predeterminados" (como print
), y también queremos enfocarnos en el conjunto de nombres "interesantes". Por lo tanto, ignoraremos los métodos en Kernel
, y solo devolveremos los métodos que se definieron directamente en los módulos, ignorando los métodos heredados. Podemos lograr lo último pasando false
al método methods()
. Poniendo todo junto, obtenemos ...
def included_methods(object=self)
object = object.class if object.class != Class
modules = (object.included_modules-[Kernel])
modules.collect{ |mod| mod.methods(false)}.flatten.sort
end
Puede pasarle una clase, un objeto o nada (su valor predeterminado es el alcance actual). Probémoslo ...
irb(main):006:0> included_methods
=> []
irb(main):007:0> include Math
=> Object
irb(main):008:0> included_methods
=> ["acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", "cos", "cosh", "erf", "erfc", "exp", "frexp", "hypot", "ldexp", "log", "log10", "sin", "sinh", "sqrt", "tan", "tanh"]
dir()
también incluye variables definidas localmente, y eso es fácil. Solo llama...
local_variables
... desafortunadamente, no podemos simplemente agregar la llamada local_variables
los local_variables
porque nos daría las variables que son locales para el método de local_variables
, y eso no sería muy útil. Por lo tanto, si quieres incluir variables locales con los methods_methods, solo llama ...
(included_methods + local_variables).sort
No estoy del todo seguro de lo que quiere decir con los "objetos actuales". Puede iterar sobre ObjectSpace, como ya se ha mencionado. Pero aquí hay algunos otros métodos.
local_variables
instance_variables
global_variables
class_variables
constants
Hay una gotcha. Deben ser llamados en los ámbitos correctos. Así que en IRB, o en una instancia de objeto o en el alcance de clase (así que en todas partes, básicamente) puede llamar a los primeros 3.
local_variables #=> ["_"]
foo = "bar"
local_variables #=> ["_", "foo"]
# Note: the _ variable in IRB contains the last value evaluated
_ #=> "bar"
instance_variables #=> []
@inst_var = 42
instance_variables #=> ["@inst_var"]
global_variables #=> ["$-d", "$/"", "$$", "$<", "$_", ...]
$" #=> ["e2mmap.rb", "irb/init.rb", "irb/workspace.rb", ...]
Pero umm, ¿y si quieres que tu programa los evalúe realmente sin necesidad de que los digite mucho? El truco es eval.
eval "@inst_var" #=> 42
global_variables.each do |v|
puts eval(v)
end
Los últimos 2 de los 5 mencionados al principio deben evaluarse a nivel de módulo (una clase es un descendiente de un módulo, por lo que funciona).
Object.class_variables #=> []
Object.constants #=> ["IO", "Duration", "UNIXserver", "Binding", ...]
class MyClass
A_CONST = ''pshh''
class InnerClass
end
def initialize
@@meh = "class_var"
end
end
MyClass.constants #=> ["A_CONST", "InnerClass"]
MyClass.class_variables #=> []
mc = MyClass.new
MyClass.class_variables #=> ["@@meh"]
MyClass.class_eval "@@meh" #=> "class_var"
Aquí hay algunos trucos más para explorar en diferentes direcciones
"".class #=> String
"".class.ancestors #=> [String, Enumerable, Comparable, ...]
String.ancestors #=> [String, Enumerable, Comparable, ...]
def trace
return caller
end
trace #=> ["(irb):67:in `irb_binding''", "/System/Library/Frameworks/Ruby...", ...]
Qué pasa:
Object.constants.select{|x| eval(x.to_s).class == Class}
Eso enumera las clases disponibles para mí. No soy un experto en rubíes y estaba siendo arrojado a una consola de rubí sin tener idea de qué clases tenían a mano. Ese único trazador de líneas fue un comienzo.