İade zararlı olarak kabul edilir? Kod, onsuz işlevsel olabilir mi?


45

Tamam, bu yüzden başlık biraz tıkanma ama ciddi bir şekilde söylüyorum, bir süre tekme sorma . Mesajları , gerçek nesne yönelimli biçimde kullanılmaya teşvik etmeyi seviyorum . Ama bunun kafamda karmakarışık olan bir dırdır sorunu var.

İyi yazılmış bir kodun OO ilkelerini ve işlevsel ilkelerini aynı anda izleyebileceğinden şüphelenmeye başladım. Bu fikirleri uzlaştırmaya çalışıyorum ve indiğim en büyük yapıştırma noktası return.

Saf fonksiyonun iki özelliği vardır:

  1. Aynı girişlerle tekrar tekrar çağırmak her zaman aynı sonucu verir. Bu değişmez olduğu anlamına gelir. Durumu sadece bir kez ayarlanır.

  2. Yan etkisi yoktur. Aramanın sebep olduğu tek değişiklik sonucu üretmektir.

Öyleyse, returnsonuçları iletme yönteminiz olarak kullanmaya yemin ederseniz, tamamen işlevsel olmak nasıl geçer ?

Söyle, sormayın bazı yan etkiye düşünün ne kullanılarak fikri eser. Bir nesneyle uğraşırken içsel durumu hakkında soru sormuyorum. Yapmam gerekeni söylüyorum ve yapmam gerektiğini söylediklerimle ne yapabileceğimizi bulmak için içsel durumunu kullanıyor. Bir kere söylediğimde ne yaptığını sormuyorum. Ne yapması gerektiği hakkında bir şeyler yapmasını bekliyorum.

Ben söyle, Kapsülleme için farklı bir isimden daha fazlasını sorma. Kullandığımda returnbeni neyin aradığı hakkında hiçbir fikrim yok. Protokolü konuşamam, protokolümle başa çıkmak için onu zorlamalıyım. Hangi durumlarda iç devlet olarak ifade edilir. Maruz kalan tam olarak durum olmasa bile, genellikle sadece durum ve giriş argümanlarında yapılan bir hesaplama. Yanıt verecek bir arayüze sahip olmak, sonuçları iç durumdan veya hesaplamalardan daha anlamlı bir şeye masaj yapma şansı verir. Bu mesaj geçiyor . Bu örneğe bakınız .

Gündüz yolunda, disk sürücülerinin içinde gerçekten diskler varken ve bir parmak sürücü, tekerlek parmaklarınızla dokunamayacak kadar soğukken arabada yaptığınız şeydi, sinir bozucu insanlara parametreleri içeren işlevleri nasıl düşündüklerini öğrettim. void swap(int *first, int *second)çok kullanışlı görünüyordu ama sonuçları döndüren işlevler yazmaya teşvik edildik. Ben de bunu iman üzerine yürekten aldım ve takip etmeye başladım.

Fakat şimdi insanların nesnelerin sonuçlarını gönderdikleri yeri kontrol etmelerine nasıl izin verdikleri konusunda mimarlık inşa ettiğini görüyorum . İşte örnek bir uygulama . Çıkış portu nesnesine enjekte etmek tekrar tekrar out parametre fikri gibi gözüküyor. Ancak bunu sorma-sorma nesneleri, diğer nesnelere yaptıklarını söyler.

Yan etkileri ilk öğrendiğimde, çıktı parametresi gibi düşündüm. İnsanlara işlerin bir kısmını şaşırtıcı bir şekilde gerçekleştirerek, yani return resultsözleşmeyi takip etmeyerek şaşırtmamaları söylendi . Şimdi eminim ki, yan etkileri ile çarpıştığı ama geri dönüşü gerçekten sadece bir kongre olduğunu biliyorum, sonuçta yığının üzerine itilen sonucu bıraktı, böylece ne denirse onu patlatabilirsin. Hepsi bu kadar.

Gerçekten sormaya çalıştığım şey:

