İşlevin adına atanarak dönüş değeri hangi dil (ler) de ayarlanır?
Bu Yığın Taşması sorusunda , orijinal kod, işlev adını bir değişken olarak kullanma hatasını yaptı ve ona dönüş değerini atadı. Bir yorumcu , bir zamanlar işlevlerden değeri döndürdüğünüz şekilde bir dil kullandığından bahsetmişti. Yorumda, "Bir işlevin dönüş değerinin işlevin adına atanması gereken bir dil kullandığımı biliyorum. O kadar eski ve modası geçmiş ki, hangi dil olduğunu bile hatırlayamıyorum."
Bu bana tanıdık geliyor ama hangi dil olduğunu da hatırlayamıyorum.
Bizden daha iyi hafızaya sahip olan ve bize hangi dil olduğunu söyleyebilir mi?
Yanıtlar
Bunu Pascal yapar, başkalarını bilmiyorum. Uygulamanın diğer Wirth dilleriyle ilerleyip ilerlemediğini bilmiyorum.
Visual Basic ailesindeki diller tam olarak bunu yapar. Buna VBScript, VBA, Visual Basic ve önceki sürümler dahildir. Bunların QBASIC'den "özelliği" miras aldığına inanıyorum. Örneğin
Public Function AddTwo(something as Integer)
AddTwo = something + 2
End Function
Fortran, elbette:
PROGRAM TRIANG
WRITE(UNIT=*,FMT=*)'Enter lengths of three sides:'
READ(UNIT=*,FMT=*) SIDEA, SIDEB, SIDEC
WRITE(UNIT=*,FMT=*)'Area is ', AREA3(SIDEA,SIDEB,SIDEC)
END
FUNCTION AREA3(A, B, C)
*Computes the area of a triangle from lengths of sides
S = (A + B + C)/2.0
AREA3 = SQRT(S * (S-A) * (S-B) * (S-C))
END
(Clive G. Page'in Profesyonel Programcı Kılavuzu'ndan Fortran77 ).
Fortran ANSI X 3.9 1966 Fortran 66 standardında da bu şekilde tanımlanmıştır .
Bulabildiğim en eski diller, her ikisi de aynı yıl 1958'de yayınlanan FORTRAN II ve ALGOL 58; orijinal FORTRAN (1956) da tartışmalı bir şekilde dahil edilebilir.
FORTRAN için, işlevlerle ilgili kılavuz bölümünün ilk sayfası şu örneği içerir (s. 27):
FUNCTION AVRG (ALIST, N)
DIMENSION ALIST (500)
SUM = ALIST (1)
DO 10 I=2, N
SUM = SUM + ALIST (I)
AVRG = SUM / FLOATF (N)
RETURN
END (2, 2, 2, 2, 2)
FORTRAN II ayrıca öncülünden miras alınan tek satırlık işlev tanımı olan başka bir işlev sözdizimi (s. 10) içerir:
FIRSTF(X) = A*X + B
Önceki sözdiziminin, ikincisinin doğal bir uzantısı olduğunu ve dolayısıyla matematiksel kullanımdan geldiğini görmek zor değil.
ALGOL 58 , FORTRAN'a benzer şekilde, her iki tek satırlı 'işlevi' tanımlar:
Bir işlev bildirimi, belirli bir ifadeyi değişkenlerinden bazılarının bir işlevi olarak bildirir. Bu nedenle, bildirim (belirli basit işlevler için), bu işlev bir ifadede göründüğünde işleve değer atamak için hesaplama kuralını ( işlevlerle karşılaştırın ) verir.
Form: Δ ~ I n (I, I, ~, I): = E burada I tanımlayıcıdır ve E, bileşenleri arasında parantez içinde görünen tanımlayıcılar tarafından adlandırılan basit değişkenler içerebilen bir ifadedir.
ve bugünün işlev tanımına eşdeğer olan 'prosedürler' (en azından zorunlu / prosedürel programlama dillerinde). Dönüş değeri aşağıdaki şekilde gösterilir (s. 19):
Başlıkta listelenen her bir tek çıkış prosedürü I (P i ) için, prosedür dahilinde bir atama ifadesi "I: = E" ile bir değer atanmalıdır, burada I, bu prosedürü adlandıran tanımlayıcıdır.
Bu sözdizimleri daha sonra BASIC'in bazı lehçeleri (şeklinde DEF FN
ve daha sonra FUNCTION
) ve ALGOL'un soyundan gelen Pascal: Borland'ın Pascal derleyicilerinde, Result
Delphi 1.0'da değişkenin tanıtılmasından önce desteklenen tek sözdizimiydi .
Muhtemelen adı geçen yorumcunun hatırladığı Pascal'dır; bazı üniversiteler hala içinde programlama öğretiyor ve genellikle Object Pascal gibi modern genişletilmiş lehçeler yerine orijinal, standart çeşitliliğe bağlı kalıyor. (Bu gerçekten sorunun bir parçası değil, ancak StackOverflow sorusunun yanlış anlamasının da bundan kaynaklandığını varsayıyorum.)
TL; DR:
80'li yılların başlarında oldukça popüler olduğu için, 80'li yıllardan 90'lara kadar Üniversite kurslarında kullanılan ve daha sonra hala orada, en önemlisi Delphi'den bir miktar arkadaşlık kurduğu için PASCAL olduğunu söyleyebilirim.
Bazı Tarihler
Temel fikir, işlev adının yalnızca önceden ayrılmış olmamasıdır, bu nedenle farklı bir şey bulmaya gerek yoktur ve bunu kullanmak, sonucun bu olduğu açık bir ifadedir. Arama kuralı içinde ayrılmış bir veri öğesi tahsis edilebildiğinden, derleyici tasarımını da basitleştirir.
Esasen iki miras hattı vardır, FORTRAN ve ALGOL.
Her ikisi için de torunlarından bazıları tuttu, mesela
- FORTRAN'dan bazı TEMEL varyantlar ve
- ALGOL'dan Pascal ve Modula.
ALGOL'un takibi gibi diğerleri bunu düşürdü
return()
Sözdizimini tanıtan BCPL ,
Bu, C'nin BCPL'den aldığı günümüzde oldukça yaygındır.
Dil fikirleri, ana bilgisayarlar arasında sıçrayan genler gibidir. Örneğin ADA, birçok yönden bir ALGOL / PASCAL torunu da bir return
element kullanmaya yöneldi .
Granddaddy FORTRAN, yıllar içinde işlev sonuçlarını döndürme yöntemini değiştirdi.
- Başlangıçta bir işlevin sonucu, işlevin tanımlayıcısına atandı
- FORTRAN 90 ile işlev başlığında bir dönüş adının açık tanımı tanıtıldı.
Bu aslında sadece sözdizimsel bir şeker olsa da, tarzda bir değişikliğe sahiptir. Uygulanan akıl yürütme, gibi özyineleme yapılarının Foo = Foo(x-1)
garip görüneceğiydi. Ama sanırım bu yoruma bağlı.
Burada ilginç olan, 1958'in FORTRAN II'sinin RETURN
prosedürel programlama ekleme çabasında bir ifade sunmasıdır, ancak kullanımı basitçe yürütmeyi bir çağırana geri döndürmekti, dönüş değerinin ayrı olarak ayarlanması gerekiyordu.
Fortran, bu sözdizimini en eski sürümden Fortran 2008 ve sonrasına kadar işlevlere sahip olan en eski sürümden kullandı.
Ancak Fortran 2008, bir fonksiyon değeri döndürmek için kullanılan farklı bir değişken adı tanımlayabileceğiniz (daha da kafa karıştırıcı?) Bir seçeneğe sahiptir! Örneğin
function xyz(argument) result(answer)
...
answer = 42
...
end function xyz
eski tarz yerine
...
xyz = 42
...
Biri için Algol 60.
Algoritmik Dil Algol 60 Üzerine Revize Edilmiş Rapordaki ilgili kelimeler .
5.4.4. Fonksiyon belirleyicilerinin değerleri.
Bir prosedür bildiriminin bir fonksiyon göstericisinin değerini tanımlaması için, prosedür bildirimi gövdesi içinde, sol kısımda prosedür tanımlayıcısı ile bir veya daha fazla açık atama ifadesinin olması gerekir; bunlardan en az biri yürütülmeli ve prosedür tanımlayıcısıyla ilişkili tür, prosedür bildiriminin ilk sembolü olarak bir tür tanımlayıcısının ortaya çıkmasıyla bildirilmelidir. Bu şekilde atanan son değer, işlev göstericisinin meydana geldiği ifadenin değerlendirilmesine devam etmek için kullanılır.
Prosedür tanımlayıcısının, bir atama ifadesinin sol kısmı dışında prosedürün gövdesi içinde herhangi bir oluşumu, prosedürün etkinleştirilmesini belirtir.
Son cümle anlamlıdır - tip prosedürün (fonksiyon) adının prosedür (fonksiyon) gövdesi içindeki bir değişken 'gibi' ele alınmadığını gösterir; daha ziyade, özel kasalı olan yalnızca atamadır.
Algol 60'da, bağımsız değişken almayan bir işleve yapılan çağrının ardından boş parantezler gelmez: bu nedenle n := read
değil n := read()
.
Son cümle de varlık olarak ünlüdür cümle diline özyinelemeli prosedürler var. Ancak bu, bu yanıtla ilgili değil.
BASIC, bazı lehçelerin dönüş değerini sağlamak için işlev adına atamayı kullandığı işlevlere sahip başka bir dildir. En eski lehçeler, Fortran tek hat işlevlerine benziyordu:
DEF FND(x) = x*x
Ancak daha sonraki lehçeler, Fortran çok hatlı işlevlere benzer şekilde daha karmaşık değişkenlere izin verdi :
DEF FNPeekWord& (A&)
FNPeekWord& = PEEK(A&) + 256& * PEEK(A& + 1)
END DEF
MATLAB / Octave de bunu yapar.
1984 yılından; diğerlerinden bazıları kadar eski değil.
Başlangıçta üst düzey bir araç olarak düşünüldüğü için muhtemelen Fortran'ı taklit ediyordu. Linpack ve Eispack gibi Fortran kütüphanelerinin üstünde.
SNOBOL4'ün bunu yaptığına inanıyorum. http://berstis.com/greenbook.pdf
Aşağıda, sayıların faktöriyellerini hesaplamak için bir işlevin tanımı ve kullanımına bir örnek verilmiştir:
DEFINE('FACT(N)') :(SKIPFCN) * Set value to 1 FACT FACT = 1 * Return 1 if N<2 * Return N*((N-1)!) with recursive call FACT = GT(N,1) FACT(N - 1) * N :(RETURN) SKIPFCN OUTPUT = '5 factorial is ' FACT(5)
http://berstis.com/s4ref/prim3e.htm
Verilog (1995/2001) ayrıca örtük değişkene atama yoluyla geri döner. SystemVerilog "return" ifadesini ekledi ancak klasik atama hala kullanılabilir.
Haskell (1990'dan itibaren) bunu da yapıyor:
doubleMe x = x + x
doubleMe
bir parametrenin işlevini tanımlar x
ve x+x
ona işlev gövdesini atar , bkz. Büyük İyi Bir Haskell Öğrenin Harika Bir Haskell
Pascal, bunu yapmak için kişisel olarak kullandığım biridir. Common Lisp biraz-ama-gerçekten yapmaz, çünkü dönüş değerleri neredeyse her zaman örtüktür (yani her ifadenin bir değeri vardır ve bir bloktaki son değer bloğun dönüş değeridir), bu nedenle çok nadiren görürsünüz Eğer bir değer döndürmek gerekiyor ve örtük bir şekilde kullanamadığı zaman açık bir return ifadesi, ancak, bunu yapmanın yolu kullanmaktır RETURN-FROM
[*] aynen böyle deyimi: (return-from function-name value)
.
[*] Orada da bir var RETURN
deyimi, ancak bir kısaltmadır var (return-from nil value)
ve olacak değil yapma etkisine sahip VALUE
yürütüldüğünde edildiği işlevinin değerini. C ve onun soyundan gelen yeni başlayanlar için büyük bir tuzak.