ค่าส่งกลับถูกกำหนดโดยการกำหนดให้กับชื่อฟังก์ชันในภาษาใด
ในคำถาม Stack Overflowนี้รหัสเดิมทำผิดพลาดในการใช้ชื่อฟังก์ชันเป็นตัวแปรและกำหนดค่าส่งคืนให้ ผู้แสดงความคิดเห็นกล่าวว่าครั้งหนึ่งเขาเคยใช้ภาษาซึ่งเป็นวิธีที่คุณส่งคืนค่าจากฟังก์ชัน ความคิดเห็นอ่านว่า "ฉันรู้ว่าครั้งหนึ่งฉันเคยใช้ภาษาที่ต้องกำหนดค่าส่งคืนของฟังก์ชันให้กับชื่อของฟังก์ชันมันโบราณและล้าสมัยมากฉันจำไม่ได้ด้วยซ้ำว่าเป็นภาษาใด"
ฟังดูคุ้น ๆ เหมือนกัน แต่จำไม่ได้เหมือนกันว่าเป็นภาษาอะไร
มีใครมีความจำดีกว่าเราและบอกเราได้ไหมว่ามันคือภาษาอะไร?
คำตอบ
ปาสคาลทำแบบนี้ฉันไม่รู้จักคนอื่น ไม่รู้ว่าการฝึกฝนก้าวไปข้างหน้าด้วยภาษาเวิร์ ธ อื่น ๆ หรือไม่
ภาษาในตระกูล Visual Basic ทำเช่นนี้ ซึ่งรวมถึง VBScript, VBA, Visual Basic และรุ่นก่อนหน้า ฉันเชื่อว่าสิ่งเหล่านี้สืบทอด "คุณลักษณะ" จาก QBASIC ตัวอย่างเช่น
Public Function AddTwo(something as Integer)
AddTwo = something + 2
End Function
Fortran แน่นอน:
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 สำหรับ Fortran77 )
นอกจากนี้ยังกำหนดวิธีการที่ใน Fortran ANSI X 3.9 1966 Fortran 66มาตรฐาน
ภาษาที่เร็วที่สุดที่ฉันสามารถหาได้คือ FORTRAN II และ ALGOL 58 ซึ่งทั้งสองได้รับการตีพิมพ์ในปีพ. ศ. 2501 แม้ว่า FORTRAN ดั้งเดิม (1956) สามารถรวมเนื้อหาได้ด้วย
สำหรับ FORTRAN หน้าแรกของบทคู่มือที่ครอบคลุมฟังก์ชันประกอบด้วยตัวอย่างนี้ (น. 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 ยังมีไวยากรณ์ของฟังก์ชันอื่น (หน้า 10) นิยามฟังก์ชันบรรทัดเดียวซึ่งสืบทอดมาจากตัวประมวลผลล่วงหน้า:
FIRSTF(X) = A*X + B
ไม่ยากที่จะดูว่าไวยากรณ์ในอดีตเป็นส่วนขยายตามธรรมชาติของส่วนหลังอย่างไรซึ่งมาจากการใช้งานทางคณิตศาสตร์
ALGOL 58คล้ายกับ FORTRAN กำหนด 'ฟังก์ชัน' บรรทัดเดียว:
การประกาศฟังก์ชันประกาศนิพจน์ที่กำหนดให้เป็นฟังก์ชันของตัวแปรบางตัว ดังนั้นการประกาศจึงให้กฎการคำนวณ (สำหรับฟังก์ชันพื้นฐานบางอย่าง) สำหรับการกำหนดค่าให้กับฟังก์ชัน ( ฟังก์ชัน cf. ) เมื่อใดก็ตามที่ฟังก์ชันนี้ปรากฏในนิพจน์
รูปแบบ: Δ ~ I n (I, I, ~, I): = E โดยที่ I เป็นตัวระบุและ E คือนิพจน์ซึ่งในบรรดาองค์ประกอบอาจมีตัวแปรง่ายๆที่ตั้งชื่อโดยตัวระบุที่ปรากฏในวงเล็บ
และ 'ขั้นตอน' เทียบเท่ากับคำจำกัดความของฟังก์ชันในปัจจุบัน (อย่างน้อยในภาษาโปรแกรมที่จำเป็น / ขั้นตอน) ค่าที่ส่งคืนจะระบุไว้ดังนี้ (หน้า 19):
สำหรับแต่ละโพรซีเดอร์เอาต์พุตเดี่ยว I (P i ) ที่แสดงรายการในส่วนหัวต้องกำหนดค่าภายในโพรซีเดอร์โดยคำสั่งกำหนด“ I: = E” โดยที่ฉันเป็นตัวระบุที่ตั้งชื่อโพรซีเดอร์
ไวยากรณ์เหล่านี้ถูกนำมาใช้ในภายหลังโดยบางภาษาของ BASIC (ในรูปแบบของDEF FN
และในภายหลังFUNCTION
) และ Pascal ที่สืบทอดมาของ ALGOL: ในคอมไพเลอร์ Pascal ของ Borland การกำหนดให้กับชื่อฟังก์ชันเป็นเพียงไวยากรณ์ที่รองรับก่อนที่จะมีการเปิดตัวResult
ตัวแปรใน Delphi 1.0
อาจเป็นภาษาปาสคาลที่ผู้แสดงความคิดเห็นดังกล่าวจำได้ มหาวิทยาลัยบางแห่งยังคงสอนการเขียนโปรแกรมอยู่และมักยึดติดกับความหลากหลายมาตรฐานดั้งเดิมแทนที่จะใช้ภาษาถิ่นแบบขยายที่ทันสมัยเช่น Object Pascal (นี่ไม่ได้เป็นส่วนหนึ่งของคำถามจริงๆ แต่ฉันคิดว่าความเข้าใจผิดของผู้ถาม StackOverflow ก็มาจากเรื่องนั้นเช่นกัน)
TL; DR:
ฉันจะบอกว่าน่าจะเป็น PASCAL ที่คุณจำได้เพราะมันค่อนข้างเป็นที่นิยมในช่วงต้นยุค 80 ซึ่งใช้ในหลักสูตรของมหาวิทยาลัยตลอดช่วงยุค 80 จนถึงยุค 90 และยังคงมีมิตรภาพที่นั่นหลังจากนั้นโดยเฉพาะอย่างยิ่ง Delphi
ประวัติศาสตร์บางส่วน
แนวคิดพื้นฐานคือชื่อฟังก์ชันไม่ได้ถูกสงวนไว้แล้วเท่านั้นดังนั้นไม่จำเป็นต้องคิดอะไรที่แตกต่างออกไปและการใช้มันเป็นคำสั่งที่ชัดเจนว่านี่คือผลลัพธ์ นอกจากนี้ยังช่วยลดความยุ่งยากในการออกแบบคอมไพลเลอร์เนื่องจากสามารถจัดสรรรายการข้อมูลเฉพาะได้ภายในหลักการเรียก
โดยพื้นฐานแล้วมีมรดกสองสายคือ FORTRAN และ ALGOL
สำหรับลูกหลานของพวกเขาทั้งสองบางคนเก็บมันไว้เช่น
- ตัวแปรพื้นฐานบางตัวจาก FORTRAN และ
- Pascal และ Modula จาก ALGOL
คนอื่น ๆ ลดลงเช่น ALGOL ติดตาม
- BCPL ซึ่งแนะนำ
return()
ไวยากรณ์
ซึ่งเป็นเรื่องปกติในปัจจุบันเนื่องจาก C นำมาจาก BCPL
ความคิดทางภาษาเปรียบเสมือนยีนที่กระโดดไปมาระหว่างโฮสต์ ตัวอย่างเช่น ADA ในหลาย ๆ ทางหลานของ ALGOL / PASCAL ก็หันมาใช้return
องค์ประกอบเช่นกัน
ในช่วงหลายปีที่ผ่านมา Granddaddy FORTRAN มีวิธีการส่งคืนผลลัพธ์ของฟังก์ชันแตกต่างกันไป
- แต่เดิมผลลัพธ์ของฟังก์ชันถูกกำหนดให้กับตัวระบุของฟังก์ชัน
- ด้วย FORTRAN 90 คำจำกัดความที่ชัดเจนของชื่อส่งคืนในส่วนหัวของฟังก์ชันถูกนำมาใช้
แม้ว่านี่จะเป็นเพียงน้ำตาลสังเคราะห์ แต่ก็มีการเปลี่ยนแปลงในรูปแบบ เหตุผลที่นำไปใช้คือด้วยโครงสร้างการเรียกซ้ำFoo = Foo(x-1)
จะดูแปลก ๆ แต่ฉันเดาว่าขึ้นอยู่กับการตีความ
ที่น่าสนใจเช่นกันก็คือ FORTRAN II ปี 1958 ได้แนะนำRETURN
คำสั่งในความพยายามที่จะเพิ่มการเขียนโปรแกรมขั้นตอน แต่การใช้งานเป็นเพียงการส่งคืนการดำเนินการไปยังผู้โทรเท่านั้นค่าส่งคืนจะต้องถูกตั้งค่าแยกต่างหาก
Fortran ใช้ไวยากรณ์นี้ตั้งแต่รุ่นแรกสุดซึ่งมีฟังก์ชันเลยจนถึง Fortran 2008 และรุ่นที่ใหม่กว่า
อย่างไรก็ตาม Fortran 2008 มีตัวเลือก (สับสนมากยิ่งขึ้น?) ที่คุณสามารถประกาศชื่อตัวแปรอื่นที่ใช้เพื่อส่งคืนค่าฟังก์ชัน! ตัวอย่างเช่น
function xyz(argument) result(answer)
...
answer = 42
...
end function xyz
แทนรูปแบบเก่า
...
xyz = 42
...
Algol 60 สำหรับหนึ่ง
นี่คือคำที่เกี่ยวข้องจากแก้ไขรายงานในขั้นตอนภาษา Algol 60
5.4.4. ค่าของตัวกำหนดฟังก์ชัน
สำหรับการประกาศโพรซีเดอร์เพื่อกำหนดค่าของตัวกำหนดฟังก์ชันจะต้องมีในส่วนของการประกาศโพรซีเดอร์ที่มีคำสั่งการกำหนดอย่างชัดเจนอย่างน้อยหนึ่งคำสั่งพร้อมตัวระบุโพรซีเดอร์ในส่วนด้านซ้าย ต้องดำเนินการอย่างน้อยหนึ่งอย่างและประเภทที่เกี่ยวข้องกับตัวระบุโพรซีเดอร์ต้องถูกประกาศผ่านรูปลักษณ์ของตัวประกาศประเภทเป็นสัญลักษณ์แรกสุดของการประกาศโพรซีเดอร์ ค่าสุดท้ายที่กำหนดจะถูกใช้เพื่อดำเนินการประเมินนิพจน์ที่ตัวกำหนดฟังก์ชันเกิดขึ้นต่อไป
การเกิดขึ้นของตัวระบุโพรซีเดอร์ใด ๆ ภายในเนื้อหาของโพรซีเดอร์นอกเหนือจากในส่วนซ้ายในคำสั่งการกำหนดหมายถึงการเปิดใช้งานโพรซีเดอร์
ประโยคสุดท้ายมีความสำคัญ - แสดงให้เห็นว่าชื่อของขั้นตอนประเภท (ฟังก์ชัน) ไม่ได้รับการปฏิบัติ 'เหมือนกับ' ตัวแปรภายในตัวกระบวนงาน (ฟังก์ชัน) แต่จะเป็นเพียงการมอบหมายงานที่มีลักษณะพิเศษเท่านั้น
ใน Algol 60, เรียกร้องให้ฟังก์ชั่นที่ใช้เวลาไม่มีข้อโต้แย้งไม่ได้ตามด้วยวงเล็บที่ว่างเปล่าจึงมากกว่าn := read
n := read()
ประโยคสุดท้ายมีชื่อเสียงเช่นกันว่าเป็นประโยคที่มีขั้นตอนการเรียกซ้ำในภาษา แต่นั่นไม่ใช่สิ่งสำคัญสำหรับคำตอบนี้
ภาษาเบสิกเป็นภาษาอื่นที่มีฟังก์ชันที่ภาษาถิ่นบางภาษาใช้การกำหนดชื่อฟังก์ชันเพื่อให้ค่าส่งกลับ ภาษาถิ่นแรกสุดนั้นคล้ายคลึงกับฟังก์ชันบรรทัดเดียวของ Fortran:
DEF FND(x) = x*x
แต่ภาษาถิ่นในภายหลังอนุญาตให้มีรูปแบบที่ซับซ้อนมากขึ้นเช่นเดียวกับฟังก์ชันหลายบรรทัดของ Fortran :
DEF FNPeekWord& (A&)
FNPeekWord& = PEEK(A&) + 256& * PEEK(A& + 1)
END DEF
MATLAB / Octave ก็ทำเช่นนี้เช่นกัน
มาจากปีพ. ศ. 2527 จึงไม่เก่าเหมือนของคนอื่น ๆ
มันอาจจะเป็นการเลียนแบบ Fortran เนื่องจากได้รับการสรุปให้เป็นเครื่องมือระดับสูง ด้านบนของห้องสมุด Fortran เช่น Linpack และ Eispack
ฉันเชื่อว่า SNOBOL4 ทำเช่นนี้ http://berstis.com/greenbook.pdf
ต่อไปนี้เป็นตัวอย่างของคำจำกัดความและการใช้ฟังก์ชันเพื่อคำนวณแฟกทอเรียลของตัวเลข:
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) ยังส่งคืนโดยการกำหนดให้กับตัวแปรนัย SystemVerilog เพิ่มคำสั่ง "return" แต่ยังคงมีการกำหนดแบบคลาสสิก
Haskell (จากปี 1990) ทำสิ่งนี้เช่นกัน:
doubleMe x = x + x
กำหนดฟังก์ชันdoubleMe
ของพารามิเตอร์หนึ่งตัวx
และกำหนดเนื้อหาของฟังก์ชันx+x
ให้ดูที่Learn You A Haskell For Great Good
Pascal เป็นสิ่งที่ฉันใช้เป็นการส่วนตัวที่ทำมัน Common Lisp kinda-sorta-but-not-do it จริงๆในนั้นค่าที่ส่งคืนนั้นมักจะเป็นนัย (กล่าวคือทุกคำสั่งมีค่าและค่าสุดท้ายในบล็อกคือค่าส่งคืนของบล็อก) ดังนั้นคุณจึงไม่ค่อยเห็น คำสั่งการกลับมาอย่างชัดเจน แต่เมื่อคุณจำเป็นต้องคืนค่าและไม่สามารถใช้วิธีปริยายวิธีที่จะทำคือการใช้RETURN-FROM
[*](return-from function-name value)
คำสั่งเช่นดังนั้น:
[*]นอกจากนี้ยังมีRETURN
คำสั่ง แต่เป็นชวเลข(return-from nil value)
และจะไม่มีผลในการสร้างVALUE
ค่าของฟังก์ชันที่เรียกใช้งาน เป็นข้อผิดพลาดอย่างยิ่งสำหรับมือใหม่ที่มาจาก C และลูกหลาน