returnkilitleri olmadan iplik güvenlik tüm bu yan etki sefalet önlemek ve almak için tek yol vb Ya da ben takip edebilirsiniz sorma, söyleme tamamen işlevsel bir şekilde?


3
Komut Sorgusu Ayrımı'nı yoksaymamayı seçerseniz, sorunun çözülmüş olduğunu düşünür müsünüz?
rwong

30
Kendinizi bir tekme üzerinde bulmanın, her özel durumun artılarını ve eksilerini düşünmek yerine dogma odaklı bir tasarımla uğraştığınızın bir göstergesi olabilir.
Blrfl

3
Genel olarak, insanlar "geri dönüşün" zararlı olduğu hakkında konuştuklarında, işlevsel değil yapılandırılmış programlamaya ve rutinin sonunda tek bir geri dönüş ifadesine (ve belki bir if / else engellemesinin her iki tarafının da sonunda olduğunu) söylüyorlar. bu, kendisinin son elemanıdır) buna dahil değildir.
Random832

16
@jameslarge: Yanlış ikilik. Dogmatik düşünceyle tasarımlara yönelmenize izin vermemek, Vahşi Batı ile aynı şey değildir / bahsettiğiniz her şey yaklaşıyor. Önemli olan dogmanın iyi, basit ve açık bir kodla girmesine izin vermemektir. Evrensel yasa lakkiler içindir; bağlam krallar içindir.
Nicol Bolas

4
Sorunuzda net olmayan bir şey var: 'return' kullanarak yemin ettiğinizi söylüyorsunuz, ancak söyleyebileceğim kadarıyla bunu açıkça diğer kavramlarınızla ilişkilendirmiyorsunuz veya bunu neden yaptığınızı söylüyorsunuz. Bir sonuç üretmek de dahil olmak üzere saf bir fonksiyonun tanımı ile birleştirildiğinde, çözülmesi imkansız olan bir şey yaratırsınız.
Danikov

Yanıtlar:


96

Bir işlevin herhangi bir yan etkisi yoksa ve hiçbir şey döndürmezse, işlev işe yaramaz demektir. Bu kadar basit.

Ama kuralların harfini takip etmek ve altta yatan mantığı görmezden gelmek istersen bazı hileler kullanabilirsin . Örneğin, bir out parametresi kullanmak kesinlikle bir geri dönüş kullanmamaktan bahsediyor. Fakat yine de tam olarak daha karmaşık bir şekilde, bir geri dönüşle tam olarak aynı şeyi yapıyor. Dolayısıyla, geri dönüşün bir sebepten dolayı kötü olduğunu düşünüyorsanız , o zaman bir out parametresini kullanmak aynı temel sebeplerden dolayı açıkça kötüdür.

Daha kıvrımlı hileler kullanabilirsiniz. Örneğin Haskell, pratikte yan etkilere sahip olabileceğiniz IO monad hilesi ile ünlüdür, ancak yine de kesinlikle konuşmadıkça, teorik bir bakış açısıyla yan etkileri vardır. Devam eden stil, kodunuzu spagetti'ye dönüştürmenin bedelinden iade etmemenizi sağlayan başka bir püf noktasıdır.

Alt satırda, aptal hileler yok, yan etkisiz fonksiyonların iki prensibi ve "geri dönüş yok" sadece uyumlu değildir. Dahası, her ikisinin de ilk başta gerçekten kötü ilkeler (gerçekten dogmalar) olduğuna işaret edeceğim, ancak bu farklı bir tartışma.

"Anlat, sorma" veya "yan etki yok" gibi kurallar evrensel olarak uygulanamaz. Her zaman bağlamı göz önünde bulundurmalısın. Yan etkisi olmayan bir program tam anlamıyla yararsızdır. Saf işlevsel diller bile bunu kabul ediyor. Aksine , kodun saf kısımlarını yan etkileri olanlardan ayırmaya çalışırlar . Haskell'deki Devlet veya IO monadlarının amacı, yan etkilerden kaçınmanız değildir - çünkü yapamazsınız - ancak yan etkilerin varlığının , işlev imzası tarafından açıkça belirtildiğidir .

