Change variable passed in a method [duplicate] - ruby

This question already has answers here:
'pass parameter by reference' in Ruby?
(6 answers)
Closed 8 years ago.
How can I change the contents of a variable using a method? Maybe I'm not saying this correctly. What is a way to get the reference to a variable like in C? Example:
// main stuff
int gorilla = 29;
makeMeABanana(&gorilla);
void makeMeABanana(int *gorilla) { }
How can I do something like this in Ruby?

You should not do this - you're just porting techniques that are fully appropriate to C to Ruby, where they are no longer appropriate. There are several fancy ways around this (eg using a Proc closed over your calling namespace, or eval) but they are usually inappropriate in Ruby unless you know precisely what you're doing.

Recently on the ruby-talk mailing list, someone asked about writing a swap function where swap(a,b) would swap the values of the variables "a" and "b". Normally this cannot be done in Ruby because the swap function would have no reference to the binding of the calling function.
However, if we explictly pass in the binding, then it is possible to write a swap-like function. Here is a simple attempt:
def swap(var_a, var_b, vars)
old_a = eval var_a, vars
old_b = eval var_b, vars
eval "#{var_a} = #{old_b}", vars
eval "#{var_b} = #{old_a}", vars
end
a = 22
b = 33
swap ("a", "b", binding)
p a # => 33
p b # => 22
This actually works! But it has one big drawback. The old values of "a" and "b" are interpolated into a string. As long as the old values are simple literals (e.g. integers or strings), then the last two eval statements will look like: eval "a = 33", vars". But if the old values are complex objects, then the eval would look like eval "a = #", vars. Oops, this will fail for any value that can not survive a round trip to a string and back.
Referred from : http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc

Integers are objects, with an id, like everything else in Ruby. They are implemented like this:
p (0..10).map{|n| n.object_id}
#=>[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
All other objects have even object_id numbers. There is no way to change 7 (object_id 15) into something else.

Related

Binding vs Assignment

I've read a number of articles on the difference between assignment and binding, but it hasn't clicked yet (specifically in the context of an imperative language vs one without mutation).
I asked in IRC, and someone mentioned these 2 examples illustrate the difference, but then I had to go and I didn't see the full explanation.
Can someone please explain how/why this works in a detailed way, to help illustrate the difference?
Ruby
x = 1; f = lambda { x }; x = 2; f.call
#=> 2
Elixir
x = 1; f = fn -> x end; x = 2; f.()
#=> 1
I've heard this explanation before and it seems pretty good:
You can think of binding as a label on a suitcase, and assignment as a
suitcase.
In other languages, where you have assignment, it is more like putting a value in a suitcase. You actually change value that is in the suitcase and put in a different value.
If you have a suitcase with a value in it, in Elixir, you put a label on it. You can change the label, but the value in the suitcase is still the same.
So, for example with:
iex(1)> x = 1
iex(2)> f = fn -> x end
iex(3)> x = 2
iex(4)> f.()
1
You have a suitcase with 1 in it and you label it x.
Then you say, "Here, Mr. Function, I want you to tell me what is in this suitcase when I call you."
Then, you take the label off of the suitcase with 1 in it and put it on another suitcase with 2 in it.
Then you say "Hey, Mr. Function, what is in that suitcase?"
He will say "1", because the suitcase hasn't changed. Although, you have taken your label off of it and put it on a different suitcase.
After a while, I came up with the answer that is probably the best explanation of the difference between “binding” and “assignment”; it has nothing in common with what I have written in another answer, hence it’s posted as a separate answer.
In any functional language, where everything is immutable, there is no meaningful difference between terms “binding” and “assignment.” One might call it either way; the common pattern is to use the word “binding,“ explicitly denoting that it’s a value bound to a variable. In Erlang, for instance, one can not rebound a variable. In Elixir this is possible (why, for God’s sake, José, what for?)
Consider the following example in Elixir:
iex> x = 1
iex> 1 = x
The above is perfectly valid Elixir code. It is evident, one cannot assign anything to one. It is neither assignment nor binding. It is matching. That is how = is treated in Elixir (and in Erlang): a = b fails if both are bound to different values; it returns RHO if they match; it binds LHO to RHO if LHO is not bound yet.
In Ruby it differs. There is a significant difference between assignment (copying the content,) and binding (making a reference.)
Elixir vs Ruby might not be the best contrast for this. In Elixir, we can readily "re-assign" the value of a previously assigned named variable. The two anonymous-function examples you provided demonstrate the difference in how the two languages assign local variables in them. In Ruby, the variable, meaning the memory reference, is assigned, which is why when we change it, the anonymous function returns the current value stored in that memory-reference. While in Elixir, the value of the variable at the time the anonymous function is defined (rather than the memory reference) is copied and stored as the local variable.
In Erlang, Elixir's "parent" language, however, variables as a rule are "bound." Once you've declared the value for the variable named X, you are not allowed to alter it for the remainder of the program and any needed alterations would need to be stored in new named variables. (There is a way to reassign a named variable in Erlang but it is not the custom.)
Binding refers to particular concept used in expression-based languages that may seem foreign if you're used to statement-based languages. I'll use an ML-style example to demonstrate:
let x = 3 in
let y = 5 in
x + y
val it : int = 8
The let... in syntax used here demonstrates that the binding let x = 3 is scoped only to the expression following the in. Likewise, the binding let y = 5 is only scoped to the expression x + y, such that, if we consider another example:
let x = 3 in
let f () =
x + 5
let x = 4 in
f()
val it : int = 8
The result is still 8, even though we have the binding let x = 4 above the call to f(). This is because f itself was bound in the scope of the binding let x = 3.
Assignment in statement-based languages is different, because the variables being assigned are not scoped to a particular expression, they are effectively 'global' for whatever block of code they're in, so reassigning the value of a variable changes the result of an evaluation that uses the same variable.
The easiest way to understand the difference, would be to compare the AST that is used by the language interpreter/compiler to produce machine-/byte-code.
Let’s start with ruby. Ruby does not provide the AST viewer out of the box, so I will use RubyParser gem for that:
> require 'ruby_parser'
> RubyParser.new.parse("x = 1; f = -> {x}; x = 2; f.()").inspect
#=> "s(:block, s(:lasgn, :x, s(:lit, 1)),
# s(:lasgn, :f, s(:iter, s(:call, nil, :lambda), 0, s(:lvar, :x))),
# s(:lasgn, :x, s(:lit, 2)), s(:call, s(:lvar, :f), :call))"
The thing we are looking for is the latest node in the second line: there is x variable inside the proc. In other words, ruby expects the bound variable there, named x. At the time the proc is evaluated, x has a value of 2. Hence the the proc returns 2.
Let’s now check Elixir.
iex|1 ▶ quote do
...|1 ▶ x = 1
...|1 ▶ f = fn -> x end
...|1 ▶ x = 2
...|1 ▶ f.()
...|1 ▶ end
#⇒ {:__block__, [],
# [
# {:=, [], [{:x, [], Elixir}, 1]},
# {:=, [], [{:f, [], Elixir}, {:fn, [], [{:->, [], [[], {:x, [], Elixir}]}]}]},
# {:=, [], [{:x, [], Elixir}, 2]},
# {{:., [], [{:f, [], Elixir}]}, [], []}
# ]}
Last node in the second line is ours. It still contains x, but during a compilation stage this x will be evaluated to it’s currently assigned value. That said, fn -> not_x end will result in compilation error, while in ruby there could be literally anything inside a proc body, since it’ll be evaluated when called.
In other words, Ruby uses a current caller’s context to evaluate proc, while Elixir uses a closure. It grabs the context it encountered the function definition and uses it to resolve all the local variables.

