Sözdizimi Tasarımı - Neden hiçbir argüman iletilmezse parantez kullanılır?


66

Birçok dilde, sözdizimi function_name(arg1, arg2, ...)bir işlevi çağırmak için kullanılır. Fonksiyonu herhangi bir argüman olmadan çağırmak istediğimizde yapmalıyız function_name().

Bir derleyici veya komut dosyası yorumlayıcısının ()onu işlev çağrısı olarak başarılı bir şekilde algılaması gerekebileceğini garip buluyorum . Bir değişkenin çağrılabilir olduğu biliniyorsa, neden function_name;yeterli olmaz?

Öte yandan, bazı dillerde yapabiliriz: function_name 'test';hatta function_name 'first' 'second';bir işlevi veya komutu çağırmak için.

Bence sadece öncelik sırasını açıklamak için gerekli olsaydı, diğer yerlerde isteğe bağlıysa parantez daha iyi olurdu. Örneğin, yapmak if expression == true function_name;kadar geçerli olmalıdır if (expression == true) function_name();.

Bence en sinir bozucu şey 'SOME_STRING'.toLowerCase()prototip işlevinde açıkça hiçbir argümana ihtiyaç duyulmadığında yapmaktır . Tasarımcılar neden daha basitine karşı karar verdi 'SOME_STRING'.lower?

Yasal Uyarı: Beni yanlış anlamayın, C benzeri sözdizimini seviyorum! ;) Sadece daha iyi olup olmadığını soruyorum. İsteğin ()herhangi bir performans avantajı var mı , yoksa kodu anlamayı kolaylaştırıyor mu? Sebebinin tam olarak ne olduğunu gerçekten merak ediyorum.


103
Bir işlevi başka bir işleve argüman olarak iletmek isteseydiniz ne yapardınız?
Vincent Savard,

30
Kodun insanlar tarafından okunması gerektiği sürece okunabilirlik kraldır.
Tulains Córdova

75
Bu sorulan okunabilirliği olan şey (), ancak yazınızda öne çıkan şey if (expression == true)ifadedir. Gereksizler için endişeleniyorsun (), sonra da gereksiz bir şey kullanıyorsun == true:)
David Arno

15
Visual Basic buna izin verdi
edc65

14
Pascal'da zorunluydu, sadece argümanları alan fonksiyonlar ve prosedürler için parens kullandınız.
RemcoGerlich

Yanıtlar:


251

Birinci sınıf işlevleri kullanan diller için, bir işleve başvuruda bulunma sözdiziminin şu şekilde olması yaygındır :

a = object.functionName

bu işlevi çağırma eylemi :

b = object.functionName()

aYukarıdaki örnekte, yukarıdaki fonksiyona atıfta bulunulur (ve bunu yaparak arama yapabilirsiniz a()), bfonksiyonun dönüş değerini içerir.

Bazı diller parantez olmadan işlev çağrıları yapabilirken , işlevi çağırıp çağırmadıklarını veya yalnızca işleve başvurarak kafalarını karıştırabilir .


9
Bu farkın yalnızca yan etkilerin varlığında ilginç olduğunu söylemek isteyebilirsiniz - saf bir işlev için önemli değil
Bergi

73
@ Bergi: Saf fonksiyonlar için çok önemlidir! Ben bir işlevi varsa make_listbir liste halinde onun argümanlarını paketleri, arasında büyük bir fark var f(make_list)bir işlev geçirmeden fveya boş bir liste geçirerek.
user2357112

12
@Bergi: O zaman bile, SATInstance.solvehemen çalıştırmayı denemeden yine de başka bir işleve geçmek ya da bir diğer inanılmaz pahalı işlevi kullanmak isterdim . Ayrıca, saf olarak ilan someFunctionedilip edilmediğine bağlı olarak farklı bir şey yaparsa işleri gerçekten garipleştirir someFunction. I (pseudocode) varsa, örneğin, func f() {return g}, func g() {doSomethingImpure}, ve func apply(x) {x()}daha sonra apply(f)aramaları f. Sonra beyan ederse fsaftır, sonra aniden apply(f)geçer giçin applyve applyçağrılar gve bir şey saf olmayan yok.
user2357112 5:16