Tell-dont-ask kuralı farklı bir mimariye uygulanır - programdaki nesnelerin birbirleriyle iletişim kuran bağımsız "aktörler" olduğu stil. Her oyuncu temelde özerk ve enkapsüle edilir. Bir mesaj gönderebilirsiniz ve nasıl tepki vereceğine karar verir, ancak oyuncunun iç durumunu dışarıdan inceleyemezsiniz. Bu, bir mesajın oyuncunun / nesnenin iç durumunu değiştirip değiştirmeyeceğini söyleyemeyeceğiniz anlamına gelir. Devlet ve yan etkiler tasarımla gizlenir .


20
@CandiedOrange: Bir çağrının birçok katmanı kavramsal olarak değişmese de, bir yöntemin doğrudan veya dolaylı olarak yan etkileri olup olmadığı. Hala bir yan etki. Fakat mesele şu ki, yan etkiler sadece enjekte edilen nesneler ile gerçekleşiyorsa, böylece ne tür yan etkilerin mümkün olduğunu kontrol edersiniz, o zaman bu iyi bir tasarım gibi görünür. Sadece yan etki değil. OO iyidir ancak tamamen işlevsel değildir.
JacquesB

12
@LightnessRacesinOrbit: sessiz modda grep kullanılacak olan bir işlem dönüş koduna sahiptir. O olmasaydı, o zaman gerçekten işe yaramaz olurdu
unperson325680

10
@ progo: Bir dönüş kodu yan etki değildir; öyle etki. Yan etki dediğimiz her şeye yan etki denir, çünkü geri dönüş kodu değildir;)
Hafiflik Yarışları, Monica ile

8
@ Cubic asıl mesele bu. Yan etkisi olmayan bir program işe yaramaz.
Jens Schauder,

5
@ mathreadler Bu bir yan etki :)
Andres F.

32

Söyle, Sorma bazı temel varsayımlarla gelir:

  1. Nesneleri kullanıyorsun.
  2. Nesnelerin devlet var.
  3. Nesnelerin durumu davranışlarını etkiler.

Bunların hiçbiri saf fonksiyonlar için geçerli değil.

Öyleyse neden "Söyle, Sorma" kuralına sahip olduğumuzu gözden geçirelim. Bu kural bir uyarı ve bir hatırlatmadır. Bu şekilde özetlenebilir:

Sınıfınızın kendi durumunu yönetmesine izin verin. Sizden onun devletini istemeyin ve sonra o duruma göre harekete geçin. Sınıfa ne istediğinizi söyleyin ve kendi durumuna göre ne yapılacağına karar vermesine izin verin.

Başka bir deyişle, sınıflar kendi devletlerini korumaktan ve ona göre hareket etmekten tek başına sorumludur. Kapsülleme bununla ilgili.

Gönderen Fowler :

Sakın Söyle-Sorma , insanların nesne yöneliminin bu veriler üzerinde çalışan işlevlerle veri toplamakla ilgili olduğunu hatırlamasına yardımcı olan bir ilkedir. Bize bir nesneye veri sormak yerine bu verilere göre hareket etmek yerine, ne yapacağını bir nesneye anlatmamız gerektiğini hatırlatır. Bu, davranışları verilerle devam edecek bir nesneye taşımamızı teşvik eder.

Yinelemek için, bunların hiçbirinin saf işlevlerle ilgisi yoktur, ya da bir sınıfın durumunu dış dünyaya maruz bırakmadıkça safları bile etkilemez. Örnekler:

TDA İhlali

var color = trafficLight.Color;
var elapsed = trafficLight.Elapsed;
If (color == Color.Red && elapsed > 2.Minutes)
    trafficLight.ChangeColor(green);

TDA İhlali Değil

var result = trafficLight.ChangeColor(Color.Green);

veya

var result = await trafficLight.ChangeColorWhenReady(Color.Green);     

Son iki örnekte de, trafik ışığı durumunun ve eylemlerinin kontrolünü elinde tutar.


