Operatörler, anahtar kelimelerden veya işlevlerden daha net okunabilir mi? [kapalı]


14

Biraz öznel, ancak bir operatörün geniş ve zor olarak kullanılmasını hangi faktörlerin netleştirdiğini daha net bir şekilde anlamayı umuyorum. Son zamanlarda dil tasarımlarını göz önünde bulunduruyorum ve her zaman geri döndüğüm bir konu, dilde bazı önemli işlemleri ne zaman bir operatör haline getireceğimiz ve ne zaman bir anahtar kelime veya işlev kullanacağım.

Özel işleçlerin oluşturulması kolay olduğundan ve genellikle yeni bir veri türü üzerinde kullanılmak üzere birkaç işleçle paketleneceğinden Haskell bunun için biraz kötü şöhretlidir. Örneğin Parsec kütüphanesi, ayrıştırıcıları bir araya getirmek için bir sürü operatörle birlikte gelir, mücevherler gibi >.ve .> şu anda ne demek istediklerini bile hatırlayamıyorum, ama ne olduğunu ezberledikten sonra çok kolay çalıştıklarını hatırlıyorum aslında demek istedikleri. Böyle bir işlev çağrısı leftCompose(parser1, parser2)daha iyi olur muydu? Kesinlikle daha ayrıntılı, ancak bazı yönlerden daha net.

C benzeri dillerdeki operatör aşırı yüklemeleri benzer bir konudur, ancak +alışılmadık operatörlerin anlamını olağandışı yeni anlamlarla aşırı yüklemenin ek sorunu ile sınırlıdır.

Herhangi bir yeni dilde, bu oldukça zor bir konu gibi görünecektir. Örneğin F # 'da döküm, C # stili döküm sözdizimi veya ayrıntılı VB stili yerine matematiksel olarak türetilmiş bir tür döküm operatörü kullanır. C #: (int32) xVB: CType(x, int32)F #:x :> int32

Teoride, yeni bir dilde en yerleşik işlevsellik için operatörler bulunabilir. Yerine defya decya vardeğişken bildiriminde, neden olmasın için ! nameveya @ nameveya benzer bir şey. Kesinlikle bildirimi ve ardından bağlamayı kısaltır: @x := 5yerine declare x = 5veya let x = 5 Çoğu kod çok sayıda değişken tanımı gerektirecektir, neden olmasın?

Bir operatör ne zaman açık ve yararlıdır ve ne zaman gizlidir?



1
Keşke bana Java'nın operatör aşırı yüklenmesi eksikliğinden şikayetçi olan 1000 geliştiriciden birinin bu soruya cevap vermesini diliyorum.
smp7d

1
Soruyu yazmayı bitirdiğimde APL'yi düşünmüştüm, ama bazı açılardan konuyu açıklığa kavuşturuyor ve daha az öznel bir bölgeye taşıyor. Çoğu insanın APL'nin aşırı sayıda operatör aracılığıyla kullanımda bir şey kaybettiğini kabul edebileceğini düşünüyorum, ancak bir dilde operatör aşırı yüklemesi olmadığında şikayet eden insanların miktarı, bazı işlevlerin uygun olması lehine konuşuyor operatör olarak hareket etmek. Yasak özel işleçler ile işleçlerden başka bir şey arasında, pratik uygulama ve kullanım için bazı yönergeler gizlenmelidir.
CodexArcanum