6
@ user2357112 Değerlendirme stratejisi saflıktan bağımsızdır. Aramaların sözdizimini neyin mümkün olduğunu değerlendirmek için bir açıklama olarak kullanmak (ancak muhtemelen gariptir), ancak sonucu veya doğruluğunu değiştirmez. Örneğinizle ilgili olarak apply(f), eğer gsaf değilse (ve applyde?) O zaman her şey saf değildir ve elbette bozulur.
Bergi

14
Bunun örnekleri Python ve ECMAScript, ikisi de gerçekten bir "yöntemler" kavramına sahip değil, bunun yerine adsız bir birinci sınıf işlev nesnesi döndüren adlandırılmış bir özelliğiniz var ve daha sonra buna adsız birinci sınıf işlev diyorsunuz. Özellikle, Python ve ECMAScript'te hem de söyleyerek foo.bar()değil bir operasyon "çağrısı yöntemi barnesnenin foo" ziyade iki işlemleri, "alanına KQUEUE barnesnenin foo ardından obje o alanın döndü çağrı". Yani, .bir alan seçici operatörü ve ()bir çağrı operatörü ve bağımsızdır.
Jörg K Mittag

63

Nitekim, Scala buna izin vermektedir, ancak takip edilen bir kongre vardır: yöntem yan etkileri varsa, yine de parantez kullanılmalıdır.

Derleyici bir yazar olarak parantez içinde garantili varlığı oldukça uygun bulur; Bunun bir yöntem çağrısı olduğunu her zaman bilirdim ve garip durum için bir çatallanma oluşturmak zorunda kalmayacağım.

Bir programcı ve kod okuyucusu olarak, parantezlerin varlığı, hiçbir parametre geçmese de, yöntem çağrısı olduğundan kuşku duymaz.

Parametrelerin geçirilmesi, bir yöntem çağrısının tek tanımlayıcı özelliği değildir. Neden parametresiz bir metodu, parametreleri olan bir metottan farklı olarak kabul edeyim?


Teşekkürler ve bunun neden önemli olduğu konusunda geçerli sebepler verdiniz. Dil tasarımcılarının neden prototiplerde işlevleri kullanması gerektiğine dair örnekler de verebilir misiniz?
David Refoua

parantezlerin varlığı kuşkusuz, tamamen kabul ettiğim bir yöntem çağrısıdır . Programlama dillerimi örtükten daha açık olarak tercih ederim
Corey Ogburn, 15: 02'de

20
Scala aslında bundan biraz daha incedir: diğer diller yalnızca sıfır veya daha fazla parametreli bir parametre listesine izin verirken, Scala sıfır veya daha fazla parametreli sıfır veya daha fazla parametre listesine izin verir. Yani, def foo()bir boş parametre listesi içeren bir yöntemdir ve parametre listesi içermeyen def foobir yöntemdir ve ikisi farklı şeylerdir ! Genel olarak, parametre listesi içermeyen bir yöntemin argüman listesi olmadan çağrılması ve boş parametre listesi içeren bir yöntemin boş bir argüman listesiyle çağrılması gerekir. Parametre listesi olmayan, boş bir argüman içeren bir metot çağırmak aslında…
Jörg W Mittag

19
… Yöntem çağrısı tarafından döndürülenapply nesnenin yöntemini boş bir argüman listesiyle çağırmak olarak yorumlanırken, bir argüman listesi olmadan boş bir parametre listesiyle bir yöntemi çağırmak, içeriğe bağlı olarak, yöntemi boş bir argüman listesiyle çağırmak olarak çeşitli şekillerde yorumlanabilir, η kısmen uygulanan bir yönteme genişleme (yani "yöntem başvurusu"), ya da hiç derlenmeyebilir. Ayrıca, Scala Tekdüzen Erişim Prensibi'ni takip eder, argüman listesi olmadan bir metodu çağırmak ve bir alana referans vermek arasında (sözdizimsel olarak) ayrım yapmaz.
Jörg W Mittag

3
Gerekli "törenin" olmadığı için Ruby'yi takdir etsem bile - parens, kaşlı ayraçlar, açık tip - yöntem-parantezin daha hızlı okuduğunu söyleyebilirim ; ama bir zamanlar tanıdık deyimsel Ruby oldukça okunabilir ve kesinlikle daha hızlı yazmaktır.
radarbob

19