Bekle bir saniye, kapaklar saf olabilir. devleti var (buna sözcüksel kapsam diyorlar). ve bu sözcük kapsamı davranışlarını etkileyebilir. TDA'nın yalnızca nesneler dahil olduğunda ilgili olduğundan emin misiniz?
candied_orange 13:18

7
@CandiedOrange kapaklar yalnızca kapalı ciltleri değiştirmezseniz saf kalır. Aksi takdirde, kapatma işlevinden dönen işlevi çağırırken referans şeffaflığı kaybedersiniz.
Jared Smith,

1
@ JaredSmith ve nesneler hakkında konuşurken aynı doğru değil mi? Bu sadece değişmezlik meselesi değil mi?
candied_orange

1
@bdsl - Ve şimdi istemeyerek de olsa bu tür tartışmaların tam olarak nereye TrafficLight.refreshDisplay örneğiyle gittiğini belirttiniz. Kurallara uyarsanız, orijinal kodlayıcıdan başka kimsenin anlamadığı esnek bir sisteme yönlendirirsiniz. Birkaç yıl sonra aradan sonra orijinal kodlayıcı bile onların ne yaptığını anlamadıklarına bahse girerim.
Dunk,

1
"Aptal" gibi, "Diğer nesneleri açmayın ve onların bağırsaklarına bakmayın, bunun yerine kendi bağırsaklarınızı (varsa) diğer nesnelerin yöntemlerine dökün;
Joker_vD

30

Bir nesneyle uğraşırken içsel durumu hakkında soru sormuyorum. Yapmam gerekeni söylüyorum ve yapmam gerektiğini söylediklerimle ne yapabileceğimizi bulmak için içsel durumunu kullanıyor.

Yalnızca onun için sorma dahili durumuna evin yoksa sormayın, hiç bir iç durumu vardır ya.

Ayrıca söyle, sorma! Bu, bir geri dönüş değeri şeklinde bir sonuç elde edilemez anlamına gelmez ( returnyöntem içindeki bir ifade ile sağlanır ). Sadece nasıl yaptığınız umrumda değil, ama o işlemi yapın! . Ve bazen derhal işlemlerin sonucunu istiyorsun ...


1
CQS, durumun değiştirilmesi ve sonuçların birbirinden ayrılması gerektiği anlamına gelir
jk.

7
@jk. Her zamanki gibi: genel olarak durum değişikliğini ayırmanız ve bir sonuç döndürmeniz gerekir, ancak nadir durumlarda bunu birleştirmek için geçerli nedenler vardır. Örn: bir yineleyici next()yöntemi yalnızca geçerli nesneyi döndürmekle kalmaz, yineleyici iç durumunu da değiştirir, böylece bir sonraki çağrı bir sonraki nesneyi döndürür ...
Timothy Truckle 11

4
Kesinlikle. Bence OP’in sorunu sadece yanlış anlama / yanlış anlamadan “söyle, sorma” dır. Yanlış anlamaların düzeltilmesi sorunu ortadan kaldırır.
Konrad Rudolph

@KonradRudolph Plus, burada sadece yanlış anlama olduğunu sanmıyorum. "Saf fonksiyon" un tanımları "Durum sadece bir kez ayarlanır" ifadesini içerir. Başka bir yorum, bir kapanmanın bağlamı anlamına gelebileceğini gösteriyor, ancak kelime öbekleri bana garip geliyor.
Izkata

17

return"Zararlı" olarak görüyorsanız (resminizde kalabilirsiniz), sonra gibi bir işlev yapmak yerine

ResultType f(InputType inputValue)
{
     // ...
     return result;
}

mesaj iletme biçiminde inşa et:

void f(InputType inputValue, Action<ResultType> g)
{
     // ...
     g(result);
}

Sürece fve gyan etkisi ücretsiz, birlikte zincirleme serbest hem de yan etki olur. Bence bu tarz Devamlı geçiş tarzı olarak da adlandırılana benzer .

Bu gerçekten "daha iyi" yol açarsa, bazı sözleşmeleri ihlal ettiğinden programlar tartışmalıdır. Alman yazılım mühendisi Ralf Westphal bunun etrafında bir programlama modeli yaptı, "Akış Tasarımı" olarak adlandırdığı bir modelleme tekniği ile "Olay Tabanlı Bileşenler" adını verdi.