Gördüğüm gibi, kullanıcı tarafından tanımlanan türlere göre yerel türleri ayrıcalıklı kıldığından operatör aşırı yüklenmesinin olmaması sakıncalıdır (Java'nın bunu başka şekillerde de yaptığını unutmayın).
Soruna

2
@comingstorm: Aslında Haskell yolunun daha iyi olduğunu düşünüyorum. Farklı şekillerde aşırı yükleyebileceğiniz sonlu bir işleç kümeniz varsa, işleçleri genellikle farklı bağlamlarda (örneğin +dize birleştirme veya <<akışlar için) yeniden kullanmak zorunda kalırsınız . Haskell ile, bir operatör, sadece özel bir ada sahip bir işlevdir (aşırı yüklenmemiş) veya tip sınıfının bir parçasıdır, bu da polimorfik olsa da, her tip için aynı mantıklı şeyi yapar ve hatta aynı tip imzası vardır. Yani >>olan >>her tür ve asla biraz kayma olacak.
Tikhon Jelvis

Yanıtlar:


16

genel bir dil tasarımı açısından işlevler ve operatörler arasında herhangi bir fark olması gerekmez. Fonksiyonlar herhangi (veya değişken değişken) önek işlemleri olarak tanımlanabilir. Ve anahtar kelimeler yalnızca ayrılmış adları olan işlevler veya işleçler olarak görülebilir (bu, dilbilgisi tasarlamada yararlıdır).

Tüm bu karar nihayetinde gösterimin nasıl okunmasını istediğinizi ve söylediğiniz gibi sübjektif olduğunu, ancak herkesin bildiği gibi matematik için olağan infix operatörlerini kullanmak gibi açık bir rasyonalizasyonlar yapabilir.

Son olarak, Dijkstra kullandığı matematiksel notasyonların ilginç bir gerekçesini yazdı;


4
Dijkstra gazetesine bağlantı için sana ikinci bir +1 vermek isterim.
AProgrammer

Harika bir bağlantı, bir PayPal hesabı yayınlamak zorundaydınız! ;)
Adriano Repetti 15:12

8

Bana göre, bir operatör artık kod satırını yüksek sesle veya kafanızda okuyamadığında ve mantıklı hale getiremediğinizde kullanışlı olmayı bırakıyor.

Örneğin, declare x = 5gibi okur "declare x equals 5"ya let x = 5kadar okunabilir "let x equal 5"ancak okuma, yüksek sesle okuduğunda çok anlaşılabilir bir @x := 5şekilde okunduğunda "at x colon equals 5"(veya "at x is defined to be 5"bir matematikçi iseniz) hiç mantıklı değil.

Bu yüzden bana göre, kod yüksek sesle okunabiliyorsa ve dile aşina olmayan makul derecede zeki bir kişi tarafından anlaşılabiliyorsa, bir işleç kullanın, ancak değilse işlev adlarını kullanın.


5
@x := 5Anlamak zor değil - hala kendime yüksek sesle okuyorum set x to be equal to 5.
SinirliWithFormsDesigner

3
@Rachel, bu durumda, :=programlama dillerinin dışındaki matematiksel gösterimde daha geniş bir kullanıma sahiptir. Ayrıca, gibi ifadeler x = x + 1biraz saçma olur.
ccoakley

3
İronik olarak, bazı insanların :=görev olarak tanımamalarını unutmuştum . Aslında birkaç dil bunu kullanıyor. Smalltalk, bence, belki de en iyi bilineni olmak. Atama ve eşitliğin ayrı operatörler olup olmayacağı, biri zaten başka bir sorunun kapsadığı tamamen farklı bir solucan kutusudur.
CodexArcanum

1
@ccoakley Teşekkürler, bunun :=matematikte kullanıldığının farkında değildim . Bunun için bulduğum bir tanım, "olarak tanımlandı" olarak tanımlanmıştı, bu yüzden @x := 5İngilizce'ye çevrilecekti "at x is defined to be 5", ki bana hala olması gerektiği kadar mantıklı değil.
Rachel

1
Kesinlikle Pascal şunları kullandı: = ödev olarak, ASCII'de sol ok olmaması için.
Vatine

4

Bir operatör bilindiği zaman açık ve kullanışlıdır. Ve bu muhtemelen aşırı yük operatörlerinin, sadece seçilen operatör önceden kurulmuş bir uygulama olarak yeterli (form, öncelik ve ilişkilendirilebilirlik gibi) olduğunda yapılması gerektiği anlamına gelir.

Ama biraz daha kazmak, iki yönü var.

Sözdizimi (işlev çağrısı sözdizimi için önek yerine işleç için infix) ve adlandırma.

Sözdizimi için, ön ekin önekten yeterince açık olduğu başka bir durum daha vardır: çağrıların tanıdık gelmesini gerektirebilir: çağrılar zincirlendiğinde ve iç içe yerleştirildiğinde.

