I'm trying to understand the concept of Ruby as a pass-by-reference-value language. Using an example I found on this site...
def uppercase(value)
value.upcase!
end
name = 'William'
uppercase(name)
puts name
we get the output "WILLIAM". So value and name are both pointing at the same object, which is initially holding a value of "William" and then .upcase changes it to "WILLIAM". I would understand this as pass-by-reference.
But then if I change .upcase to =:
def uppercase2(value)
value = "WILLIAM"
end
name = 'William'
uppercase2(name)
puts name
The output becomes "William". Which is pass by value.
Why does an assignment operator make the difference in how a variable is treated in Ruby?
The key here is that you can never change a Ruby object's core self, once it has been created it will always be the same object until garbage collected and destroyed. It is only possible to alter properties of the object.
You can, however, change variables or object references such as instance variables, constants, attr_accessor properties among other things.
So in this case:
def uppercase2(value)
value = "WILLIAM"
end
This reassigns the value local variable. It does nothing to the original object.
If you want to replace that text you need to use methods on the object to effect it, if supported. In this case there is a method:
def uppercase2(value)
value.replace("WILLIAM")
end
These are generally termed in-place modifications as in the object itself is manipulated rather than swapped for another object.
I'm trying to understand the concept of Ruby as a pass-by-reference-value language.
Ruby is pass-by-value. Always. It is never pass-by-reference. The value that is being passed is an immutable unforgeable pointer, but that is very different from pass-by-reference.
C is pass-by-value. And C has pointers. That doesn't mean that if you pass a pointer in C, it magically becomes pass-by-reference. It is still pass-by-value.
C++ has pointers, and it supports both pass-by-value and pass-by-reference. In C++, you can pass pointers by value or by reference and you can pass non-pointers by value or by reference. The two concepts are completely orthogonal.
If we can agree that C is pass-by-value, and we can agree that C has pointers, and we can agree that when we pass a pointer in C, that is still pass-by-value, then we must also agree that Ruby is pass-by-value, because Ruby behaves like a hypothetical version of C, where the only allowed types are "pointer to something", the only way to access a value is dereferencing the pointer, and the only way to pass a value is taking the pointer.
That does not change parameter passing in C in any way, which means it is still pass-by-value, which means if we call that in C pass-by-value, it doesn't make sense to call it anything else in Ruby.
def uppercase(value)
value.upcase!
end
name = 'William'
uppercase(name)
puts name
we get the output "WILLIAM". So value and name are both pointing at the same object, which is initially holding a value of "William" and then .upcase changes it to "WILLIAM". I would understand this as pass-by-reference.
Again, this is not pass-by-reference. Pass-by-reference would mean that you can change the reference in the caller's scope, which Ruby does not allow you to do.
This is nothing but simple mutation. Ruby is not a purely functional language, it does allow you to mutate objects. And when you mutate an object, you can observe its changed state regardless of what name you call it.
My friends call me "Jörg" but my barber calls me "Mr. Mittag". When my barber cuts my hair, it doesn't magically grow back when I meet my friends, it will still be gone even though they don't refer to me by the same name as my barber does.
You have two names for the same object, and you mutate that object. You will observe the new state regardless of which name you use to refer to that object.
That is simply "mutable state", it has nothing to do with pass-by-reference.
But then if I change .upcase to =:
def uppercase2(value)
value = "WILLIAM"
end
name = 'William'
uppercase2(name)
puts name
The output becomes "William". Which is pass by value.
Why does an assignment operator make the difference in how a variable is treated in Ruby?
It doesn't. Both cases are pass-by-value. In the second case, you created a new object and assigned it to the local variable value inside the uppercase2 method. (Technically, it is not a local variable, it is a parameter binding, but it can be rebound inside the method body, precisely because Ruby is pass-by-value. If it were pass-by-reference, then this would have also reassigned the name local variable to the newly created object.)
Sometimes, this specific case of pass-by-value, where the value being passed is an immutable pointer to a potentially mutable object is called call-by-object-sharing, call-by-sharing, or call-by-object. But that is not something different from pass-by-value. It is still pass-by-value. It is a special case of pass-by-value, where the value cannot be "any value" but is always "an immutable unforgeable pointer".
Sometimes, you will hear the description "Ruby is pass-by-value where the value that is being passed is a reference" or "Ruby is pass-by-reference-value" or "Ruby is pass-by-value-reference" or "Ruby is pass-by-object-reference". I don't really like these terms, because they sound very close to "pass-by-reference", but actually the term "reference" in "pass-by-reference" and the term "reference" in "pass-by-object-reference" mean two different things.
In "pass-by-reference", the term "reference" is a technical term that can be thought of as a generalization of the concept of "variable", "storage location", etc. Wheres in "pass-by-value-reference", we are talking about "object references", which are more like pointers but cannot be manufactured or changed.
I also don't like the terms that I used above "pass-by-value where the value being passed is an immutable unforgeable pointer", because the term "pointer" has certain connotations, especially for people coming from C. In C, you can do pointer arithmetic, and you can cast a number to a pointer, i.e. you can "conjure up a pointer out of thin air". You can do none of that in Ruby. That's why I add the adjectives "immutable" (no arithmetic) and "unforgeable" (you cannot create a pointer, only be handed one by the system), but people overlook or ignore them or underestimate their importance.
In some languages, these immutable unforgeable pointers to objects are called "object references" (which is again dangerous because it invites confusion with "pass-by-reference") or OOPS (Object-Oriented PointerS) which has the unfortunate connotations of the mostly unrestricted free-for-all "C" pointers. (Go, for example, has much more restrictive pointers, but when you simply say the word "pointer", nobody thinks of Go.)
Note that none of this is really specific to Ruby. Python, ECMAScript, Java, and many others behave the same way. C# behaves the same way by default, but also supports pass-by-reference as an explicit opt-in. (You must explicitly request pass-by-reference both at the method definition and at the method call.) Scala behaves the same way by default, but optionally supports call-by-name.
C# is actually a very good way of demonstrating the distinctions, because C# supports both pass-by-value and pass-by-reference, both value types and reference types, and obviously, you can write types both as mutable and immutable types, so you actually get all 8 possible different combinations and you can study how they behave.
I came up with this simple test code, which you can easily translate into other languages as well:
def is_ruby_pass_by_value?(foo)
foo.replace('More precisely, it is call-by-object-sharing!')
foo = 'No, Ruby is pass-by-reference.'
end
bar = 'Yes, of course, Ruby *is* pass-by-value!'
is_ruby_pass_by_value?(bar)
p bar
# 'More precisely, it is call-by-object-sharing!'
Here is the slightly more involved example in C#:
struct MutableCell { public string value; }
static void ArgumentPassing(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
bar.value = "For value types, it is *not* call-by-sharing.";
bar = new MutableCell { value = "And also not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
}
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
var grault = "This string will vanish because of pass-by-reference.";
var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
ArgumentPassing(quux, corge, ref grault, ref garply);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(corge.value);
// For value types it is pure pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
Console.WriteLine(garply.value);
// Pass-by-reference is supported for value types as well.
Let's start breaking this down in something more understandable.
You can compare a variable like name (or value) with a signpost.
Let's say I point it to the a beige house, which will be the value of the variable.
With the above in mind let's take a look at the first example:
# don't worry about this line for now
House = Struct.new(:color)
def color_red(value)
value.color = :red
end
house = House.new(:beige)
color_red(house)
puts house
# prints: #<struct House color=:red>
So what happens here? When we pass house as parameter to color_red Ruby will copy our signpost and assign it to value. Now both signposts point to the same house. We then follow the directions of signpost value and walk to the house and paint it red.
For this reason the color of house will end up being red.
Now let's have a look at the other example:
def color_red(value)
value = House.new(:red)
end
house = House.new(:beige)
color_red(house)
puts house
# prints: #<struct House color=:beige>
Here we start of the same, we copy our signpost house and assign the copy to value. However instead of walking up to the house and painting it, we are going to modify the signpost and point it to a red house somewhere further down the street. And because our signpost value is a copy of house, pointing it in a new direction will not effect house.
Your code is doing the same thing. When you call value.upcase! you are saying to she string. Hey you, upcase all your characters! (Similar to painting the house.)
When you reasign value (value = "WILLIAM") you are essentially just modifying the signpost and pointing it to a new direction. However the signpost is passed as a copy so it does not effect the original.
def uppercase(value)
value.upcase!
end
name = 'William'
uppercase(name)
puts name #WILLIAM
In this case, you are mutating the original object. name points to William
and so does value. When you pass in the argument, Ruby will assign
the parameter variable value to the same object that name is pointing to.
def uppercase2(value)
value = "WILLIAM"
end
name = 'William'
uppercase2(name)
puts name
In this case, you are reassigning value. That is, you are changing which
object value is pointing to. It was pointing to the same string object that
name was pointing to. But, now, you are asking value to reference a
different object.
So, in summary, upcase! mutates the object while = will re-assign.
You can think of 3 circles, value is in one, name in another and William
in the third.
value and name both point to the string object, William.
In the first situation, you mutate the string object that both value and name
are pointing to.
In the second situation, you are creating a 4th circle, which has WILLIAM in it. Then you are erasing the line from value to William and creating a line
from value to WILLIAM.
You get the idea if I do this:
def uppercase2(value)
value = "WILLIAM"
puts value
end
name = 'William'
uppercase2(name) # => “WILLIAM”
puts name # William
I'm wanting to modify a variable in place, replicating the methodname! syntax as opposed to reassigning a new modified value to the same var. Can I do this with a proc? I'm still learning procs and see them as quite useful is used properly.
a = "Santol bag 85.88 www.example.com/products/16785
Shaddock kg 2.94 www.example.com/products/4109
Palm Fig 5kg 94.34 www.example.com/products/23072
Litchee lb 95.85 www.example.com/products/2557"
a = a.split("\n")
linebreak = Proc.new { |text| text.split("\n") }
linebreak![a]
that first reassignment seems cumbersome. The proc version I would like to see if I can perform it inline. Is this possible?
This is surely possible, you just need to modify the string inplace
linebreak = ->(text) { text.replace text.split("\n").join(",") }
a = "foo\nbar"
linebreak[a]
#⇒ "foo,bar"
a
#⇒ "foo,bar"
What is not possible, is to change the class in place, that’s why split won’t work (called on a string, it returns an array.)
methodname! is just a convention - usually there are two flavours of the same method - one without bang and one with bang. If you want to have a proc that mutates its params, you need to implement it using mutating methods.
And in this case it's not possible, because you're trying to transform a string into an array. You have to reassign the variable:
linebreak = Proc.new { |text| text.split("\n") }
a = linebreak.call(a)
I've been practicing some Ruby meta-programming recently, and was wondering about assigning anonymous classes to constants.
In Ruby, it is possible to create an anonymous class as follows:
anonymous_class = Class.new # => #<Class:0x007f9c5afb21d0>
New instances of this class can be created:
an_instance = anonymous_class.new # => #<#<Class:0x007f9c5afb21d0>:0x007f9c5afb0330>
Now, when the anonymous class is assigned to a constant, the class now has a proper name:
Foo = anonymous_class # => Foo
And the previously created instance is now also an instance of that class:
an_instance # => #<Foo:0x007f9c5afb0330>
My question: Is there a hook method for the moment when an anonymous class is assigned to a constant?
There are many hooks methods in Ruby, but I couldn't find this one.
Let's take a look at how constant assignment works internally. The code that follows is extracted from a source tarball of ruby-1.9.3-p0. First we look at the definition of the VM instruction setconstant (which is used to assign constants):
# /insns.def, line 239
DEFINE_INSN
setconstant
(ID id)
(VALUE val, VALUE cbase)
()
{
vm_check_if_namespace(cbase);
rb_const_set(cbase, id, val);
INC_VM_STATE_VERSION();
}
No chance to place a hook in vm_check_if_namespace or INC_VM_STATE_VERSION here. So we look at rb_const_set (variable.c:1886), the function that is called everytime a constant is assigned:
# /variable.c, line 1886
void
rb_const_set(VALUE klass, ID id, VALUE val)
{
rb_const_entry_t *ce;
VALUE visibility = CONST_PUBLIC;
# ...
check_before_mod_set(klass, id, val, "constant");
if (!RCLASS_CONST_TBL(klass)) {
RCLASS_CONST_TBL(klass) = st_init_numtable();
}
else {
# [snip], won't be called on first assignment
}
rb_vm_change_state();
ce = ALLOC(rb_const_entry_t);
ce->flag = (rb_const_flag_t)visibility;
ce->value = val;
st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
}
I removed all the code that was not even called the first time a constant was assigned inside a module. I then looked into all the functions called by this one and didn't find a single point where we could place a hook from Ruby code. This means the hard truth is, unless I missed something, that there is no way to hook a constant assignment (at least in MRI).
Update
To clarify: The anonymous class does not magically get a new name as soon as it is assigned (as noted correctly in Andrew's answer). Rather, the constant name along with the object ID of the class is stored in Ruby's internal constant lookup table. If, after that, the name of the class is requested, it can now be resolved to a proper name (and not just Class:0xXXXXXXXX...).
So the best you can do to react to this assignment is to check the name of the class in a loop of a background worker thread until it is non-nil (which is a huge waste of resources, IMHO).
Anonymous classes don't actually get their name when they're assigned to a constant. They actually get it when they're next asked what their name is.
I'll try to find a reference for this. Edit: Can't find one, sorry.
In the Lua language, I am able to define functions in a table with something such as
table = { myfunction = function(x) return x end }
I wondered if I can created methods this way, instead of having to do it like
function table:mymethod() ... end
I am fairly sure it is possible to add methods this way, but I am unsure of the proper name of this technique, and I cannot find it looking for "lua" and "methods" or such.
My intention is to pass a table to a function such as myfunction({data= stuff, name = returnedName, ?method?init() = stuff}).
Unfortunately I have tried several combinations with the colon method declaration but none of them is valid syntax.
So...anyone here happens to know?
Sure: table:method() is just syntactic sugar for table.method(self), but you have to take care of the self argument. If you do
tab={f=function(x)return x end }
then tab:f(x) won't work, as this actually is tab.f(tab,x) and thus will return tab instead of x.
You might take a look on the lua users wiki on object orientation or PiL chapter 16.
Extract Method (a refactoring from Fowler's book) works great if your method doesn't assign any values. If it assigns one value, that becomes the return value of the extracted method. What if it assigns two values?
Some C# code to illustrate:
private void someBigFunction() {
doSomething();
doSomethingElse();
// start extraction here
string first = Database.Select(...);
// ...
// next is dependent on the value of "first"
int next = Database.Select(...);
// ...
// stop extraction here
doMoreUselessStuff();
}
The exact code or values are not important here. The point is extracting this method. (The two values are linked, so it makes sense to have them in the same method -- and not to make two methods.)
Possible answers to this question would be "return both in an array," "return them both in a pair-like data structure," or "use out parameters (pass by reference)" -- but I'm looking for something cleaner. (The actual code is in Delphi, not C#)
Perhaps Sprout Class is what you're looking for. Make the two members instance variables of a new class and extract this method into that class, assigning the instance variables and providing getters for the caller. Or, of course, you could convert the local variables to be instance variables of the original class. That conversion frequently makes Extract Method easier, but you wind up with what is arguably an excess of instance variables. With Sprout class, you have a class whose only purpose is to retrieve and provide those values, so there's no question that they deserve to be instance variables in it.