Bazı örnekleri görmek için bu blog girişinin "Olaylara Çeviri" bölümünde başlayın . Tam yaklaşım için, "Programlama modeli olarak mesajlaşma - Demek istediğin gibi OOP yapma" e-kitabını öneririm .


24
If this really leads to "better" programs is debatableSadece bu yüzyılın ilk on yılında, JavaScript’te yazılmış kodlara bakmak zorundayız. Jquery ve eklentileri bu paradigma geri aramalarına ... her yerdeki geri aramalara meyilliydi . Belirli bir noktada, çok fazla iç içe geçmiş geri çağırma , kabustan hata ayıklama yaptı. Kod, yazılım mühendisliğinin eksantriklikleri ve “ilkeleri” ne olursa olsun insanlar tarafından okunmalıdır
Laiv

1
o zaman bile bir noktada yan etki gösteren bir işlem yapmanız ya da CPS kısmından geri dönmek için bir yola ihtiyacınız var
jk.

12
@Laiv CPS, derleyiciler için bir optimizasyon teknolojisi olarak icat edildi, kimse programcıların kodu bu şekilde elle yazmasını beklemiyordu.
Joker_vD

3
@CandiedOrange Slogan formunda, "dönüş, sadece devam etmenin ne yapılması gerektiğini söylüyor" şeklindedir. Aslında, Schitt'in aktör modelini anlamaya çalışarak Scheme'in yaratılması motive edildi ve aktörler ve kapanışların aynı şey olduğu sonucuna varıldı.
Derek Elkins

2
Varsayım olarak, tüm uygulamanızı hiçbir şey döndürmeyen bir dizi işlev çağrısı olarak yazabilirsiniz. Sıkıca bağlanmış olması sakıncası yoksa, bağlantı noktalarına bile ihtiyacınız yoktur. Ancak çoğu akıllıca uygulama, işleri döndüren işlevleri kullanır, çünkü ... pekala, onlar aklı başında. Ve cevabımı yeterince gösterdiğime inanıyorum return, fonksiyonlardan veri alabilir ve bir nesnenin durumuna hükmetmediğiniz sürece, hala Yapma Sorma'ya bağlı kalabilirsiniz .
Robert Harvey,

7

Mesaj iletme doğal olarak etkilidir. Bir nesneye bir şey yapmasını söylerseniz, bir şey üzerinde etkisinin olmasını beklersiniz. Mesaj işleyicisi safsa, mesaj göndermenize gerek kalmaz.

Dağıtılmış aktör sistemlerinde, bir işlemin sonucu genellikle orijinal isteğin göndericisine bir mesaj olarak gönderilir . İletinin göndereni, aktörün çalışma zamanı tarafından örtük olarak kullanılabilir duruma getirilir veya iletinin bir parçası olarak açıkça kabul edilir. Senkronize mesaj iletmede, tek bir yanıt returnifadeye benzer . Eşzamansız mesaj iletmede, yanıt mesajlarını kullanmak, özellikle sonuç verirken birden fazla aktörde eşzamanlı işlem yapılmasına izin verdiği için özellikle kullanışlıdır.

Sonucun açıkça iletilmesi gereken "göndereni" geçmek, temelde devam eden geçiş stilini ya da aşınan parametreleri - doğrudan bunları mutasyon yapmak yerine mesajlara iletmesi dışında modeller .


5

Tüm bu soru beni 'seviye ihlali' olarak vuruyor.

Büyük bir projede (en azından) aşağıdaki seviyelere sahipsiniz:

  • Sistem seviyesi, örneğin e-ticaret platformu
  • Alt sistem seviyesi, örneğin kullanıcı doğrulama: sunucu, AD, ön uç
  • Bireysel program seviyesi, örneğin yukarıdaki bileşenlerden biri.
  • Aktör / Modül seviyesi [bu, dile bağlı olarak bulanıklaşır]
  • Metod / fonksiyon seviyesi.

Ve böylece bireysel belirteçleri aşağı.

