ค่าส่งกลับถูกกำหนดโดยการกำหนดให้กับชื่อฟังก์ชันในภาษาใด

Jan 18 2021

ในคำถาม Stack Overflowนี้รหัสเดิมทำผิดพลาดในการใช้ชื่อฟังก์ชันเป็นตัวแปรและกำหนดค่าส่งคืนให้ ผู้แสดงความคิดเห็นกล่าวว่าครั้งหนึ่งเขาเคยใช้ภาษาซึ่งเป็นวิธีที่คุณส่งคืนค่าจากฟังก์ชัน ความคิดเห็นอ่านว่า "ฉันรู้ว่าครั้งหนึ่งฉันเคยใช้ภาษาที่ต้องกำหนดค่าส่งคืนของฟังก์ชันให้กับชื่อของฟังก์ชันมันโบราณและล้าสมัยมากฉันจำไม่ได้ด้วยซ้ำว่าเป็นภาษาใด"

ฟังดูคุ้น ๆ เหมือนกัน แต่จำไม่ได้เหมือนกันว่าเป็นภาษาอะไร

มีใครมีความจำดีกว่าเราและบอกเราได้ไหมว่ามันคือภาษาอะไร?

คำตอบ

50 WillHartung Jan 18 2021 at 22:45

ปาสคาลทำแบบนี้ฉันไม่รู้จักคนอื่น ไม่รู้ว่าการฝึกฝนก้าวไปข้างหน้าด้วยภาษาเวิร์ ธ อื่น ๆ หรือไม่

50 OmarL Jan 18 2021 at 23:14

ภาษาในตระกูล Visual Basic ทำเช่นนี้ ซึ่งรวมถึง VBScript, VBA, Visual Basic และรุ่นก่อนหน้า ฉันเชื่อว่าสิ่งเหล่านี้สืบทอด "คุณลักษณะ" จาก QBASIC ตัวอย่างเช่น

Public Function AddTwo(something as Integer)
    AddTwo = something + 2
End Function
29 scruss Jan 18 2021 at 23:03

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มาตรฐาน

22 user3840170 Jan 18 2021 at 23:54

ภาษาที่เร็วที่สุดที่ฉันสามารถหาได้คือ 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 ก็มาจากเรื่องนั้นเช่นกัน)

17 Raffzahn Jan 19 2021 at 00:28

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คำสั่งในความพยายามที่จะเพิ่มการเขียนโปรแกรมขั้นตอน แต่การใช้งานเป็นเพียงการส่งคืนการดำเนินการไปยังผู้โทรเท่านั้นค่าส่งคืนจะต้องถูกตั้งค่าแยกต่างหาก

12 alephzero Jan 18 2021 at 23:02

Fortran ใช้ไวยากรณ์นี้ตั้งแต่รุ่นแรกสุดซึ่งมีฟังก์ชันเลยจนถึง Fortran 2008 และรุ่นที่ใหม่กว่า

อย่างไรก็ตาม Fortran 2008 มีตัวเลือก (สับสนมากยิ่งขึ้น?) ที่คุณสามารถประกาศชื่อตัวแปรอื่นที่ใช้เพื่อส่งคืนค่าฟังก์ชัน! ตัวอย่างเช่น

function xyz(argument) result(answer)
...
answer = 42
...
end function xyz

แทนรูปแบบเก่า

...
xyz = 42
...
9 another-dave Jan 19 2021 at 01:02

Algol 60 สำหรับหนึ่ง

นี่คือคำที่เกี่ยวข้องจากแก้ไขรายงานในขั้นตอนภาษา Algol 60

5.4.4. ค่าของตัวกำหนดฟังก์ชัน

สำหรับการประกาศโพรซีเดอร์เพื่อกำหนดค่าของตัวกำหนดฟังก์ชันจะต้องมีในส่วนของการประกาศโพรซีเดอร์ที่มีคำสั่งการกำหนดอย่างชัดเจนอย่างน้อยหนึ่งคำสั่งพร้อมตัวระบุโพรซีเดอร์ในส่วนด้านซ้าย ต้องดำเนินการอย่างน้อยหนึ่งอย่างและประเภทที่เกี่ยวข้องกับตัวระบุโพรซีเดอร์ต้องถูกประกาศผ่านรูปลักษณ์ของตัวประกาศประเภทเป็นสัญลักษณ์แรกสุดของการประกาศโพรซีเดอร์ ค่าสุดท้ายที่กำหนดจะถูกใช้เพื่อดำเนินการประเมินนิพจน์ที่ตัวกำหนดฟังก์ชันเกิดขึ้นต่อไป

