İkame modelini kabaca anladığım için (referans şeffaflığı (RT) ile), bir işlevi en basit parçalarına ayırabilirsiniz. İfade RT ise, ifadeyi kaldırabilir ve her zaman aynı sonucu alabilirsiniz.
Evet, sezgi oldukça doğru. Daha kesin olmak için birkaç işaret:
Dediğiniz gibi, herhangi bir RT ifadesinin bir single"sonucu" olmalıdır. Yani, factorial(5)programda bir ifade verildiğinde , her zaman aynı "sonucu" vermelidir. Bu nedenle, factorial(5)programda belirli bir değer varsa ve 120 verirse, zamana bakılmaksızın hangi "adım sırası" genişletildiği / hesaplandığından bağımsız olarak daima 120 vermelidir .
Örnek: factorialişlev.
def factorial(n):
if n == 1:
return 1
return n * factorial(n - 1)
Bu açıklama ile ilgili birkaç husus vardır.
Her şeyden önce, farklı değerlendirme modellerinin (bkz. Uygulanabilir veya normal sıraya bakın) aynı RT ifadesi için farklı "sonuçlar" verebileceğini unutmayın.
def first(y, z):
return y
def second(x):
return second(x)
first(2, second(3)) # result depends on eval. model
Yukarıdaki kodda firstve secondreferans olarak şeffaftır ve yine de, sondaki ifade, normal düzen ve uygulanabilir düzen altında değerlendirildiğinde farklı "sonuçlar" verir (ikincisinin altında, ifade durmaz).
.... tırnak içinde "sonuç" kullanımına yol açar. Bir ifadenin durması gerekmediğinden, bir değer üretmeyebilir. Yani "sonuç" kullanmak biraz bulanık. Bir RT ifadesinin computationsbir değerlendirme modeli altında her zaman aynı sonucu verdiği söylenebilir .
Üçüncüsü, foo(50)programda farklı yerlerde iki ifadenin farklı ifadeler olarak görünmesi gerekebilir - her biri birbirinden farklı olabilecek kendi sonuçlarını verir. Örneğin, dil dinamik kapsama izin veriyorsa, her iki ifade de, sözcüksel olarak özdeş olsa da, farklıdır. Perl dilinde:
sub foo {
my $x = shift;
return $x + $y; # y is dynamic scope var
}
sub a {
local $y = 10;
return &foo(50); # expanded to 60
}
sub b {
local $y = 20;
return &foo(50); # expanded to 70
}
Dinamik kapsam misleads o kadar kolay bir düşünmek için yapmak çünkü xtek girdidir foogerçekte, o zaman, xve y. Farkı görmenin bir yolu, programı dinamik kapsamı olmayan eşdeğer bir programa dönüştürmektir - yani, parametreleri açıkça geçirerek, tanımlamak yerine , arayanları açıkça foo(x)tanımlar foo(x, y)ve yiletiriz.
Mesele şu ki, her zaman bir functionzihniyet altındayız : bir ifade için belirli bir girdi verildiğinde, buna karşılık gelen bir "sonuç" verilir. Aynı girdiyi verirsek, her zaman aynı "sonucu" beklemeliyiz.
Şimdi, aşağıdaki kod ne olacak?
def foo():
global y
y = y + 1
return y
y = 10
foo() # yields 11
foo() # yields 12
Yeniden footanımlamalar olduğundan prosedür RT'yi keser. Yani, ybir noktada tanımladık ve ikincisi de aynı şeyi yeniden tanımladık y. Yukarıdaki perl örneğinde, ys, aynı "y" harf adını paylaşsalar da farklı bağlardır. Burada ys aslında aynı. Bu yüzden atamanın bir meta işlem olduğunu söylüyoruz : aslında programınızın tanımını değiştiriyorsunuz.
Kabaca, insanlar genellikle farkı şu şekilde tasvir eder: yan etkisi olmayan bir ortamda, bir eşlemeniz vardır input -> output. "Zorunlu" bir ortamda, zaman input -> ouputiçinde statedeğişebilen bir bağlamda var .
Şimdi, ifadeleri sadece karşılık gelen değerleri yerine koymak yerine state, bunu gerektiren her işlemde de dönüşümler uygulanmalıdır (ve tabii ki ifadeler statehesaplamaları gerçekleştirmek için buna danışabilir ).
Dolayısıyla, bir yan etki serbest programında, bir ifadeyi hesaplamak için bilmemiz gereken tek şey onun bireysel girdisidir, zorunlu bir programda, her bir hesaplama adımı için girdileri ve tüm durumu bilmemiz gerekir. Akıl yürütme ilk kez büyük bir darbe çekiyor (şimdi, sorunlu bir prosedürde hata ayıklamak için, girdiye ve çekirdek dökümü gerekir). Bazı numaralar ezberleme gibi pratik değildir. Ama aynı zamanda, eşzamanlılık ve paralellik çok daha zorlaşıyor.
RTkullanmasını devre dışı bırakır sizisubstitution model.ile büyük bir sorun değil kullanmak mümkün olansubstitution modelbir program hakkında nedenden için kullanarak gücüdür?