Yöntem / işlev seviyesindeki bir varlığın geri dönmemesi için herhangi bir ihtiyaç yoktur (sadece geri dönse bile this). Ve (açıklamanızda) Aktör seviyesindeki herhangi bir şeyin bir şeyi iade etmesi (dile getirilmesi mümkün olmayan bir dile bağlı olarak) ihtiyacı yoktur. Kargaşanın bu iki seviyeyi birbirine bağladığını düşünüyorum ve onların belirgin bir şekilde mantıklı olması gerektiğini savunuyorum (herhangi bir nesne aslında birden çok seviyeye yayılmış olsa bile).


2

Hem "söyleme, sorma" nın OOP ilkesine hem de saf işlevlerin işlevsel ilkesine uymak istediğinizi söylüyorsunuz, ancak bunun return ifadesinden kaçınmanıza nasıl yol açtığını pek anlamadım.

Her iki ilkeyi izlemenin nispeten yaygın olan alternatif bir yolu, iade ifadelerine tamamen dahil olmak ve değişmeyen nesneleri yalnızca alıcılarla kullanmaktır. O zaman yaklaşım, alıcıların bazılarının, orijinal nesnenin durumunu değiştirmenin aksine, yeni bir devletle benzer bir nesneyi döndürmesini sağlamaktır.

Bu yaklaşımın bir örneği Python yerleşimi tupleve frozensetveri tipleridir. İşte frozensetin tipik bir kullanımı:

small_digits = frozenset([0, 1, 2, 3, 4])
big_digits = frozenset([5, 6, 7, 8, 9])
all_digits = small_digits.union(big_digits)

print("small:", small_digits)
print("big:", big_digits)
print("all:", all_digits)

Aşağıdakileri basacak olan, sendika yönteminin eski objeleri etkilemeden kendi devletiyle yeni bir frozenset oluşturduğunu gösteren:

küçük: frozenset ({0, 1, 2, 3, 4})

büyük: frozenset ({5, 6, 7, 8, 9})

tümü: frozenset ({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})

Benzer değişmez veri yapılarının bir başka kapsamlı örneği, Facebook'un Immutable.js kütüphanesidir. Her iki durumda da, bu yapı taşları ile başlıyorsunuz ve aynı ilkeleri izleyen daha yüksek düzeyli etki alanı nesneleri oluşturabiliyorsunuz, işlevsel bir OOP yaklaşımı elde ediyorsunuz. Değişmezlik ayrıca kilitler hakkında endişelenmenize gerek kalmadan bu nesneleri dişler arasında paylaşabilmenin avantajını görmenizi sağlar.


1

İyi yazılmış bir kodun OO ilkelerini ve işlevsel ilkelerini aynı anda izleyebileceğinden şüphelenmeye başladım. Bu fikirleri uzlaştırmaya çalışıyorum ve indiğim büyük tutuşma noktası geri dönüş.

returnAslında , zorunlu ve işlevsel programlamanın bazı faydalarını uzlaştırmak için elimden gelenin en iyisini yapmaya çalışıyorum (doğal olarak tüm faydaları elde etmiyoruz, ancak aslanın ikisinden de payını almaya çalışıyorum) . Çoğu durumda benim için basit bir moda

returnDürüst ifadelerden kaçınmaya çalışmakla ilgili olarak , son bir saat boyunca bunun üstesinden gelmeye çalıştım ve temelde beynim birkaç kez taştı. Ne yapması gerektiğini söylenen çok özerk nesneler lehine en güçlü kapsülleme düzeyini ve bilgiyi gizleme anlamında çekiciliğini görebiliyorum ve sadece daha iyisini elde etmeye çalışmak için fikirlerin uçlarını keşfetmeyi seviyorum. Nasıl çalıştıklarını anlama.

