Jugando con la libertad que ofrece Ruby en sus características básicas, encontré bastante fácil crear un alias para la mayoría de los operadores utilizados en el lenguaje, pero el operador de prefijo unario Regexp#~ es más complicado.
Un primer enfoque ingenuo sería crear un alias en la propia clase Regexp.
class Regexp alias hit ~@ # remember that @ stands for "prefix version" # Note that a simple `alias_method :hit, :~@` will give the same result end Como se señaló en alguna respuesta a continuación, este enfoque es de alguna manera funcional con la forma de llamada de notación de puntos, como /needle/.hit . Sin embargo, intentar ejecutar hit /needle/ generará hit de undefined method para main:Object (NoMethodError)`
Entonces, otro enfoque ingenuo sería definir este mismo método en Object , algo así como
class Object def ~@(pattern) pattern =~ $_ end end Sin embargo, esto no funcionará, ya que la variable global $_ de hecho está enlazada localmente y no mantendrá el valor que tiene en el contexto de la llamada, es decir, $_ siempre es nil en el fragmento anterior.
Entonces la pregunta es, ¿es posible hacer que la expresión hit /needle/ para restituir el mismo resultado que ~ /needle/ ?
Funciona bien para mí:
class Regexp alias_method :hit, :~ # both of them work # alias hit ~ # both of them work end $_ = "input data" /at/.hit #=> 7 ~/at/ #=> 7 /at/.hit #=> 7 ~/at/ #=> 7Entonces, como la pregunta completa ahora lo inhibe, el principal obstáculo es el alcance limitado de $_ . Ahí es donde trace_var puede venir al rescate:
trace_var :$_, proc { |nub| $last_explicitly_read_line = nub #puts "$_ is now '#{nub}'" } def reach(pattern) $last_explicitly_read_line =~ pattern end def first $_ = "It's needless to despair." end def second first p reach /needle/ $_ = 'What a needlework!' p reach /needle/ end p reach /needle/ second p reach /needle/ $_ = nil p reach /needle/ Entonces, la idea básica es esconder el valor de $_ cada vez que se cambia en otra variable a la que se podrá acceder en otro contexto de llamada posterior. Aquí se implementó con otra variable global (no enlazada localmente, a diferencia $_ , por supuesto), pero se podría obtener el mismo resultado con otras implementaciones, como definir una variable de clase en Object .
También se podría intentar usar algo como binding_of_caller o binding_ninja , pero mi propio enfoque falló y también, por supuesto, viene con dependencias adicionales que tienen sus propias limitaciones.