作为参数传递时,未定义的局部变量强制为nil

时间:2016-04-20 14:14:58

标签: ruby

我错误地编写了一个方法,该方法将一个变量赋值给方法调用的返回值,该方法调用在以前未定义时将参数传递给参数。我很想知道这是Ruby中的错误,还是实际的预期行为?

public class Timer extends AppCompatActivity {
    TextView proba, textViewTimerVrijeme;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_timer);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        textViewTimerVrijeme = (TextView) findViewById(R.id.textViewTimerVrijeme);
        Intent intent = getIntent();
        Bundle b = intent.getExtras();

        if (b!=null){
            String j = (String) b.get("visokiInterval");
            textViewTimerVrijeme.setText(j);
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_timer, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_pause:
        }

        return super.onOptionsItemSelected(item);
    }

}

2 个答案:

答案 0 :(得分:5)

来自David Flanagan的“Ruby编程语言”:

  

如果已经看到任何先前对变量的赋值,Ruby会将标识符视为局部变量。即使从未执行过该分配,它也会这样做。

这意味着即使在任何代码执行之前,Ruby解析器也会隐式声明变量。只要ruby看到=运算符,它就会立即生成一个名为yellow的新变量,其默认值为nil。然后,当执行该语句时,对该变量的每个引用都共享它的默认值。

本书接着展示了一个类似的,也许是令人惊讶的ruby变量声明行为的例子,类似于:

>> x               # NameError: undefined local variable or method `x'
>> x = 0 if false  # parsed, but never executed
>> p x             # displays nil

此代码的重要性在于表明变量在解析代码后立即声明,并且由于您对yellow的两个引用发生在同一行,因此必须解析黄色的赋值,因此声明,在作为green

的参数传递之前

答案 1 :(得分:0)

分配可能隐式声明变量

这种行为虽然令人惊讶,但似乎在包括MRI,JRuby和Rubinius在内的Ruby实现中是一致的。这很可能是解析器将赋值的右侧视为解析为 nil 的表达式的结果。

例如,这会引发一个异常,通知您 blue 为零:

red = 1
blue = red + blue
# TypeError: nil can't be coerced into Fixnum

因为它是一个赋值,解析器似乎隐含地将 blue 声明为nil,然后在右侧将其作为nil值。将其与真正未声明的变量进行对比:

red = 1
blue = red + green
# NameError: undefined local variable or method `green' for main:Object

所以,虽然this answer指向某些相关文档,但它仍然没有真正解释为什么这仅适用于赋值的右侧,然后仅适用于左值在rvalue中隐式声明。由于它在实现中是一致的,因此它似乎是预期的行为,并且可能是语言内部所需要的。

询问为什么Matz和Ruby Core Team设计解析器来处理这个边缘情况对他们来说是一个问题。但实际上,这种语言功能通常会为程序员“做正确的事”。