Trafik ışığı örneğini kullanırsak, o zaman derhal naif bir girişim onu ​​çevreleyen tüm dünya hakkında böyle bir trafik ışığı bilgisi vermek isteyecektir ve bu kesinlikle eşleştirme açısından istenmeyecektir. Bu yüzden, doğru anlarsam, onu soyutlarsınız ve boru hattı üzerinden veri değil mesajları ve talepleri daha da dağıtan I / O portları kavramını genelleştirmek lehine çevirirsiniz ve temelde bu nesneleri birbirleri arasında istenen etkileşimler / isteklerle enjekte ederler. birbirlerine habersiz iken.

Nodal Boru Hattı

görüntü tanımını buraya girin

Ve bu şema, bunu ortaya çıkarmaya çalıştığım kadarıyla ilgili (ve basit olsa da, değiştirmeye ve yeniden düşünmeye devam etmem gerekiyordu). Derhal bu dekuplaj ve soyutlama seviyesine sahip bir tasarımın kod biçiminde akla gelmesinin çok zor olduğunu düşünmeye meyilliyim, çünkü bütün bunları karmaşık bir dünyaya bağlayan orkestra şefi çok zor bulabilir İstenilen boru hattını oluşturmak için tüm bu etkileşimleri ve istekleri takip edin. Bununla birlikte, görsel biçimde, bu şeyleri sadece bir grafik olarak çizmek ve her şeyi birbirine bağlamak ve etkileşimli olarak gerçekleşen şeyleri görmek mantıklı olabilir.

Yan etkiler açısından, bu taleplerin, çağrı istifinde, her bir iş parçacığının gerçekleştirmesi için bir emir komuta zincirine yol açabileceği anlamında "yan etkilerden" arınmış olduğunu görebiliyordum. pragmatik bir anlamda, dış dünya ile ilgili herhangi bir devleti bu tür komutlar yerine getirilinceye kadar değiştirmeyeceği için “yan etki” olarak - çoğu yazılımda benim için asıl amaç yan etkileri ortadan kaldırmak değil, onları ertelemek ve merkezileştirmektir. . Dahası, emir, var olanı değiştirmenin aksine yeni bir dünya ortaya çıkarabilir. Beynim gerçekten tüm bunları anlamaya çalışarak vergilendiriliyor, ancak bu fikirleri prototipleme girişimi yok. Ben de yapmadım

Nasıl çalışır

Açıklığa kavuşturmak için, bunu gerçekten nasıl programladığınızı hayal ediyordum. Çalışmakta olduğunu görmemin yolu, aslında kullanıcı-sonu (programcının) iş akışını yakalamanın üzerindeki diyagramdı. Bir trafik ışığını dünyaya sürükleyebilir, bir zamanlayıcıyı sürükleyebilir, geçen bir süre verebilirsiniz ("onu inşa ederken"). Zamanlayıcının bir On Intervalolayı (çıkış bağlantı noktası) vardır, bunu trafik ışığına bağlayabilirsiniz, böylece bu tür olaylarda ışığa renkleri arasında geçiş yapması söylenir.

Ardından, trafik ışığı belirli renklere geçildiğinde On Red, bir noktada bir yayayı dünyamıza sürdürebilir ve bu olayı yayaya yürümeye başlamasını söylettirebilir ... ya da kuşları içine sürükleyebiliriz. Sahnemize ve ışık kırmızıya döndüğünde, kuşlara uçmalarını ve kanatlarını çırpmalarını söyleriz ... ya da ışık kırmızıya döndüğünde, bir bombaya patlamasını söyleriz - istediğimiz ve nesneler Birbirlerine tamamen habersizler ve dolaylı olarak birbirlerine bu soyut giriş / çıkış konseptiyle ne yapacaklarını söylemekten başka bir şey yapmıyorlar.

Ve devletlerini tamamen kapsıyorlar ve onunla ilgili hiçbir şey açığa vurmuyorlar (bu "olaylar" TMI olarak kabul edilmediği sürece, bu noktada her şeyi çok fazla düşünmek zorunda kalacağım), birbirlerine dolaylı olarak yapmaları gerektiğini söylemezler, sormazlar. Ve onlar uber ayrıldılar. Bu genelleştirilmiş giriş / çıkış portu soyutlaması dışında hiçbir şey bilmiyor.

Pratik Kullanım Durumları?

