class Binding
Objekte der Klasse Binding kapseln den Ausführungskontext an einer bestimmten Stelle im Code und behalten diesen Kontext für die zukünftige Verwendung. Die Variablen, Methoden, der Wert von self und möglicherweise ein Iterator-Block, auf die in diesem Kontext zugegriffen werden kann, werden alle beibehalten. Binding-Objekte können mit Kernel#binding erstellt und den Rückrufen von Kernel#set_trace_func sowie Instanzen von TracePoint zur Verfügung gestellt werden.
Diese Bindungsobjekte können als zweites Argument der Methode Kernel#eval übergeben werden, um eine Umgebung für die Auswertung herzustellen.
class Demo def initialize(n) @secret = n end def get_binding binding end end k1 = Demo.new(99) b1 = k1.get_binding k2 = Demo.new(-3) b2 = k2.get_binding eval("@secret", b1) #=> 99 eval("@secret", b2) #=> -3 eval("@secret") #=> nil
Binding-Objekte haben keine klassenspezifischen Methoden.
Öffentliche Instanzmethoden
Source
static VALUE
bind_eval(int argc, VALUE *argv, VALUE bindval)
{
VALUE args[4];
rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
args[1] = bindval;
return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */);
}
Wertet die Ruby-Ausdrücke in string im Kontext der binding aus. Wenn die optionalen Parameter filename und lineno vorhanden sind, werden sie bei der Meldung von Syntaxfehlern verwendet.
def get_binding(param) binding end b = get_binding("hello") b.eval("param") #=> "hello"
Source
static VALUE
bind_implicit_parameter_defined_p(VALUE bindval, VALUE sym)
{
ID lid = check_local_id(bindval, &sym);
const rb_binding_t *bind;
const rb_env_t *env;
if (lid == idIt) lid = idItImplicit;
if (!lid || !rb_implicit_param_p(lid)) {
rb_name_err_raise("'%1$s' is not an implicit parameter",
bindval, sym);
}
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
return RBOOL(get_local_variable_ptr(&env, lid, FALSE));
}
Gibt true zurück, wenn der nummerierte Parameter oder der "it"-Parameter existiert.
def foo [42].each do it binding.implicit_parameter_defined?(:it) #=> true binding.implicit_parameter_defined?(:_1) #=> false end { k: 42 }.each do _2 binding.implicit_parameter_defined?(:_1) #=> true binding.implicit_parameter_defined?(:_2) #=> true binding.implicit_parameter_defined?(:_3) #=> false binding.implicit_parameter_defined?(:it) #=> false end end
Source
static VALUE
bind_implicit_parameter_get(VALUE bindval, VALUE sym)
{
ID lid = check_local_id(bindval, &sym);
const rb_binding_t *bind;
const VALUE *ptr;
const rb_env_t *env;
if (lid == idIt) lid = idItImplicit;
if (!lid || !rb_implicit_param_p(lid)) {
rb_name_err_raise("'%1$s' is not an implicit parameter",
bindval, sym);
}
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
if ((ptr = get_local_variable_ptr(&env, lid, FALSE)) != NULL) {
return *ptr;
}
if (lid == idItImplicit) lid = idIt;
rb_name_err_raise("implicit parameter '%1$s' is not defined for %2$s", bindval, ID2SYM(lid));
UNREACHABLE_RETURN(Qundef);
}
Gibt den Wert des nummerierten Parameters oder des "it"-Parameters zurück.
def foo [42].each do it binding.implicit_parameter_get(:it) #=> 42 end { k: 42 }.each do _2 binding.implicit_parameter_get(:_1) #=> :k binding.implicit_parameter_get(:_2) #=> 42 end end
Source
static VALUE
bind_implicit_parameters(VALUE bindval)
{
const rb_binding_t *bind;
const rb_env_t *env;
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
if (get_local_variable_ptr(&env, idItImplicit, FALSE)) {
return rb_ary_new_from_args(1, ID2SYM(idIt));
}
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
return rb_vm_env_numbered_parameters(env);
}
Gibt die Namen der nummerierten Parameter und des "it"-Parameters zurück, die in der Bindung definiert sind.
def foo [42].each do it binding.implicit_parameters #=> [:it] end { k: 42 }.each do _2 binding.implicit_parameters #=> [:_1, :_2] end end
Source
static VALUE
bind_local_variable_defined_p(VALUE bindval, VALUE sym)
{
ID lid = check_local_id(bindval, &sym);
const rb_binding_t *bind;
const rb_env_t *env;
if (!lid) return Qfalse;
if (rb_numparam_id_p(lid)) {
rb_name_err_raise("numbered parameter '%1$s' is not a local variable",
bindval, ID2SYM(lid));
}
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
return RBOOL(get_local_variable_ptr(&env, lid, TRUE));
}
Gibt true zurück, wenn eine lokale Variable symbol existiert.
def foo a = 1 binding.local_variable_defined?(:a) #=> true binding.local_variable_defined?(:b) #=> false end
Diese Methode ist die Kurzform des folgenden Codes
binding.eval("defined?(#{symbol}) == 'local-variable'")
Source
static VALUE
bind_local_variable_get(VALUE bindval, VALUE sym)
{
ID lid = check_local_id(bindval, &sym);
const rb_binding_t *bind;
const VALUE *ptr;
const rb_env_t *env;
if (!lid) goto undefined;
if (rb_numparam_id_p(lid)) {
rb_name_err_raise("numbered parameter '%1$s' is not a local variable",
bindval, ID2SYM(lid));
}
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
if ((ptr = get_local_variable_ptr(&env, lid, TRUE)) != NULL) {
return *ptr;
}
sym = ID2SYM(lid);
undefined:
rb_name_err_raise("local variable '%1$s' is not defined for %2$s",
bindval, sym);
UNREACHABLE_RETURN(Qundef);
}
Gibt den Wert der lokalen Variable symbol zurück.
def foo a = 1 binding.local_variable_get(:a) #=> 1 binding.local_variable_get(:b) #=> NameError end
Diese Methode ist die Kurzform des folgenden Codes
binding.eval("#{symbol}")
Source
static VALUE
bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val)
{
ID lid = check_local_id(bindval, &sym);
rb_binding_t *bind;
const VALUE *ptr;
const rb_env_t *env;
if (!lid) lid = rb_intern_str(sym);
if (rb_numparam_id_p(lid)) {
rb_name_err_raise("numbered parameter '%1$s' is not a local variable",
bindval, ID2SYM(lid));
}
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
if ((ptr = get_local_variable_ptr(&env, lid, TRUE)) == NULL) {
/* not found. create new env */
ptr = rb_binding_add_dynavars(bindval, bind, 1, &lid);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
}
#if YJIT_STATS
rb_yjit_collect_binding_set();
#endif
RB_OBJ_WRITE(env, ptr, val);
return val;
}
Setzt die lokale Variable namens symbol auf obj.
def foo a = 1 bind = binding bind.local_variable_set(:a, 2) # set existing local variable `a' bind.local_variable_set(:b, 3) # create new local variable `b' # `b' exists only in binding p bind.local_variable_get(:a) #=> 2 p bind.local_variable_get(:b) #=> 3 p a #=> 2 p b #=> NameError end
Diese Methode verhält sich ähnlich wie der folgende Code
binding.eval("#{symbol} = #{obj}")
if obj in Ruby-Code gedumpt werden kann.
Source
static VALUE
bind_local_variables(VALUE bindval)
{
const rb_binding_t *bind;
const rb_env_t *env;
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
return rb_vm_env_local_variables(env);
}
Gibt die Namen der lokalen Variablen der Bindung als Symbole zurück.
def foo a = 1 2.times do |n| binding.local_variables #=> [:a, :n] end end
Diese Methode ist die Kurzform des folgenden Codes
binding.eval("local_variables")
Source
static VALUE
bind_receiver(VALUE bindval)
{
const rb_binding_t *bind;
GetBindingPtr(bindval, bind);
return vm_block_self(&bind->block);
}
Gibt den gebundenen Empfänger des Bindungsobjekts zurück.
Source
static VALUE
bind_location(VALUE bindval)
{
VALUE loc[2];
const rb_binding_t *bind;
GetBindingPtr(bindval, bind);
loc[0] = pathobj_path(bind->pathobj);
loc[1] = INT2FIX(bind->first_lineno);
return rb_ary_new4(2, loc);
}
Gibt den Ruby-Quellcode-Dateinamen und die Zeilennummer des Bindungsobjekts zurück.