Veya a * b + c * d + e * file karşılaştır (her ikisi de infix sürümü ile aynı durumda ayrıştırılabilir). Aslında bunun yerine uzun arada bunlardan bir öncekinin terimlerini ayırmak gözlerimde daha okunabilir kılmak (ancak önek sözdizimi için gerekli olmayan öncelik kuralları hatırlamak zorunda). Eğer şeyleri bu şekilde birleştirmeniz gerekiyorsa, uzun vadeli fayda yolu öğrenme maliyetine değecektir. Ayrıca, operatörlerinizi sembol kullanmak yerine harflerle adlandırsanız bile bu avantajı korursunuz.+(+(*(a, b), *(c, d)), *(e, f))+ + * a b * c d * e f+

Operatörlerin isimlendirilmesinde, yerleşik semboller veya açık isimden başka bir şey kullanmanın birkaç avantajı görüyorum. Evet, daha kısa olabilirler, ancak gerçekten şifrelenirler ve onları tanımak için iyi bir nedeniniz yoksa hızlı bir şekilde unutulurlar.

Bir üçüncü dil tasarımı POV alırsanız, operatör kümesinin açık veya kapalı olması gerekiyorsa - operatör ekleyebilir veya ekleyemezsiniz - ve öncelik ve ilişkilendirilebilirliğin kullanıcı tarafından belirlenebilir olması gerekip gerekmediğidir. İlk kullanımım dikkatli olmak ve kullanıcı tarafından belirlenebilir öncelik ve ilişkilendirilebilirlik sağlamak değil, açık bir sete sahip olmaya daha açık olacağım (operatör aşırı yüklemesini kullanma baskısını artıracak, ancak kötü bir tane kullanmak için olanı azaltacaktır) yalnızca yararlı olduğu yerde infix sözdiziminden yararlanmak için).


Kullanıcılar operatör ekleyebiliyorsa, neden ekledikleri operatörlerin önceliğini ve ilişkisini ayarlamalarına izin vermiyorsunuz?
Tikhon Jelvis

@TikhonJelvis, Çoğunlukla muhafazakarlıktı, ancak örneklerden başka bir şey için kullanabilmek istiyorsanız dikkate almanız gereken bazı yönler var. Örneğin, aşırı yüklenmiş kümenin belirli bir üyesini değil, önceliği ve ilişkilendirmeyi operatöre bağlamak istiyorsunuz (ayrıştırma yapıldıktan sonra üyeyi seçtiniz, seçim ayrışmayı etkileyemez). Bu nedenle, aynı operatörü kullanarak kütüphaneleri entegre etmek için önceliği ve ilişkilendirilebilirliği konusunda anlaşmaları gerekir. Olasılığı eklemeden önce, neden bu kadar az dilin Algol 68'i (AFAIK yok) takip ettiğini ve bunları tanımlamasına izin verdiğini bulmaya çalıştım.
12'de programcı

Haskell, keyfi operatörleri tanımlamanıza ve önceliklerini ve ilişkilendirilebilirliklerini belirlemenize izin verir. Fark Operatörleri yüklenmeyin olmasıdır se başına , normal fonksiyonları gibi --they davranırlar. Bu, farklı işleçler için aynı işleci kullanmaya çalışan farklı kitaplıkların bulunamayacağı anlamına gelir. Kendi operatörünüzü tanımlayabildiğiniz için, aynı şeyleri farklı şeyler için tekrar kullanmak için çok daha az neden vardır.
Tikhon Jelvis

1

Sembol olarak operatörler, sezgisel olarak anlamlı olduklarında faydalıdır. +ve -açıkça toplama ve çıkarma, örneğin, bu yüzden hemen hemen her dil onları operatör olarak kullanır. Karşılaştırma ile aynı ( <ve >ilkokulda öğretilir ve <=ve >=standart klavyede hiçbir Altı çizili karşılaştırma tuşları var olduğunu anladığınızda temel karşılaştırmaların sezgisel uzantılarıdır.)

*ve /hemen daha az açıktır, ancak evrensel olarak kullanılırlar ve +ve -tuşlarının yanındaki sayısal tuş takımındaki konumları bağlam sağlamaya yardımcı olur. C'ler <<ve >>aynı kategoridedir: sola kaydırma ve sağa kaydırma ne olduğunu anladığınızda, okların arkasındaki anımsatıcıları anlamak çok zor değildir.

