require 'rubygems'
require 'activesupport'

# this doesn't work as expected. does anyone know why?
z = returning html="" do
  html += "stuff" 
  html += "more stuff" if true
end
p z
#>> "" 

# this works though
z = returning html=[] do
  html << "stuff" 
  html << "more_stuff" if true
end.join("\n")
p z
#>> "stuff\nmore_stuff" 

Update: Thanks DrMark, I should have done it like this: (I didn’t realize that one could use << on strings)

z = returning html="" do
  html << "stuff" 
  html << " more stuff" if true
end

5 Responses to “returning doesn't work with empty/blank string??”

  1. DrMark Says:

    There are a couple of things going on here. The second case works because you are using the << method. This changes the original array even though you are inside the block. For the string case, you are confusing variable scopes. If you want to use the "html=''" syntax, you need to use this inside your block:

    z = returning html="" do html << "stuff" html << "more stuff" if true end

    which will change the original string or more similar to your first attempt:

    z = returning html do html += "stuff" html += "more stuff" if true end

    notice I did not use "html=''" in this approach, I simply return the inner variable.

    Best of luck, DrMark

  2. Lourens Naude Says:

    You should yield to the block.Your examples piggy back on scope outside the block - returning in your first example essentially ignores the scope inside the block ...

    See http://gist.github.com/15951 for correct and reliable use.

  3. Arya Asemanfar Says:

    str = "abc" firstid = str.objectid str += "def" secondid = str.objectid str << "ghi" thirdid = str.objectid

    puts firstid == secondid

    => false

    puts secondid == thirdid

    => true

  4. Reg Braithwaite Says:

    "returning" is a red herring. Consider:

    x = y = 5 y = 6 p x

    Do you expect 5 or 6? x is 5 because x = y = 6 is really x = (y = 5) and y = 5 returns the value 5, not a some kind of magic reference to the variable y that updates when y updates.

    Your second example is this:

    x = y = [3, 2, 1] y = y.sort p x

    Now x is a reference to the original array, and it is not sorted because y.sort created a sorted copy of the array and that doesn't change x. So x is still [3, 2, 1]

    x = y = [3, 2, 1] y.sort! p x

    This time sort! destructively modifies the original array, so x becomes [1, 2, 3].

    As for returning, I would never write returning (html = ...). I usually write:

    returning(somevalueexpression) do |variable| ... end

    It is up to you to make sure that whatever you do in the block destructively modifies somevalueexpression. For example, Array#uniq! is a handy method, but quite annoyingly, it returns nil if no changes are made. So:

    returning(somearrayexpression) do |arr| arr.uniq!; end

    This always returns the array, just like #uniq, but doesn't create a copy and never returns nil.

  5. David Lowenfels Says:

    Thanks everyone for the helpful comments!

    @Laurent, your snippets are functionally identical to mine, and the first one still doesn't work. The final solution for me is to use the << operator on the string instead of +=

    
    z = returning html="" do
      html << "stuff" 
      html << " more stuff" if true
    end
    
    

Sorry, comments are closed for this article.