5

içinde saf işlevleri Algoritmik olarak tanımlamak javascript kullanarak javascript işlevi "saf" olup olmadığını belirlemek mümkün mü?Javascript

bir fonksiyon, her x için, işlev her zaman aynı ilişkili y değerini (yani, bir tek değerli harita) döner anlamda, tahmin edilebilir bir şekilde davranır zaman saf olduğu söylenir. Örneğin

, saf fonksiyonu:

function pure(x) { 
    return x * x; 
} 

Ve saf olmayan:

var x = 0; 
function impure(y) { 
    x = x + y; 
    return x++; 
} 

o, bir fonksiyonu gibi gibi belirgin değildir impure(0) !== impure(0) burada söylemek kolay olsa :

( )
var count = 0; 
function surprise(x) { 
    count++; 
    if (count === 10e10 && x === 0) { 
    return true; 
    } else { 
    return false; 
    } 
} 

Bunu sormanın başka bir yolu da, javascript kullanarak javascript işlevinin "impure" olup olmadığını belirlemek mümkün müdür?

Teorik olarak mümkün veya imkansız olabilir, fakat pratik olarak bunu belirlemek için hangi adımları atmaya başlayabiliriz, belki de bir dizi kısıtlama veya varsayımdan bahsedilebilir mi?

Diğer bir saflık tanımı, yerel olmayan değişkenlerin değiştirilemeyeceği uyarısını içerir, ancak ayrı bir sorun olduğunu düşünmek isterim. Bu durumda, tutarlı girdileri tutarlı çıktılarla eşleyen fonksiyonlar düşünmekteyiz.

+0

Teorik olarak? Emin. Pratikte? Fikrim yok. Birisi böyle bir şey yapmak için bir ayrıştırıcı yazmış olabilir. Bir ayrıştırma ağacı oluşturun, kesin olmayan şeyleri * bilinen * işaretleyin (örn. Math.random() '), sonra yolunuzu çalışın. Birisinin bunu yapmak için bir araç yazıp yazmadığını görmek ilginç olurdu. – thetoast

+0

Bu, işlevin kaynak koduna bakmadan belirlenip belirlenemeyeceğini soruyor musunuz? Ya da hangi girişlere izin verilir? Kesinlikle bir kişi, kodu inceleyebilir ve uygunsuz davranışlara sahip olabileceği herhangi bir koşul olup olmadığını belirleyebilir. Yani, bir bilgisayarın size bunu söylemek için kod üzerinde çalışıp çalışamayacağını mı soruyorsunuz? – jfriend00

+4

İlgili: http://programmers.stackexchange.com/questions/176761/compute-if-a-function-is-pure - nutshell sürümü, bunu yapmak için durma sorunu çözmek zorunda. – jdphenix

cevap

3

JavaScript, Turing complete olup, JavaScript'in diğer programlama dilleri gibi ayrıştırılıp analiz edilebilmesidir. Yani, soru gerçekten: "JavaScript işlevleri otomatik olarak" saflık "için otomatik olarak test edilebilir mi?"

Kısa cevap

Sadece bazen.

AST kesinlikle yalındır ve tüm semboller içerdiği kendisi için bazı işlevler için

Uzun cevap. function(X) { return X * X; } gibi bir şey, progresif olarak saftır ( ilkel giriş için ) çünkü işlev gövdesinde kullanılan tek değişkenler, işlev bağımsız değişkenleri olarak iletilen değişkenlerdir. Bu işlev herhangi bir ek API çağrısına dayanmaz, ancak saf aritmetikler. Kesinlikle saf olduğunu gösterebiliriz.

Rastgele içeriğe izin verdiğimizde işler değişir, çünkü JavaScript'in açık türleri yoktur ve bunun yerine karmaşık olmayandan ilkel veri türüne (veya ilkelden ilkel veri türüne) sahip olmayan bir işlem gerçekleştirmesi gerektiğinde, will happily type-coerce Bu işlem uygulandı. Yukarıdaki işlevi bir sayı yerine bir nesne ile çağırmak, sualtında daha fazla işlev çağrısı yapar ve bu işlevler tamamen garanti edilmez (bkz. Andrea'nın bu yanıtı)

JS işlevlerinin büyük çoğunluğu bizim basit işlevimiz.Çoğu fonksiyon için, yalnızca saf olduklarını değil, aynı zamanda dahili olarak adlandırdıkları tüm fonksiyonların da saf olduğunu kanıtlamalıyız. Şimdi halting problem'a koşuyoruz. Gülünç bir örnek alalım:

function(x) { 
    if (typeof window !== "undefined") { 
    return x * x; 
    } 
    return x * x * x; 
} 

Bu saf mı? Tarayıcıda bu koşuyu çalıştırırsak, numaralı tarayıcıda , her zaman sıfırdır, çünkü window her zaman tanımlanmıştır. Ama Node.js gibi bir şeyde, olabilir, ama olmayabilir: ispatlayamaz, ne de kanıtlayamazız, çünkü bu gizemli window değişkeninin fonksiyonda olduğunu ispatlayamayız koşar. Node.js'nin global window değişkenine sahip olmasa da, istediğimiz zaman bir tanesini kolayca ekleyebiliriz ve fonksiyonun davranışı değişebilir. Şimdi aniden kodumuzun bütününün window değişkenini (global["win" + _abc] = true gibi _abc dizgesi "dow" olduğu gibi) yapıp yapamayacağını kanıtlamakla karşı karşıyayız. Bu kayıp bir sebep.

Tavşan deliği derinleşir ve durma problemini okumak, durma problemine karşı kaç farkın bulunduğunu anlamanızı sağlar. JavaScript * yılında x kullanıcı tanımlı toString veya valueOf yöntemle bir nesne olmak olur, keyfi kullanıcı kodu çağırmak olabilen bir ToNumber dönüşüm, çağırmak ya da biri oldu çünkü

+0

Maalesef, ilk işlev, aslında, ya saf değil. Cevabımı görün. –

+0

iyi nokta, cevap değiştirildi. –

2

Hatta ilk fonksiyonu, saf değil maymun yama Object.prototype için.

Üzücü gerçek şu ki, JS'de neredeyse hiçbirinin saf olduğu kanıtlanabilir. Hiçbir zaman yan etkisi olmayan tek operasyonlar ===, !==, !, &&, || ve typeof'dur. Bu derleyicilerdeki optimizasyonlar için büyük bir sorun, btw.

+0

Örnek: http://jsfiddle.net/9kf6ywmn/ – Oriol