Kuşkusuz bu tür kavramları dil ve doğası, etki alanı ve hatta dili kullanma şeklimize göre C ++ 'da uygulayan bir önyargılıyım. Ama bunlar göz önüne alındığında, bence değişmez tasarımlar o iplik güvenliği, sistem hakkında akıl kolaylığı, fonksiyonlar için daha fazla yeniden kullanımını bulma (ve biz olabilir bulma gibi, fonksiyonel programlama ile ilişkili yararlar toplu hasat geldiğinde en az ilginç yönü vardır hoş olmayan sürprizler olmadan bunları herhangi bir sırada birleştirin), vb.
Bu basit C ++ örneğini alın (kuşkusuz, herhangi bir görüntü işleme uzmanının önünde kendimi utandırmaktan kaçınmak için basitlik için optimize edilmemiştir):
// Inputs an image and outputs a new one with the specified size.
Image resized_image(const Image& src, int new_w, int new_h)
{
Image dst(new_w, new_h);
for (int y=0; y < new_h; ++y)
{
for (int x=0; x < new_w; ++x)
dst[y][x] = src.sample(x / (float)new_w, y / (float)new_h);
}
return dst;
}
Bu işlevin uygulanması, yerel (ve geçici) durumu iki sayaç değişkeni ve çıktı için geçici bir yerel görüntü biçiminde değiştirirken, dış yan etkileri yoktur. Bir görüntü girer ve yeni bir görüntü verir. Bunu kalplerimizin içeriğine çoğaltabiliriz. Akıl yürütmek kolay, iyice test etmek kolaydır. İstisnai olarak güvenlidir, çünkü bir şey atılırsa, yeni görüntü otomatik olarak atılır ve harici yan etkileri geri alma konusunda endişelenmemize gerek kalmaz (tabiri caizse, işlevin kapsamı dışında değiştirilen harici görüntüler yoktur).
Image
Yukarıdaki fonksiyonun uygulanmasını daha uygunsuz ve muhtemelen biraz daha az verimli hale getirmesi dışında, yukarıdaki bağlamda, C ++ 'da değişmez hale getirilerek kazanılacak çok az ve potansiyel olarak kaybedilecek çok şey görüyorum .
Saflık
Bu yüzden saf işlevler ( dış yan etkilerden arınmış ) benim için çok ilginç ve C ++ 'da bile ekip üyelerine sık sık tercih etmenin önemini vurguluyorum. Ancak, genellikle bağlam ve nüans olmadan uygulanan değişmez tasarımlar benim için neredeyse ilginç değil, çünkü dilin zorunlu doğası göz önüne alındığında, bazı yerel geçici nesneleri verimli bir şekilde mutasyona uğratmak genellikle yararlı ve pratiktir (her ikisi de geliştirici ve donanım için).
Ağır Yapıların Ucuz Kopyalanması
Bulduğum ikinci en kullanışlı özellik, sık sık giriş / çıkış doğası göz önüne alındığında, işlevleri saf hale getirmek için sık sık olacağı gibi, gerçekten ağır veri yapılarını ucuza kopyalama yeteneğidir. Bunlar yığına sığabilecek küçük yapılar olmazdı. Scene
Bir video oyunu için olduğu gibi büyük, ağır yapılar olurdu .
Bu durumda kopyalama yükü, etkili paralellik fırsatlarını önleyebilir, çünkü fizik, oluşturucunun eşzamanlı olarak çizmeye çalıştığı sahneyi eşzamanlı olarak fizik yaparken mutasyona uğratıyorsa, fiziği birbirine kilitlemeden ve darboğaz yapmadan etkili bir şekilde paralel hale getirmek ve verimli hale getirmek zor olabilir. tüm oyun sahnesini kopyalamak, fizik uygulanan bir kareyi çıktılamak için eşit derecede etkisiz olabilir. Ancak, fizik sistemi sadece bir sahne girmesi ve fizik uygulanan yeni bir sahne çıkarması anlamında 'saf' olsaydı ve bu saflık astronomik kopyalama yükü pahasına gelmediyse, güvenli bir şekilde paralel olarak çalışabilirdi. biri diğerini beklemeden render.
Böylece, uygulama durumunuzun gerçekten ağır verilerini ucuza kopyalama ve işleme ve bellek kullanımı için minimum maliyetle yeni, değiştirilmiş sürümler çıktılama yeteneği, saflık ve etkili paralellik için yeni kapılar açabilir ve orada öğrenecek çok ders buluyorum kalıcı veri yapılarının nasıl uygulandığından Ancak bu tür dersleri kullanarak yarattığımız her şeyin tamamen kalıcı olması veya değişmez arayüzler sunması gerekmez (bu, ucuza dönüşme yeteneğini elde etmek için, üzerine yazılırken kopyala veya bir "kurucu / geçici" kullanabilir). işlevlerimiz / sistemlerimiz / boru hattımızdaki paralellik ve saflık arayışımızda bellek kullanımını ve bellek erişimini ikiye katlamadan kopyalamanın yalnızca bölümlerini değiştirmek ve değiştirmek.
değişmezlik
Son olarak, bu üçünden en az ilginç olduğunu düşündüğüm değişmezlik var, ancak bazı nesne tasarımlarının saf bir işleve yerel geçişler olarak kullanılması amaçlanmadığında ve daha geniş bir bağlamda, değerli bir demir yumrukla zorlayabilir. tüm yöntemlerde olduğu gibi artık harici yan etkilere neden olmaz (artık yöntemin hemen yerel kapsamı dışında üye değişkenleri değiştirmez).
C ++ gibi dillerde bu üçünün en az ilginç olduğunu düşünürken, kesinlikle önemsiz olmayan nesnelerin test edilmesini ve iş parçacığı güvenliğini ve mantığını basitleştirebilir. Örneğin, bir nesneye yapıcısının dışında herhangi bir benzersiz durum kombinasyonu verilemeyeceği ve sabitlik ve okumaya dayanmadan referans / işaretçi ile bile özgürce aktarabileceğimiz garantisiyle çalışmak bir yük olabilir. sadece yineleyiciler ve kulplar ve benzeri, orijinal içeriğinin mutasyona uğramayacağını garanti ederken (en azından dil içinde olabildiğince iyi).
Ama bunu en az ilginç olan özellik olarak görüyorum çünkü çoğu nesneyi geçici olarak, değiştirilebilir biçimde, saf bir işlevi (veya bir nesne veya dizi olabilecek bir "saf sistem" gibi daha geniş bir konsepti uygulamak için başka bir şeye dokunmadan sadece bir şey girmenin ve yeni bir şey çıkarmanın nihai etkisi ile işlev görür) ve bence aşırı derecede zorunlu bir dilde ekstremitelere taşınan değişmezlik oldukça karşı-üretken bir hedef. Kod tabanının gerçekten en çok yardımcı olduğu kısımlar için idareli bir şekilde uygularım.
En sonunda:
[...] kalıcı veri yapılarının kendi içlerinde bir iş parçacığının diğer iş parçacıkları tarafından görülebilir bir değişiklik yaptığı senaryoları işlemek için yeterli olmadığı görülüyor. Bunun için atomlar, referanslar, yazılım işlem belleği, hatta klasik kilitler ve senkronizasyon mekanizmaları gibi cihazları kullanmamız gerektiği görülmektedir.
Doğal olarak, tasarımınız değişikliklerin (kullanıcı sonu tasarım anlamında) meydana geldiğinde aynı anda birden çok iş parçacığına görünmesini gerektiriyorsa, senkronizasyona veya en azından çizim tahtasına bununla başa çıkmanın bazı karmaşık yollarını bulmak için geri dönüyoruz ( Fonksiyonel programlamada bu tür problemlerle uğraşan uzmanlar tarafından kullanılan çok ayrıntılı örnekler gördüm).
Ama buldum, bu tür bir kopyalama ve iri yapıların kısmen değiştirilmiş versiyonlarını çıkarma kabiliyetini elde ettikten sonra, örnek olarak kalıcı veri yapıları ile alacağınız gibi, genellikle çok sayıda kapı ve fırsat açıyor daha önce katı bir G / Ç tür paralel boru hattında birbirinden tamamen bağımsız olarak çalışabilen kodu paralelleştirmeyi düşünmemiştim. Algoritmanın bazı bölümleri doğada seri olmak zorunda olsa bile, bu işlemi tek bir iş parçacığına erteleyebilir, ancak bu kavramlara yaslanmanın, endişe duymadan, ağır işlerin% 90'ını paralelleştirdiğini görebilirsiniz.