For loops LUA Different Types

I wanted to learn more about for loops, as far as I know there are different types?
For instance,
for i = 1, 5 do
print("hello")
end
^ I know about this one, it's going to print hello 5 times, but there are others like the one below which I do not understand, specifically the index bit (does that mean it is number 1?) and what is the ipairs for
for index, 5 in ipairs(x) do
print("hello")
end
If there are any other types please let me know, I want to learn all of them and if you can provide any further reading I'd be more than greatful to check them out
As you can read in the Lua reference manual
3.3.5 For Statement
The for statement has two forms: one numerical and one generic.
The numerical for loop repeats a block of code while a control
variable runs through an arithmetic progression. It has the following
syntax:
stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end
Example:
for i = 1, 3 do
print(i)
end
Will output
1
2
3
You seem familiar with that one. Read the reference manual section for more details.
The generic for statement works over functions, called iterators. On
each iteration, the iterator function is called to produce a new
value, stopping when this new value is nil. The generic for loop has
the following syntax:
stat ::= for namelist in explist do block end namelist ::= Name {‘,’
Name}
Example:
local myTable = {"a", "b", "c"}
for i, v in ipairs(myTable) do
print(i, v)
end
Will ouput
1 a
2 b
3 c
ipairs is one of those iterator functions mentioned:
Returns three values (an iterator function, the table t, and 0) so
that the construction
for i,v in ipairs(t) do body end will iterate over the key–value pairs (1,t[1]), (2,t[2]), ..., up to the first nil value.
Read more about ipairs and pairs here:
https://www.lua.org/manual/5.3/manual.html#pdf-pairs
https://www.lua.org/manual/5.3/manual.html#pdf-ipairs
Of course you can implement your own iterator functions!
Make sure you also read:
Programming in Lua: 7 Iterators and the Generic for
Yes, It will print hello 5 times
According to this answer on Difference between pairs, ipairs, and next?
ipairs does the exact same thing as pairs, but with a slight twist to it.
ipairs runs through the table, until it finds a nil value, or a value that is non-existent, if that makes sense. So, if you ran the script I showed you for pairs, but just replaced pairs with ipairs, it would do the exact same thing

Ruby: evaluate string with dynamic binding of variables

