class Binding
类 Binding 的对象封装了代码中特定位置的执行上下文,并保留该上下文以供将来使用。在此上下文中可访问的变量、方法、self 的值以及可能的迭代器块都会被保留。Binding 对象可以通过 Kernel#binding 创建,并可用于 Kernel#set_trace_func 的回调以及 TracePoint 的实例。
这些绑定对象可以作为 Kernel#eval 方法的第二个参数传递,从而为求值建立一个环境。
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 对象没有特定于类的任何方法。
Public Instance Methods
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 */);
}
在binding的上下文中求值string中的 Ruby 表达式。如果提供了可选的filename和lineno参数,则在报告语法错误时将使用它们。
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));
}
如果存在数字参数或“it”参数,则返回 true。
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);
}
返回数字参数或“it”参数的值。
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);
}
返回在 binding 中定义的数字参数和“it”参数的名称。
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));
}
如果局部变量 symbol 存在,则返回 true。
def foo a = 1 binding.local_variable_defined?(:a) #=> true binding.local_variable_defined?(:b) #=> false end
此方法是以下代码的简写形式:
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);
}
返回局部变量 symbol 的值。
def foo a = 1 binding.local_variable_get(:a) #=> 1 binding.local_variable_get(:b) #=> NameError end
此方法是以下代码的简写形式:
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;
}
将名为 symbol 的局部变量设置为 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
此方法行为类似于以下代码:
binding.eval("#{symbol} = #{obj}")
如果 obj 可以被 Ruby 代码转储。
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);
}
以符号形式返回 binding 的局部变量的名称。
def foo a = 1 2.times do |n| binding.local_variables #=> [:a, :n] end end
此方法是以下代码的简写形式:
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);
}
返回 binding 对象的绑定接收器。
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);
}
返回 binding 对象的 Ruby 源文件名和行号。