ToTheMoon
ToTheMoon

Reputation: 89

Changing argument inside a function using yield

I am new to the concept of yield and currently practising it. I was expecting to get ["bread", "JUICY", "bread"] but I got ["bread", "steak", "bread"].

Can you please help me understand why? And how can I fix my code?

def burger(patty)
  if block_given?
    yield(patty)
  end
  return ["bread", patty, "bread"]
end


# TODO: Change 'steak'to 'JUICY'using yield
juicy_burger = burger("steak") do |patty|
  patty = "JUICY"
end
p juicy_burger

Upvotes: 2

Views: 1153

Answers (2)

Tamar
Tamar

Reputation: 2066

The variable is local to the function and you did not save back the value yield returned. The code below will give you ["bread", "JUICY", "bread"]

def burger(patty)
  if block_given?
    patty = yield(patty) # <-- this is the diff
  end
  return ["bread", patty, "bread"]
end


# TODO: Change 'steak'to 'JUICY'using yield
juicy_burger = burger("steak") do |patty|
  patty = "JUICY"
end
p juicy_burger

Upvotes: 1

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230336

juicy_burger = burger("steak") do |patty|
  patty = "JUICY"
end

Reassignments like this are not propagated to the outer scopes. Once this block returns, patty "reverts" to its initial value.

Solution? Use the overwritten value while it's still in scope.

def burger(patty)
  if block_given?
    patty = yield(patty)
    # ^ shadow the parameter here. 
    # doesn't have to be a shadow. You can use any name. new_patty = yield(patty)
  end
  return ["bread", patty, "bread"]
end


juicy_burger = burger("steak") do |patty|
  "JUICY #{patty}" # <- simple return here
end
p juicy_burger # >> ["bread", "JUICY steak", "bread"]

Upvotes: 3

Related Questions