Bu tür bir şeyi, belirli bölgelerdeki, çevreleyen dünya hakkında hiçbir şey bilmeyen tüm bu özerk nesneleri orkestre etmek, çevreleyen dünya hakkında hiçbir şey bilmeyen, iç yapı durumlarından hiçbir şey göstermeyen ve temel olarak sadece istekleri çoğaltmak için, etki alanlarında yüksek seviyeli alana özgü gömülü bir dil olarak yararlı olduğunu görebiliyordum. birbirimizin arasında değiştirebileceğimiz ve kalbimizin içeriğine ince ayar yapabileceğimiz. Şu anda bunun çok etki alanına özgü olduğunu hissediyorum ya da belki de yeterince düşünmedim, çünkü beynimi düzenli olarak geliştirdiğim türlerle dolaştırmam çok zor (sık sık birlikte çalışıyorum) oldukça düşük-orta düzey kod), eğer bu tür uçlara söyleme, sorma ve akla gelebilecek en güçlü kapsülleme seviyesini istemeyi yorumlarsam Ancak, belirli bir alanda üst düzey soyutlamalar ile çalışıyorsak,

Sinyaller ve Yuvalar

Nasıl tasarlandığının nüanslarını çok fazla hesaba katmazsak, bu tasarım temelde sinyaller ve yuvalar olduğunu fark edinceye kadar bana garip geldi. Bana göre asıl soru, grafikteki bu düğümleri (nesneler), Tell, Yapma, kesinlikle kaçınmaktan kaçınmak, returnifadelerden kaçınma derecelerine uymak ve söz konusu grafiği mutasyonlar olmadan değerlendirip değerlendirmemek kadar sıkı bir şekilde uygulayabildiğimizdir . paralel, örneğin, yok kilitleme). Bu, sihirli yararların, potansiyel olarak bunları bir araya getirme biçimimizde olmadığı, ancak bu kadar kapsülleme olmayan mutasyonların derecesinde nasıl uygulanabilecekleridir. Bunların ikisi de bana uygulanabilir görünüyor, ancak bunun ne kadar yaygın olabileceğinden emin değilim ve bu, potansiyel kullanım durumlarında çalışmak için biraz güdük olduğum yer.


0

Burada kesinlikle kesinlik sızıntısı görüyorum. Görünüşe göre "yan etki" iyi bilinen ve yaygın olarak anlaşılan bir terimdir, ancak gerçekte değildir. Tanımlarınıza bağlı olarak (OP'de gerçekte eksik olan), yan etkiler tamamen gerekli olabilir (@ JacquesB açıklamayı başardığı gibi) veya mercylessly kabul edilemez. Veya açıklığa kavuşturmaya doğru bir adım atıldığında, saklanmayı sevmediği arzu edilen yan etkileri (bu noktada ünlü Haskin'in IO'su ortaya çıkar: bu açık olmaktan başka bir şey değildir) ve istenmeyen yan etkileri ortaya çıkarmak için bir zorunluluktur. kod hatalarının ve bu tür şeylerin sonucu . Bunlar oldukça farklı problemlerdir ve bu nedenle farklı muhakeme gerektirir.

Bu yüzden, kendinizi yeniden ifade etmekten başlamanızı öneriyorum: "Yan etkiyi nasıl tanımlarız ve verilen tanım (lar) da" return "ifadesiyle olan ilişkisi hakkında ne söylüyor?".


1
"Bu noktalarda ünlü Haskell'in IO ortaya çıkıyor: açık bir yoldan başka bir şey değil" - açıklık kesinlikle Haskin'in monadik IO'sunun bir yararıdır, ancak bunun başka bir anlamı var: yan etkinin tamamen izole edilmesi için bir yol sağlar dilin dışında - genel uygulamalar aslında bunu yapmasa da, çoğunlukla verimlilik kaygıları nedeniyle, kavramsal olarak doğrudur: IO monad bir talimatı tamamen dışında olan bir ortama geri göndermenin bir yolu olarak düşünülebilir. Haskell programı, tamamlandıktan sonra devam edecek bir fonksiyona referansla birlikte.
Jules
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.