1

I understand what the following warning means:

-:1: warning: useless use of a variable in void context

But I don't understand why ERB in Ruby 1.8.7 generates code that uses _erbout variable in void context:

$ rvm use ruby 1.8.7
Using /Users/radeksimko/.rvm/gems/ruby-1.8.7-head
$ touch test.erb
$ erb -x test.erb
_erbout = ''; _erbout
$ erb -x test.erb | ruby -w
-:1: warning: useless use of a variable in void context

This is not a problem in ERB / Ruby 2.0.0+ though as ERB generates code from the template differently:

$ rvm use 2.0.0
Using /Users/radeksimko/.rvm/gems/ruby-2.0.0-p598
$ erb -x test.erb
#coding:ASCII-8BIT
_erbout = ''; _erbout.force_encoding(__ENCODING__)
$ erb -x test.erb | ruby -w
$

To be clear, this has nothing to do with _ (underscores) treating in variable names in between Ruby versions:

$ rvm use 2.0.0
Using /Users/radeksimko/.rvm/gems/ruby-2.0.0-p598
$ echo "erbout = ''; erbout" | ruby -w
-:1: warning: possibly useless use of a variable in void context
$ rvm use 1.8.7
Using /Users/radeksimko/.rvm/gems/ruby-1.8.7-head
$ echo "erbout = ''; erbout" | ruby -w
-:1: warning: useless use of a variable in void context

Is this a bug that should be reported to Ruby/ERB core or am I just misunderstanding something?

mu is too short
  • 426,620
  • 70
  • 833
  • 800
Radek Simko
  • 15,886
  • 17
  • 69
  • 107

1 Answers1

4

The warning is caused by the second line:

_erbout = '';_erbout

which does nothing (_erbout is a local variable in that scope), and it is in a context where is does not return the value of the line (like in a last line of a method).

In Ruby 2.0.0 this line is replaced with

_erbout = '';_erbout.force_encoding(__ENCODING__).

Now ruby does not know for sure if the method call has any side-effects or not, so the warning is not raised.

You can reproduce this with the following code:

useless.rb

def test_me
  unused = 1
  unused
  3
end

p test_me
$ ruby -w useless.rb
useless.rb:3: warning: possibly useless use of a variable in void context
3

All this happens, because the output of erb -x is not supposed to be run on its own. When running a ruby script, the last line is not used as return value, unlike a method.

If you embed the code in a program, and actually use the _erbout, the warning will not be shown.

Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
  • Great answer, thanks! This is the most important bit: "All this happens, because the output of erb -x is not supposed to be run on its own." – Radek Simko Mar 08 '15 at 15:26