การเกิดขึ้นของตัวระบุโพรซีเดอร์ใด ๆ ภายในเนื้อหาของโพรซีเดอร์นอกเหนือจากในส่วนซ้ายในคำสั่งการกำหนดหมายถึงการเปิดใช้งานโพรซีเดอร์

ประโยคสุดท้ายมีความสำคัญ - แสดงให้เห็นว่าชื่อของขั้นตอนประเภท (ฟังก์ชัน) ไม่ได้รับการปฏิบัติ 'เหมือนกับ' ตัวแปรภายในตัวกระบวนงาน (ฟังก์ชัน) แต่จะเป็นเพียงการมอบหมายงานที่มีลักษณะพิเศษเท่านั้น

ใน Algol 60, เรียกร้องให้ฟังก์ชั่นที่ใช้เวลาไม่มีข้อโต้แย้งไม่ได้ตามด้วยวงเล็บที่ว่างเปล่าจึงมากกว่าn := readn := read()

ประโยคสุดท้ายมีชื่อเสียงเช่นกันว่าเป็นประโยคที่มีขั้นตอนการเรียกซ้ำในภาษา แต่นั่นไม่ใช่สิ่งสำคัญสำหรับคำตอบนี้

6 StephenKitt Jan 18 2021 at 23:03

ภาษาเบสิกเป็นภาษาอื่นที่มีฟังก์ชันที่ภาษาถิ่นบางภาษาใช้การกำหนดชื่อฟังก์ชันเพื่อให้ค่าส่งกลับ ภาษาถิ่นแรกสุดนั้นคล้ายคลึงกับฟังก์ชันบรรทัดเดียวของ Fortran:

DEF FND(x) = x*x

แต่ภาษาถิ่นในภายหลังอนุญาตให้มีรูปแบบที่ซับซ้อนมากขึ้นเช่นเดียวกับฟังก์ชันหลายบรรทัดของ Fortran :

DEF FNPeekWord& (A&)
  FNPeekWord& = PEEK(A&) + 256& * PEEK(A& + 1)
END DEF
5 LyndonWhite Jan 19 2021 at 20:38

MATLAB / Octave ก็ทำเช่นนี้เช่นกัน

มาจากปีพ. ศ. 2527 จึงไม่เก่าเหมือนของคนอื่น ๆ

มันอาจจะเป็นการเลียนแบบ Fortran เนื่องจากได้รับการสรุปให้เป็นเครื่องมือระดับสูง ด้านบนของห้องสมุด Fortran เช่น Linpack และ Eispack

5 chasly-supportsMonica Jan 19 2021 at 21:29

ฉันเชื่อว่า 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

4 d3jones Jan 19 2021 at 07:12

Verilog (1995/2001) ยังส่งคืนโดยการกำหนดให้กับตัวแปรนัย SystemVerilog เพิ่มคำสั่ง "return" แต่ยังคงมีการกำหนดแบบคลาสสิก

1 arne Jan 21 2021 at 03:02

Haskell (จากปี 1990) ทำสิ่งนี้เช่นกัน:

doubleMe x = x + x  

กำหนดฟังก์ชันdoubleMeของพารามิเตอร์หนึ่งตัวxและกำหนดเนื้อหาของฟังก์ชันx+xให้ดูที่Learn You A Haskell For Great Good

mathrick Jan 19 2021 at 13:08

Pascal เป็นสิ่งที่ฉันใช้เป็นการส่วนตัวที่ทำมัน Common Lisp kinda-sorta-but-not-do it จริงๆในนั้นค่าที่ส่งคืนนั้นมักจะเป็นนัย (กล่าวคือทุกคำสั่งมีค่าและค่าสุดท้ายในบล็อกคือค่าส่งคืนของบล็อก) ดังนั้นคุณจึงไม่ค่อยเห็น คำสั่งการกลับมาอย่างชัดเจน แต่เมื่อคุณจำเป็นต้องคืนค่าและไม่สามารถใช้วิธีปริยายวิธีที่จะทำคือการใช้RETURN-FROM[*](return-from function-name value)คำสั่งเช่นดังนั้น:

[*]นอกจากนี้ยังมีRETURNคำสั่ง แต่เป็นชวเลข(return-from nil value)และจะไม่มีผลในการสร้างVALUEค่าของฟังก์ชันที่เรียกใช้งาน เป็นข้อผิดพลาดอย่างยิ่งสำหรับมือใหม่ที่มาจาก C และลูกหลาน