Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where and how is the _ (underscore) variable specified?

Tags:

ruby

Most are aware of _’s special meaning in IRB as a holder for last return value, but that is not what I'm asking about here.

Instead, I’m asking about _ when used as a variable name in plain-old-Ruby-code. Here it appears to have special behavior, akin to a “don't care variable” (à la Prolog). Here are some useful examples illustrating its unique behavior:

lambda { |x, x| 42 }            # SyntaxError: duplicated argument name lambda { |_, _| 42 }.call(4, 2) # => 42 lambda { |_, _| 42 }.call(_, _) # NameError: undefined local variable or method `_' lambda { |_| _ + 1 }.call(42)   # => 43 lambda { |_, _| _ }.call(4, 2)  # 1.8.7: => 2                                 # 1.9.3: => 4 _ = 42 _ * 100         # => 4200 _, _ = 4, 2; _  # => 2 

These were all run in Ruby directly (with putss added in)—not IRB—to avoid conflicting with its additional functionality.

This is all a result of my own experimentation though, as I cannot find any documentation on this behavior anywhere (admittedly it's not the easiest thing to search for). Ultimately, I'm curious how all of this works internally so I can better understand exactly what is special about _. So I’m asking for references to documentation, and, preferably, the Ruby source code (and perhaps RubySpec) that reveal how _ behaves in Ruby.

Note: most of this arose out of this discussion with @Niklas B.

like image 326
Andrew Marshall Avatar asked Mar 04 '12 22:03

Andrew Marshall


People also ask

What does _ in front of variable mean?

Double underscore (__) in front of a variable is a convention. It is used for global variable (The following variables may appear to be global but are not, rather local to each module) in Nodejs meanwhile Underscore(_) used to define private variable.

What is _ used for in Python?

The python interpreter stores the last expression value to the special variable called _ . The underscore _ is also used for ignoring the specific values. If you don't need the specific values or the values are not used, just assign the values to underscore.

What is the use of _ in flutter?

The builder pattern is an essential building block for creating composable UIs in Flutter. As such, Flutter exposes convenience builder types that are used as arguments in many widget classes. Open-Source Backend Server for Flutter Developers.

What does _ mean in C#?

From version 7.0, C# introduced a new feature called discards to create dummy variables, defined by the underscore character _. Discards are equal to unassigned variables. The purpose of this feature is to use this variable when you want to intentionally skip the value by not creating a variable explicitly.


1 Answers

There is some special handling in the source to suppress the "duplicate argument name" error. The error message only appears in shadowing_lvar_gen inside parse.y, the 1.9.3 version looks like this:

static ID shadowing_lvar_gen(struct parser_params *parser, ID name) {     if (idUScore == name) return name;     /* ... */ 

and idUScore is defined in id.c like this:

REGISTER_SYMID(idUScore, "_"); 

You'll see similar special handling in warn_unused_var:

static void warn_unused_var(struct parser_params *parser, struct local_vars *local) {     /* ... */     for (i = 0; i < cnt; ++i) {         if (!v[i] || (u[i] & LVAR_USED)) continue;         if (idUScore == v[i]) continue;         rb_compile_warn(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i]));     } } 

You'll notice that the warning is suppressed on the second line of the for loop.

The only special handling of _ that I could find in the 1.9.3 source is above: the duplicate name error is suppressed and the unused variable warning is suppressed. Other than those two things, _ is just a plain old variable like any other. I don't know of any documentation about the (minor) specialness of _.

In Ruby 2.0, the idUScore == v[i] test in warn_unused_var is replaced with a call to is_private_local_id:

if (is_private_local_id(v[i])) continue; rb_warn4S(ruby_sourcefile, (int)u[i], "assigned but unused variable - %s", rb_id2name(v[i])); 

and is_private_local_id suppresses warnings for variables that begin with _:

if (name == idUScore) return 1; /* ... */ return RSTRING_PTR(s)[0] == '_'; 

rather than just _ itself. So 2.0 loosens things up a bit.

like image 139
mu is too short Avatar answered Sep 22 '22 03:09

mu is too short