Sorry for the confusing title. I think it's easier to understand what it means to actually look at the code than to explain it in words. Regarding the environment, Ruby is Ruby 2.0 and Python is Python 3.2.
Let's try writing this code in Ruby.
#Global variables due to scope
$msg = "Hello, Before World!"
def say(str = $msg)
puts str
end
say #=> Hello, Before World!
$msg = "Hello, After World!"
say #=> Hello, After World!
The output should be as commented.
If you write similar code in Python, it will look like this.
msg = "Hello, Before World!"
def say(str = msg):
print(str)
say() #=> Hello, Before World!
msg = "Hello, After World!"
say() #=> Hello, Before World!
The code is similar, but the output of the say
function has changed.
Did you get a general idea of the title?
First, both Ruby and Python can write arbitrary expressions in the default argument values. So, the timing when this value is evaluated is different between Ruby and Python.
In Ruby, ** when a function is called **, In Python, the value of the default argument is evaluated when ** the function is defined **.
$msg = "Hello, Before World!"
def say(str = $msg)
puts str
end
say() #=> Hello, Before World!
$msg = "Hello, After World!"
say() #=>with this timing$msg is evaluated
#=>So Hello, After World!
msg = "Hello, Before World!"
def say(str = msg): #At this point msg is evaluated Hello, Before World!It has become
print(str)
say() #=> Hello, Before World!
msg = "Hello, After World!"
say() #=>Hello because the value of str has already been decided, Before World!
So, the result is the same as before.
Personally, I think Ruby is more interesting because it can do various things, but both behaviors are * natural *, so it's not bad. (I wonder if Python has to do that because of the VM specifications)
By the way, in Ruby, you can refer to arguments other than the default argument, so by calling itself in the default argument and recursing it,
#Look, this guy recurses with the default arguments ...
def fact(n,ret = n <= 1 ? 1 : fact(n-1) * n)
ret
end
puts fact(10) #=> 3628800
You can do something like that. Ruby is ... (excuse me).
By the way, it seems that Python uses this property to replace local scope (probably).
say_n = []
for i in range(0,10):
#say_n.append(lambda: print(i))
#If so, the value of i will be updated, so it is useless
say_n.append(lambda j = i: print(j))
#I need to bind i like this
say_n[2]() #=> 2
say_n[4]() #=> 4
It was a very miscellaneous tip, but if you get hooked on such small differences in specifications for each language, you will not be able to get out of it, so I feel that it is not a loss to know. I hope you remember and find something useful.
Since both Ruby and Python are outsiders, there may be some mistakes. If you find it, I would appreciate it if you could gently bite Hatoo in the comments or on Twitter ([@ alucky0707]).