Saf fonksiyon - Pure function
Gelen bilgisayar programlama , bir saf fonksiyon bir olduğunu fonksiyonu aşağıdaki özelliklere sahiptir:
- İşlev dönüş değerleri , özdeş bağımsız değişkenler için aynıdır (yerel statik değişkenler , yerel olmayan değişkenler , değiştirilebilir başvuru bağımsız değişkenleri veya giriş akışları ile değişiklik yok ).
- İşlev uygulamasının hiçbir yan etkisi yoktur (yerel statik değişkenlerin mutasyonu, yerel olmayan değişkenler, değiştirilebilir referans argümanları veya giriş/çıkış akışları).
Böylece saf bir fonksiyon, matematiksel bir fonksiyonun hesaplamalı bir analogudur . Bazı yazarlar, özellikle zorunlu dil topluluğundan, "saf" terimini, yalnızca yukarıdaki 2 özelliğine sahip olan tüm işlevler için kullanır ( aşağıda tartışılmıştır ).
Örnekler
Saf fonksiyonlar
Aşağıdaki C++ işlevleri örnekleri saftır:
-
floor, bir sayının tabanını döndürmek ; -
max, maksimum iki değer döndürülür. - f fonksiyonu olarak tanımlanır
Bu kod örneği saf değil gibi görünse de aslında öyle. Değeri
void f() { static std::atomic<unsigned int> x = 0; ++x; }
xsadece diğer çağrıları içine görülebilirf()ve aynıf()değerini iletişim kurmazxçevresine, bu işlevinden farksızdırvoid f() {}hiçbir şey yapmaz. Notxolanstd::atomicyürütme birden çok iş parçacığı bir değişiklik, bu yüzdenf()aynı zamanda bir sonuçlanmayan veri ırk sahiptir, tanımsız davranış C ve C ++.
saf olmayan fonksiyonlar
Aşağıdaki C++ işlevleri, yukarıdaki özellik 1'den yoksun oldukları için saf değildir:
- statik bir değişkenle dönüş değeri değişimi nedeniyle
int f() { static int x = 0; ++x; return x; }
- yerel olmayan bir değişkenle dönüş değeri değişimi nedeniyle
Aynı nedenle, örneğin C++ kitaplığı işlevi
int f() { return x; }
sin()saf değildir, çünkü sonucu çalışma zamanında değiştirilebilen IEEE yuvarlama moduna bağlıdır . - değiştirilebilir bir referans argümanı ile dönüş değeri değişimi nedeniyle
int f(int* x) { return *x; }
- bir giriş akışı ile dönüş değeri değişimi nedeniyle
int f() { int x = 0; std::cin >> x; return x; }
Aşağıdaki C++ işlevleri, yukarıdaki özellik 2'den yoksun oldukları için saf değildir:
- yerel bir statik değişkenin mutasyonu nedeniyle
void f() { static int x = 0; ++x; }
- yerel olmayan bir değişkenin mutasyonu nedeniyle
void f() { ++x; }
- değişken bir referans argümanının mutasyonu nedeniyle
void f(int* x) { ++*x; }
- bir çıkış akımının mutasyonu nedeniyle
void f() { std::cout << "Hello, world!" << std::endl; }
Aşağıdaki C++ işlevleri, yukarıdaki özellikler 1 ve 2'nin her ikisinden de yoksun oldukları için saf değildir:
- yerel bir statik değişken ile dönüş değeri değişimi ve yerel bir statik değişkenin mutasyonu nedeniyle
int f() { static int x = 0; ++x; return x; }
- bir giriş akışındaki dönüş değeri değişimi ve bir giriş akışının mutasyonu nedeniyle
int f() { int x = 0; std::cin >> x; return x; }
Saf fonksiyonlarda I/O
G/Ç doğası gereği saf değildir: girdi işlemleri bilgi şeffaflığını baltalar ve çıktı işlemleri yan etkiler yaratır. Bununla birlikte, ilgili G/Ç aygıtlarındaki işlemlerin sırası hem bir argüman hem de bir sonuç olarak açıkça modellenirse ve G/Ç işlemleri, giriş veya çıkış gerçekleştirebilir ve yine de saf olabilir. giriş dizisi, program yürütmeye başladığından beri gerçekleştirilen işlemleri gerçekten açıklamadığında başarısız olur.
İkinci nokta, bağımsız değişken olarak kullanılabilen tek sıranın her G/Ç eylemiyle değişmesini sağlar; ilki, değişen dizi argümanları nedeniyle farklı sonuçlar döndürmek için bir G/Ç gerçekleştirme işlevine yapılan farklı çağrılara izin verir.
I / O atom a, programlama deyim tipik olarak saf fonksiyonel dilde I / O gerçekleştirmek için kullanılır.
Derleyici optimizasyonları
Sadece yukarıdaki 2 özelliğine sahip fonksiyonlar, aritmetik operatörlere benzer ortak alt ifade eliminasyonu ve döngü optimizasyonu gibi derleyici optimizasyon tekniklerine izin verir . Bir C++ örneği, lengthdizenin işaret ettiği bellek içeriğine bağlı olan, dolayısıyla yukarıdaki özellik 1'den yoksun bir dize boyutunu döndüren yöntemdir. Bununla birlikte, tek iş parçacıklı bir ortamda aşağıdaki C++ kodu
std::string s = "Hello, world!";
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int l = 0;
for (int i = 0; i < 10; ++i) {
l += s.length() + a[i];
}
değeri s.length()döngüden önce yalnızca bir kez hesaplanacak şekilde optimize edilebilir .
Bazı programlama dilleri, bir işleve saf bir özellik bildirmeye izin verir:
- Gelen Fortran ve D,
pureanahtar (yani, yukarıdaki özelliği var 2) sadece yan etkisi serbest olduğu bir işlev bildirmek için kullanılabilir. Derleyici, bildirimin üstünde özellik 1'i çıkarabilir. - In GCC ,
puresüre niteliği belirtir mülkiyet 2,constniteliği her iki özelliklere sahip gerçekten saf işlevi belirtir. - Derleme zamanı işlev yürütmesi sunan diller , bazen başka kısıtlamaların eklenmesiyle işlevlerin saf olmasını gerektirebilir. Örnekler arasında
constexprC++ (her iki özellik) bulunur.
Birim testi
Saf işlevlerin aynı argümanlar için aynı dönüş değerleri olduğundan , bunlar birim testine çok uygundur .
Ayrıca bakınız
- Derleme zamanı işlevi yürütme : derleme zamanında saf işlevlerin değerlendirilmesi
- deterministik algoritma
- Tamamen işlevsel veri yapısı
- Lambda hesabı
- Yan etki (bilgisayar bilimi)
- saf prosedür
- iktidarsızlık
- Fortran'da saf işlevlere açıklama ekleyen saf anahtar kelime
- derleme zamanında kullanılabilen saf işlevleri açıklayan C++'da constexpr anahtar sözcüğü