Sonra gerçekten garip olanlardan bazılarına gelirsiniz, C kodunu okunamayan operatör çorbasına dönüştürebilirsiniz. (Burada C'yi seçmek, çünkü sözdizimi hemen hemen herkesin aşina olduğu, C ile veya alt dillerle çalışarak çok operatör ağır bir örnektir.) Örneğin, %operatör. Herkes bunun ne olduğunu biliyor: yüzde işareti ... değil mi? C hariç, 100'e bölünmesi ile hiçbir ilgisi yoktur; bu modül operatörüdür. Bu anımsatıcı olarak sıfır mantıklı, ama işte burada!

Daha da kötüsü, boole operatörleri. &Bir şekilde ve mantıklı orada iki farklı olduğunu hariç &rağmen sadece bir tanesi şimdiye kadar, iki farklı şeyler yapmak operatörler ve her ikisi bunlardan biri geçerlidir her durumda sözdizimsel geçerlidir aslında mantıklı herhangi bir durumda. Bu sadece karışıklık için bir reçete! Veya , xor ve değil onlar mnemonically yararlı semboller kullanmayın ve ya tutarlı değildir beri operatörler, çok daha kötüdür. (Hayır çift xor operatör ve bitsel mantıklı ve değil iki farklı semboller yerine bir sembol ve bir iki büklüm olmuş bir sürümünü kullanın.)

Ve sadece daha da kötüleştirmek için, &ve *operatörler tamamen farklı şeyler için yeniden kullanılır, bu da dili hem insanlar hem de derleyiciler için ayrıştırmayı zorlaştırır. (Bu ne anlama A * Bgeliyor? Tamamen bağlama bağlıdır: Abir tür mü değişken mi?)

Kuşkusuz, Dennis Ritchie ile hiç konuşmadım ve ona dilde yaptığı tasarım kararlarını sormadım, ancak çoğu, operatörlerin arkasındaki felsefenin "semboller uğruna semboller" olduğunu hissettiriyor.

Bunu, C ile aynı operatörlere sahip olan ancak onları temsil etmede farklı bir felsefeye sahip olan Pascal ile karşılaştırın: operatörler sezgisel ve okunması kolay olmalıdır. Aritmetik işleçler aynıdır. Modül operatörü kelimedir mod, çünkü klavyede açıkça "modül" anlamına gelen hiçbir sembol yoktur. Mantıksal operatörleri and, or, xorve notve yalnızca biri yoktur; derleyici, booleans veya sayılarda çalışıp çalışmadığınıza bağlı olarak boolean veya bitwise sürümüne ihtiyacınız olup olmadığını bilir ve tüm hata sınıflarını ortadan kaldırır. Bu , özellikle sözdizimi vurgulamalı modern bir düzenleyicide Pascal kodunun anlaşılmasını çok kolaylaştırır, böylece operatörler ve anahtar kelimeler görsel olarak tanımlayıcılardan farklıdır.


4
Pascal farklı bir felsefeyi temsil etmiyor. Wirth'in gazetelerini okursanız, her zaman andve benzeri şeyler için semboller kullandı or. Ancak Pascal'ı geliştirdiğinde, bunu 6 bit karakter kullanan bir Kontrol Verileri ana bilgisayarında yaptı. Bu karakter kümesi basitçe olmadığını basit bir nedenle, pek çok şey için kullanılması kelime kararı zorla sahip çok semboller için yer ve böyle ASCII gibi bir şey gibi neredeyse. Hem C hem de Pascal kullandım ve C'yi daha okunaklı buluyorum. Pascal'ı tercih edebilirsiniz, ama bu bir zevk meselesi, gerçek değil.
Jerry Coffin

Wirth hakkında @ JerryCoffin sözüne eklemek için, sonraki dilleri (Modula, Oberon) daha fazla sembol kullanıyor.
AProgrammer

@AProgrammer: Ve asla hiçbir yere gitmediler. ;)
Mason Wheeler

Sanırım |(ve uzantı olarak ||) ya da mantıklı. Dilbilgisi gibi diğer bağlamlarda her zaman değişim için bunu görürsünüz ve iki seçeneği bölüyor gibi görünüyor.
Tikhon Jelvis

1
Harf tabanlı anahtar kelimelerin bir avantajı, boşluklarının sembollerden çok daha büyük olmasıdır. Örneğin, Pascal tarzı bir dil, hem "modül" hem de "kalan" için ve tamsayı ile kayan nokta bölümü (işlenen türlerinin ötesinde farklı anlamları olan) için işleçler içerebilir.
supercat