Bu aslında sözdizimi seçeneklerinin oldukça ince bir ifadesidir. Yazılan lamda matematiğine dayanan fonksiyonel dilleri konuşacağım.

Söz konusu dillerde, her işlevin tam olarak bir argümanı vardır . Sıklıkla "çoklu argüman" olarak düşündüğümüz şey aslında ürün tipi için tek bir parametredir. Örneğin, iki tam sayıyı karşılaştıran işlev:

leq : int * int -> bool
leq (a, b) = a <= b

tek bir tamsayı çifti alır. Parantez yok değil işlev parametreleri belirtmek; argümanla eşleşmek için kullanılırlar . Bunun gerçekten tek bir argüman olduğuna sizi ikna etmek için, bunun yerine parselin yapısını kaldırmak için desen eşleştirme yerine yansıtmalı fonksiyonları kullanabiliriz:

leq some_pair = some_pair.1 <= some_pair.2

Bu nedenle, parantez gerçekten desen eşleştirmemizi ve bazı yazı tiplerini kaydetmemizi sağlayan bir kolaylık. Onlar gerekli değildir.

Görünüşe göre tartışmasız bir fonksiyona ne dersiniz? Böyle bir fonksiyonun aslında bir alanı vardır Unit. Tek üye Unitgenellikle şu şekilde yazılır (), bu yüzden parantez içinde görünür.

say_hi : Unit -> string
say_hi a = "Hi buddy!"

Bu fonksiyonu çağırmak için, biz türünde bir değere uygulamak zorunda kalacak Unitolmalıdır (), bu yüzden yazma sonunda say_hi ().

Yani, bir tartışma listesi gibi bir şey gerçekten yok!


3
İşte bu yüzden boş parantezler ()kaşığı eksi kaşıklara benziyor.
Mindwin

3
Kullanmak yerine leqkullanan bir fonksiyonu tanımlamak oldukça kafa karıştırıcı! <<=
KRyan

5
Bu cevabı, "ürün tipi" gibi ifadelere ek olarak "tuple" kelimesini kullanıp kullanmadığını anlamak daha kolay olabilir.
Kevin,