I have a database of "formulas" stored as strings. Let's assume for simplicity, that each formula contains 2 variables denoted by a and b, and that the formulas are all wellformed and it is ensured that it consists only of characters from the set ()ab+-*.
At runtime, formulas are fetched from this database, and from another source, numeric values for a and b are fetched, and the formulas are evaluated. The evaluation can be programmed like this:
# This is how it works right now
formula = fetch_formula(....)
a = fetch_left_arg(....)
b = fetch_right_arg(....)
result = eval(formula)
This design works, but I'm not entirely happy with it. It requires that my program names the free variables exactly the same as they are named in the formula, which is ugly.
If my "formula" would not be a string, but a Proc object or Lambda which accepts two parameters, I could do something like
# No explicitly named variables
result = fetch_proc(...).call(fetch_left_arg(....),fetch_right_arg(....))
but unfortunately, the formulas have to be strings.
I tried to experiment in the following way: What if the method, which fetches the formula from the database, would wrap the string into something, which behaves like a block, and where I could pass parameters to it?
# This does not work of course, but maybe you get the idea:
block_string = "|a,b| #{fetch_formula(....)}"
Of course I can't eval such a block_string, but is there something similar which I could use? I know that instance_eval can pass parameters, but what object should I apply it to? So this is perhaps not an option either....
This is very nasty approach, but for simple formulas you’ve mentioned it should work:
▶ formula = 'a + b'
▶ vars = formula.scan(/[a-z]+/).uniq.join(',') # getting vars names
#⇒ "a,b"
▶ pr = eval("proc { |#{vars}| #{formula} }") # preparing proc
▶ pr.call 3, 5
#⇒ 8
Here we rely on the fact, that parameters are passed to the proc in the same order, as they appear in the formula.
If I get your question correctly, it is something that I have done recently, and is fairly easy. Given a string:
s = "{|x, y| x + y}"
You can create a proc by doing:
eval("Proc.new#{s}")
One way to avoid creating the variables in the local scope could be to use a Binding:
bind = binding
formula = fetch_formula(....)
bind.local_variable_set :a, fetch_left_arg(....)
bind.local_variable_set :b, fetch_right_arg(....)
result = bind.eval(formula)
The variables a and b now only exist in the binding, and do not pollute the rest of your code.
You can create a lambda from string, as shown below:
formula = "a + b"
lambda_template = "->(a,b) { %s }"
formula_lambda = eval(lambda_template % formula)
p formula_lambda.call(1,2)
#=> 3

Naming a variable dynamically in Ruby [duplicate]

This question already has answers here:
How to dynamically create a local variable?
(4 answers)
Closed 7 years ago.
I am trying to perform the following operation.
#i, price_0, price_1, price_2 = 0, 0, 0, 0
until #i > 2 do
if trade_history[#i]["type"] == 2
price_"#{#i}" = (trade_history[#i]["xbt_gbp"]).to_f ##NOT WORKING
end
#i += 1;
end
I cannot find anywhere online where it says that you can dynamically name a variable in Ruby. What I want to be able to do is to extract the prices of the trade_history object whenever they have a type 2. I need to be able to use the prices variables (price_0..2) to make calculations at the end of the loop. Please help! :-)
Just store the values in an array:
prices = []
3.times do |i|
history = trade_history[i]
prices << history["xbt_gbp"].to_f if history["type"] == 2
end
After this loop the prices array would hold the results and look like this:
prices
#=> e.q. [0.2, 0.4, 0.5]
Calculations can be easily done with reduce or inject:
prices.inject(:+)
#=> 1.1
I do not think this is the best way to do it, you should rather use a Hash containing the prices, but if you really want to dynamically assign the local variables you created, use binding.local_variable_set.
binding.local_variable_set("price_#{#i}", "your value")
Note that this is only available from Ruby 2.1. See How to dynamically create a local variable? for more info.
If you prefer an instance variable, you can use.
instance_variable_set("#price_#{#i}", 1)

How does the assignment operator work in Ruby?

I'm writing a simple piece of code in ruby, but it's not working the way I expect it to at all. I think this problem comes from a misunderstanding of how ruby works, specifically, how the assignment operator works, relative to other languages. Here's what I've written:
#instance1 = #clock
#clock.tick!
#clock.tick!
#clock.tick!
#instance2 = #clock
puts " instace1.seconds: #{#instance1.seconds}, instance2.seconds: #{#instance2.seconds}"
'Clock' is a class and has a value, seconds, a method 'tick!' which increases seconds by one, and a method 'seconds' which returns the seconds value. Seconds is initalized as 0.
Now when I run this code, the output is:
" instace1.seconds: 3, instance2.seconds: 3"
But the output I would expect is:
" instance1.seconds: 0, instance2.seconds: 3"
Because, I've assigned intance1 the values which #clock had before I changed clock, and I did nothing to modify #instance1 thereafter.
To me this implies that ruby assigns objects as pointers in some contexts, and that there's implicit dereferencing going on. What are these contexts? (class variables?, large objects? )
How do I make an explicit assignment? In other words, how do I dereference a variable?
Like, in C, I would do something like:
*instance1 = *c
(although it's been a long time since pointer-arithmatic, so that's a rough example
Ruby assigns by reference, not by value. What you can do is #instance1 = #clock.dup or #instance1 = #clock.clone.

Resources