Domyślne przypisanie w wywołaniu funkcji

To, że w Rubim można przypisywać wartości domyślne do parametrów w wywołaniu funkcji oczywiste jest chyba dla wszystkich.
Natomiast pewnie niewielu z was zastanawiało się jak następuje ewaluacja wyrażeń w definicji.
Okazuje się, że wszystko dzieje się standardowo, tzn. od lewej do prawej, ale co ciekawsze, w trakcie przypisywania wartości domyślnych można korzystać z parametrów stojących na lewo od danego parametru.

Dlatego coś takiego uchodzi w Rubim:

[code=ruby]def fun(a,b=Array.new(a.size,false))
puts a.join(", “)
puts b.join(”, ")
end

fun([1,2,3])

1, 2, 3

false, false, false[/code]

Co więcej, można dopuścić się takiej perwersji:

[code=ruby]def fun(a,b=Array.new(a.size,false),c=b.map{|e| not e})
puts a.join(", “)
puts b.join(”, “)
puts c.join(”, ")
end
fun([1,2,3])

1, 2, 3

false, false, false

true, true, true[/code]

Szczerze powiedziawszy dopiero dzisiaj wpadłem, żeby to sprawdzić i zadziałało :slight_smile: Oczywiście nie należy tego stosować bez dobrego uzasadnienia (w szczególności drugi sposób konstruowania parametrów funkcji jest już bardzo “hackerski”), ale czasami może się przydać (np. przy wywołaniach rekurencyjnych, w których chcemy mieć tą samą funkcję wywoływaną z zewnątrz z krótką listą parametrów, oraz rekurencyjnie z dużo dłuższą listą parametrów).

Dla uzupełnienia dodam że ewaluacja następuje w momencie wywoływania metody, a kontekstem jest ten obiekt na którym wywołano metodę (czyli mówiąc prościej “self” wskazuje na odbiorcę). Zatem można ustalać domyślną wartość parametrów nie tylko na podstawie stałych, ale także na podstawie wywołań metod, np:

[code=ruby]class Foo
def i_am_random
return rand(10)
end

def foo(a = 1, b = self.i_am_random)
puts [a, b]
end
end

Foo.new.foo
Foo.new.foo
Foo.new.foo
Foo.new.foo[/code]
Jako ciekawostkę podam, że rubinius początkowo inaczej podchodzić do tego zagadnienia (bodajże ewaluował parametry z prawej do lewej) i musieli to potem przerobić żeby było zgodne ze specyfikacją rubiego. Źródło: http://betterruby.wordpress.com/2008/04/11/shotgun-rewrite-underway/