Formalizmin çoğu int f (int x, int y) I ^ 2'den I'e bir fonksiyon olarak değerlendirir. Lambda matematiği farklıdır, bu metodu diğer formalizmlerde yüksek aritelikle eşleştirmek için kullanmaz. Bunun yerine lambda matematiği körelmeyi kullanır. Karşılaştırma, x -> (y -> (x <= y)) olacaktır. (x -> (y -> (x <= y)) 2, (y-> 2 <= y) olarak değerlendirir ve (x -> (y -> (x <= y)) 2, 3 olarak değerlendirir ( y-> 2 <= y) 3 sırasıyla 2 <= 3 olarak değerlendirilir
Taemyr

1
@PeriataBreatta ()Üniteyi temsil etmenin tarihini bilmiyorum . Sebeplerin en azından bir kısmı "parametresiz işlev" e benzenseydi şaşırmam. Ancak, sözdizimi için başka bir olası açıklama vardır. Türlerin cebirinde, Unitaslında ürün türlerinin kimliğidir. İkili bir ürün şu şekilde yazılır (a,b), bizim gibi tek bir ürün yazabiliriz (a), bu yüzden mantıklı bir uzantı nüler ürünü basitçe yazmak olacaktır ().
gardenhead,

14

Örneğin Javascript'te () olmadan bir yöntem adı kullanmak, işlevi çalıştırmadan döndürür. Bu şekilde, örneğin işlevi başka bir yönteme argüman olarak iletebilirsiniz.

Java'da, () veya (...) izleyen bir tanımlayıcının, bir yöntem değişkeni anlamına gelirken, () olmayan bir tanımlayıcı bir üye değişkenine başvurduğundan seçim yapıldı. Bu, bir yöntem veya üye değişkenle ilgilenip ilgilenmediğiniz konusunda hiçbir şüpheniz olmadığı için okunabilirliği artırabilir. Aslında, aynı isim hem bir yöntem hem de bir üye değişkeni için kullanılabilir, her ikisinin de kendi sözdizimleriyle erişilebilir olacaktır.


4
+1 Kodun insanlar tarafından okunması gerektiği sürece okunabilirlik kraldır.
Tulains Córdova

1
@ TulainsCórdova Perl'in sizinle aynı fikirde olduğundan emin değilim.
Racheet

@Racheet: Perl olmayabilir ama Perl Best Practicesyapar
slebetman

1
@Racheet Perl okunabilir şekilde yazılmışsa çok okunabilir. Ezoterik olmayan her dil için bu aynıdır. Kısa, özlü Perl, Perl programcılarına çok okunabilir, tıpkı Scala veya Haskell kodunun bu dillerde deneyimli insanlara okunması gibi. Dilinizi tamamen doğru olan çok kıvrımlı bir şekilde Almanca da konuşabiliyorum, ancak Almanca konusunda uzman olsanız bile, yine de bir kelimeyi anlamayacaksınız. Bu da Alman'ın suçu değil. ;)
simbabque 6:16

Java'da bir yöntemi "tanımlamaz". Onu çağırıyor. Object::toStringbir yöntemi tanımlar.
njzk2

10

Sözdizimi anlambilim izler, öyleyse anlambilimden başlayalım:

Bir işlev veya yöntem kullanmanın yolları nelerdir?

Aslında, birçok yol var:

  • işlev, bağımsız değişkenli veya değişkensiz çağrılabilir
  • bir fonksiyon değer olarak değerlendirilebilir
  • bir fonksiyon kısmen uygulanabilir (en az bir tane daha argüman alarak ve geçen argümanların kapatılmasıyla bir kapatma oluşturulması)

Farklı kullanımlar için benzer bir sözdizimine sahip olmak, belirsiz bir dil veya en azından kafa karıştırıcı bir dil oluşturmak için en iyi yoldur (ve bunlardan yeterince sahibiz).

C ve C benzeri dillerde:

  • Bir işlev çağrısı, olduğu gibi argümanları (hiçbiri olabilir) içine almak için parantez kullanılarak yapılır. func()
  • Bir işlevin bir değer olarak ele alınması, basitçe ismini kullanarak &func(C bir işaretçi oluşturma)
  • Bazı dillerde, kısmen uygulamak için kısa el sözdiziminiz vardır; Java, someVariable::someMethodörneğin izin verir (yöntem alıcısıyla sınırlıdır, ancak yine de yararlıdır)

Her kullanımın farklı bir sözdizimine sahip olduğunu ve bunları kolayca ayırt etmenizi sağladığını unutmayın.


2
Eh, "kolayca" bunlardan biri "zaten anlaşılmışsa anlaşılır" durumlarından biridir. Yeni başlayanlar, bazı noktalama işaretlerinin neden anlam ifade ettiklerini açıklamadan açık bir şekilde hiçbir şekilde net olmadığını açıkça belirtmekle haklı çıkar.
Eric Lippert

2
@EricLippert: Gerçekten de, kolayca sezgisel olmak zorunda değildir. Her ne kadar bu durumda parantezlerin matematikte "çağırma" işlevi için de kullanıldığını belirtmek isterim. Olduğu söyleniyor, ben birçok dilde yeni başlayanlar genel olarak sözdizimi daha kavramları / anlambilim ile mücadele ediyor buldum.
Matthieu M.

Bu cevap "körleme" ve "kısmi uygulama" arasındaki ayrımı karıştırır . ::Java operatör kısmi uygulama operatörü, bir tımar operatörüdür. Kısmi uygulama, bir işlev ve bir veya daha fazla değer alan ve daha az değer kabul eden bir işlev döndüren bir işlemdir. Körükleme, değerlerde değil, yalnızca işlevlerde çalışır.
Periata Breatta

@PeriataBreatta: İyi nokta, düzeltildi.
Matthieu M.,

8

Yan etkileri olan bir dilde IMO, bir değişkenin okunması arasında (teoride yan etki serbest) ayırt etmek gerçekten yararlıdır.

variable

ve yan etkilere neden olabilecek bir işlevi çağırmak

launch_nukes()

OTOH, eğer yan etki yoksa (tip sisteminde kodlananlar dışında), bir değişkeni okumakla argüman içermeyen bir işlevi çağırmak arasında ayrım yapmanın bir anlamı yoktur.


1
OP, bir nesnenin tek argüman olduğu ve işlev adından önce sunulan (işlev adı için bir kapsam da sağlayan) durumu sunduğunu unutmayın. noun.verbSözdizimi, anlamı kadar net noun.verb()ve biraz daha az karışıklık olabilir. Benzer şekilde, member_sol referansı döndüren bir fonksiyon tipik bir ayarlayıcı fonksiyonundan daha kolay bir sözdizimi sunabilir: obj.member_ = new_valuevs. obj.set_member(new_value)( _postfix, "gizli" fonksiyonlar için _ önekleri hatırlatan "açık" diyen bir ipucudur ).
Paul A. Clayton,

1
@ PaulA.Clayton Bunun cevabımın kapsamında olmadığını nasıl görmüyorum: noun.verbİşlev çağrısı anlamına gelirse , onu üye erişiminden nasıl ayırt edersiniz?
Daniel Jour,

1
Teorik olarak yan etkilerden arındırılmış değişkenleri okumakla ilgili olarak şunu söylemek istiyorum: Her zaman yanlış arkadaşlara dikkat edin .
Justin Time

8

Diğer cevapların hiçbiri şu soru ile başa çıkmaya çalışmadı: Bir dil tasarımında ne kadar fazlalık olması gerekiyor? Çünkü bir dili x = sqrt yx'i y'nin kareköküne ayarlayacak şekilde tasarlasanız bile , bu mutlaka yapmanız gerektiği anlamına gelmez.

Artıklık olmayan bir dilde, her karakter dizisi bir şey ifade eder, yani tek bir hata yaparsanız, bir hata mesajı almazsınız, programınız yanlış olanı yapar, bu da sizden çok farklı bir şey olabilir amaçlanan ve hata ayıklamak çok zor. (Düzenli ifadelerle çalışan herkesin bileceği gibi.) Küçük bir fazlalık iyi bir şeydir, çünkü hatalarınızın çoğunun tespit edilmesini sağlar ve orada fazlalık olması ne kadar fazla olursa, teşhislerin doğru olması o kadar olasıdır. Şimdi elbette, bunu çok uzağa götürebilirsiniz (bugünlerde hiçbirimiz COBOL'da yazmak istemiyoruz), fakat doğru olan bir denge var.

Artıklık, okunabilirliğe de yardımcı olur, çünkü daha fazla ipucu vardır. Artıklık olmadan İngilizce okumak çok zor olurdu ve aynı programlama dilleri için de geçerlidir.


Bir anlamda katılıyorum: programlama dilleri “güvenlik ağı” mekanizmasına sahip olmalıdır. İşte - Ama ben sözdiziminde “küçük bir fazlalık” Bu konuda gitmek için iyi bir yol olduğunu katılmıyorum Demirbaş ve ne çoğunlukla yapar noktaya zor hatalar yapar gürültü tanıtmak olduğunu ve dikkatini dağıtabilir sözdizimi hataları için olanaklar açılır gerçek böcekler. Okunabilirliğe yardımcı olan ayrıntı türünün sözdizimi ile, daha çok adlandırma kuralları ile ilgisi yoktur . Ve bir güvenlik ağı, en rastgele değişikliklerin programı kötü niyetli hale getireceği güçlü bir tip sistemi olarak en verimli şekilde uygulanır .
leftaroundabout

@leftaroundabout: Dil tasarımı kararlarını Hamming mesafesi açısından düşünmeyi seviyorum. İki yapının farklı anlamları varsa, bunların en az iki şekilde farklılık göstermesi ve sadece bir şekilde farklılık gösteren bir biçime sahip bir derleyici ciyakası üretmesi yararlı olur. Dil tasarımcısı genel olarak tanımlayıcıların kolayca ayırt edilebildiğinden emin olmaktan sorumlu olamaz, ancak örneğin ödev gerektiriyorsa :=ve karşılaştırıyorsa ==, =yalnızca derleme zamanı başlatma için kullanılabilir olması durumunda, karşılaştırmaları ödevlere dönüştürmek için yazım hataları büyük ölçüde azalacaktır.
supercat

@leftaroundabout: Aslına bakarsanız, eğer bir dil tasarlarsam, muhtemelen ()sıfır argümanlı bir fonksiyonun başlatılmasını gerektirir , fakat aynı zamanda bir fonksiyonun "adresini almak" için bir belirteç isterim . İlk eylem çok daha yaygındır, bu yüzden daha az yaygın olan durumda bir jeton tasarrufu yapmak o kadar da faydalı değildir.
supercat,

@supercat: peki, yine bence bu problemi yanlış seviyede çözüyor. Atama ve karşılaştırma kavramsal olarak farklı işlemlerdir, bu nedenle sırasıyla işlev değerlendirmesi ve işlev adresi almadır. Bu nedenle açıkça belirgin tiplere sahip olmaları gerekir, o zaman operatörlerin Hamming mesafesinin düşük olması durumunda artık bir önemi yoktur, çünkü herhangi bir yazım hatası derleme zamanı tipi bir hata olacaktır.
leftaroundabout

@leftaroundabout: Eğer bir boole tipi değişkeni atama yapılıyorsa veya bir işlevin dönüş tipi bir işleve bir işaretçi ise (veya - bazı dillerde - gerçek bir işlev), bir karşılaştırmayı bir atama ile değiştirerek, ya da bir işlev referansı ile bir işlev çağrısı, sözdizimsel olarak geçerli olan ancak orijinal versiyondan tamamen farklı bir anlama sahip olan bir program sağlayabilir. Tip kontrolü genel olarak bu gibi bazı hataları bulacaktır, ancak sözdizimini belirgin kılmak daha iyi bir yaklaşım gibi görünmektedir.
Supercat,

5

Çoğu durumda, bunlar dilin dilbilgisinin sözdizimsel seçimleridir. Çeşitli bireysel yapıların birlikte alındıklarında (göreceli olarak) belirgin olmaları için dilbilgisi için faydalıdır. (Bazı C ++ bildirimlerinde olduğu gibi belirsizlikler varsa, çözüm için belirli kurallar olması gerekir.) Derleyicinin tahmin etme enlemi yoktur; dil şartnamesini takip etmek gerekir.


Visual Basic, çeşitli formlarda, değer döndürmeyen prosedürler ile işlevler arasında farklılık gösterir.

Prosedürler bir ifade olarak adlandırılmalıdır ve parens gerektirmez, varsa virgülle ayrılmış argümanlar gerekir. İşlevler ifadenin bir parçası olarak çağrılmalıdır ve parens gerektirir.

İki form arasında manuel yeniden düzenlemeyi olması gerekenden daha acı verici hale getiren nispeten gereksiz bir ayrımdır.

(Öte yandan Visual Basic aynı parens kullanan ()diğer diller kullanmak düşünmek olabilir, fonksiyon çağrıları için büyüdükçe dizi referanslar için, bu nedenle dizi referanslar fonksiyon çağrıları benziyorsun. Ve bu işlev çağrısı içine bir dizinin manuel üstlenmeden kolaylaştırır! Yani []'s dizi referansları için, ancak digress…)


C ve C ++ dillerinde değişkenlerin içeriklerine isimleri kullanılarak otomatik olarak erişilir ve içeriği yerine değişkenin kendisine başvurmak istiyorsanız, unary &operatörünü uygularsınız .

Bu tür bir mekanizma fonksiyon isimlerine de uygulanabilir. İşlenmemiş işlev adı, bir işlev çağrısı anlamına gelebilir; oysa, unary &işlevi, işlevi (kendisine) veri olarak adlandırmak için kullanılır. Şahsen, yan etki içermeyen argüman işlevlerine değişkenlerle aynı sözdizimi ile erişme fikrini seviyorum.

Bu tamamen mantıklı (bunun için başka sözdizimsel seçimler olduğu gibi).


2
Elbette, görsel temelin prosedür çağrıları üzerindeki parantez eksikliği, işlev çağrılarıyla karşılaştırıldığında gereksiz bir ayrım olsa da, bunlara gerekli parantezlerin eklenmesi , çoğu BASIC kaynaklı bir dilin çok etkisi olan ifadeler arasında gereksiz bir ayrım olacaktır. prosedürleri hatırlatan. Ayrıca, bir MS BASIC sürümünde herhangi bir çalışma yaptığımdan bu yana bir süre geçti, ancak sözdizimine hala izin vermiyor call <procedure name> (<arguments>)mu? Başka bir hayatta QuickBASIC programlaması yaptığımda, prosedürleri geri almanın geçerli bir yolu olduğuna eminim ...
Periata Breatta

1
@PeriataBreatta: VB hala "call" sözdizimine izin veriyor ve bazen aranacak şeyin bir ifade olduğu durumlarda [örneğin, "Call If (someCondition, Delegate1, Delegate2) (Bağımsız Değişkenler)" diyebilir, fakat doğrudan "If" işlecinin sonucunun çağrılması, bağımsız bir ifade olarak geçerli olmaz].
supercat

@PeriataBreatta DSL benzeri kodun iyi görünmesini sağladığı için VB6'nın parantez yordam çağrıları yapmamasını sevdim.
Mark Hurd

@supercat LinqPad'de, Callneredeyse "normal" üretim kodunda neredeyse hiç ihtiyaç duymadığım bir yöntem için ne kadar sıklıkla kullanmam gerektiği şaşırtıcı .
Mark Hurd

5

Tutarlılık ve okunabilirlik.

Sana işlevi çağırmak olduğunu öğrenirsek Xböyle: X(arg1, arg2, ...)o zaman ben hiçbir argümanlar için aynı şekilde çalışır bekliyoruz: X().

Şimdi aynı zamanda değişkeni bir sembol olarak tanımlayabileceğinizi ve bunun gibi kullanabileceğinizi öğrendim:

a = 5
b = a
...

Şimdi bunu bulduğumda ne düşünürdüm?

c = X

Tahminin benimki kadar iyi. Normal koşullarda, Xbir değişkendir. Fakat yolunuza gidersek, bunun bir işlevi de olabilir! Hangi sembolün hangi gruba eşlenip eşleşmediğini (değişkenler / fonksiyonlar) hatırlamıyor muyum?

“İşlevler büyük harfle başlar. Değişkenler küçük harfle başlar” gibi yapay kısıtlamalar uygulayabiliriz, ancak bu gerekli değildir ve bazen tasarım hedeflerinin bazılarına yardımcı olsa da işleri daha karmaşık hale getirir.

1. Not: Diğer cevaplar bir şeyi daha görmezden gelir: dil, aynı işlevi hem işlev hem de değişken için kullanmanıza ve bağlamla ayırt etmenize izin verebilir. Common LispÖrnek olarak görün . İşlev xve değişken xmükemmel bir şekilde bir arada bulunur.

Yan not 2: Kabul cevabı bize sözdizimi gösterilmektedir: object.functionname. İlk olarak, birinci sınıf fonksiyonları olan diller için evrensel değildir. İkincisi, bir programcı olarak bunu ek bir bilgi olarak ele functionnamealırdım : a object. İster objectbir nesne, bir sınıf veya bir ad o kadar önemli değil, ama buna ait olduğunu söyler yerde . Bu object., her bir küresel işlev için yapay sözdizimi eklemek veya objecttüm küresel işlevleri tutmak için bazılarını oluşturmak zorunda olduğunuz anlamına gelir .

Her iki durumda da, fonksiyonlar ve değişkenler için ayrı ad alanlarına sahip olma özelliğini kaybedersiniz.


Evet. Tutarlılık yeterince iyi bir nedendir, tam durma (diğer noktalarınızın geçerli olmadığı değil - bunlar geçerli).
Matthew

4

Diğer cevaplara eklemek için şu C örneğini alın:

void *func_factory(void)
{
        return 0;
}

void *(*ff)(void);

void example()
{
        ff = func_factory;
        ff = func_factory();
}

Eğer çağrı operatörü isteğe bağlı olsaydı, işlev ataması ile işlev çağrısı arasında ayrım yapmanın bir yolu olmazdı.

Bu tür bir sistemden yoksun olan dillerde daha da problemlidir, örneğin JavaScript, tür çıkarımının neyin bir fonksiyon olup olmadığını anlamak için kullanılamaması.


3
JavaScript, bir tür sistemden yoksundur. Tip bildirimlerinden yoksun . Ancak farklı değer türleri arasındaki farkın tamamen farkındadır.
Periata Breatta

1
Periata Breatta: Konu Java değişkenlerinin ve özelliklerinin herhangi bir değer türü içerebileceğidir, bu nedenle kod okuma zamanında bir işlev olup olmadığını her zaman bilemezsiniz.
reinierpost

Örneğin, bu işlev ne yapar? function cross(a, b) { return a + b; }
Mark K Cowan

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.