1

Bence operatörler işlevleri tanıdık, matematiksel amaçlarını yakından yansıttığında çok daha okunabilir. Örneğin, +, -, vb. Standart operatörler toplama ve çıkarma işlemlerinde Toplama veya Çıkarma'dan daha okunabilir. Operatörün davranışı açıkça tanımlanmalıdır. Örneğin, liste birleştirme için + anlamının aşırı yüklenmesine tahammül edebilirim. İdeal olarak, operasyonun mutasyona uğramak yerine bir değer döndürerek yan etkileri olmazdı.

Katlama gibi işlevler için kısayol operatörleriyle uğraştım. Açıkçası onlarla daha fazla deneyim bunu kolaylaştıracaktır, ancak foldRightdaha okunabilir buluyorum /:.


4
Belki kullanım sıklığı da buna girer. foldBir operatörün çok fazla zaman kazandıracağını yeterince düşünmüyorum . Bu nedenle LISPy (+ 1 2 3) tuhaf görünüyor, ancak (1 2 3 ekleyin) daha az. Operatörleri kesinlikle ikili olarak düşünme eğilimindeyiz. Parsec'in >>.stil operatörleri aptal olabilir, ancak en azından Parsec'te yaptığınız birincil şey ayrıştırıcıları birleştirmektir, bu nedenle operatörler çok fazla kullanım elde eder.
CodexArcanum

1

Operatörlerle ilgili sorun, bunların yerine kullanılabilecek sensical (!) Yöntem adlarının sayısıyla karşılaştırıldığında çok az sayıda olmasıdır. Bir yan etki, kullanıcı tanımlı operatörlerin çok fazla aşırı yüklenme eğilimi göstermesidir.

Elbette, satırın C = A * x + b * cyazılması ve okunması daha kolaydır C = A.multiplyVector(x).addVector(b.multiplyScalar(c)).

Ya da kafanızdaki tüm operatörlerin aşırı yüklenmiş sürümlerine sahipseniz yazmak kesinlikle daha kolaydır. Ve sondan ikinci hatayı düzeltirken daha sonra okuyabilirsiniz.

Şimdi, orada kodlanacak olan çoğu kod için, sorun değil. “Proje tüm testleri geçiyor ve çalışıyor” - birçoğu için isteyebileceğimiz bir yazılım parçası.

Ancak kritik alanlara giren yazılımlar yaparken işler farklı şekilde işler. Güvenlik açısından kritik şeyler. Güvenlik. Uçakları havada tutan veya nükleer tesislerin çalışmasını sağlayan yazılım. Veya son derece gizli e-postalarınızı şifreleyen yazılımlar.

Denetim kodu konusunda uzmanlaşmış güvenlik uzmanları için bu bir kabus olabilir. Çok sayıda kullanıcı tanımlı işleç ve operatör aşırı yüklemesinin karışımı, onları en sonunda hangi kodun çalıştırılacağını bulmakta zorlandıkları hoş olmayan durumlarda bırakabilir.

Yani, orijinal soruda belirtildiği gibi, bu oldukça öznel bir konudur. Operatörlerin nasıl kullanılması gerektiğine dair birçok öneri tam anlamıyla mantıklı gelse de, sadece birkaç tanesinin kombinasyonu uzun vadede çok fazla sorun yaratabilir.


0

En aşırı örnek APL olduğunu varsayalım aşağıdaki program "yaşam oyunu" dir:

life←{↑1 ⍵∨.∧3 4=+/,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂⍵}

Ve eğer referans kılavuzu ile birkaç gün harcamadan bunun ne anlama geldiğini çözebilirseniz, size iyi şanslar!

Sorun şu ki, neredeyse herkesin sezgisel olarak anladığı bir dizi sembolünüz var: +,-,*,/,%,=,==,&

ve anlaşılmadan önce biraz açıklama gerektiren geri kalanlar ve genellikle belirli bir dile özgüdür. Örneğin, bir dizinin hangi üyesini, [], () ve hatta "." İstediğinizi belirten belirgin bir sembol yoktur. kullanılmış, ancak aynı şekilde kolayca kullanabileceğiniz belirgin bir anahtar kelime yoktur, bu nedenle operatörlerin mantıklı kullanımı için bir durum söz konusudur. Ama çok fazla değil.

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.