- Trong lập trình, cách nói “gọi hàm” có nguồn gốc tương tự với khái niệm “yêu cầu” hoặc “gọi” một cuốn sách trong thư viện
- Ở giai đoạn đầu của ngành điện toán, xu hướng chủ đạo là triệu gọi, gọi các subroutine từ thư viện
- Khi Fortran II đưa vào lệnh
CALL, cách nói “gọi hàm” nhanh chóng trở nên phổ biến
- Sau đó, các ngôn ngữ như Algol và JOVIAL cũng tiếp nhận cách dùng này và sử dụng danh từ “call”
- Ý nghĩa của “call” dần được mở rộng và cố định quanh trước, trong và sau khi chuyển điều khiển lúc runtime
Vì sao lập trình viên nói là “gọi (call)” một hàm?
- Trên StackExchange đã có câu hỏi về nguồn gốc của cách nói “gọi (call) một hàm”
- Có nhiều phép so sánh khác nhau, nhưng thực tế, từ “call” bắt nguồn từ nghĩa triệu gọi (summon) hoặc gọi đến
- Tương tự như việc “yêu cầu” một cuốn sách trong thư viện, khái niệm này bắt đầu từ việc “yêu cầu” một subroutine để sử dụng
- “call number” là ký hiệu dùng để chỉ vị trí của sách trong thư viện
Lịch sử của “call” trong thuật ngữ thư viện
- Theo OED, Melvil Dewey là người đầu tiên dùng “call number” như một thuật ngữ khoa học thư viện vào năm 1876
- “call number” là ký hiệu dùng cho vị trí của sách hoặc cho yêu cầu lấy sách
- Trong Library Journal năm 1888, các thuật ngữ như “call blank”, “call slip”, “call number” đã được dùng thường xuyên
- Theo giải thích của Joudrey & Taylor, “call number” là tên gọi xuất phát từ hành động gọi tài liệu trong các kho sách đóng
- Các hệ thống như Cutter number được đưa vào để phục vụ việc phân loại
Những cách dùng ban đầu của “call” trong khoa học máy tính
- Trong bài báo năm 1947 của John W. Mauchly, đã xuất hiện trường hợp dùng “called in” để lấy subroutine từ thư viện subroutine
- Trong ngữ cảnh này, nó mang nghĩa tham chiếu nhanh và sử dụng thông qua số hiệu đã được ghi lại
- Routine assembly của MANIAC II (1956) cũng áp dụng khái niệm gán “call number” cho từng subroutine để có thể gọi ra khi cần
- Trong ngôn ngữ assembly thực tế, hành động này được gọi là “transfer control”
- Ở giai đoạn này, trọng tâm vẫn là khái niệm gọi mã từ lúc biên dịch hoặc liên kết, hơn là “lời gọi” ở runtime
Sự xuất hiện của lệnh “CALL” trong ngôn ngữ lập trình
- Fortran II (1958) đưa vào các lệnh
CALL và RETURN
- Đây là hành động “call for” một subroutine để chuyển quyền điều khiển thực thi sang đó
- Bản thân lệnh
CALL chỉ rõ hành vi cú pháp của việc “gọi”
- Dần dần, việc “transfer control” ở runtime và hành vi “gọi” ở thời điểm liên kết/lắp ráp bắt đầu hòa lẫn một cách mơ hồ
Sự mở rộng và định hình nghĩa của “call” trong thập niên 1960
- Trong từ điển của Sarbacher (1959), “call in” được định nghĩa là việc chuyển điều khiển từ routine chính sang subroutine
- Đồng thời cũng giải thích “call number” và “call word” như định danh và mã gọi
- Trong JOVIAL (1960), các cách nói như “procedure call”, “calls” đã chính thức được dùng như danh từ
- Về sau, chúng còn được dùng với các lớp nghĩa như vị trí gọi (site), đối số (argument), tham số (parameter)
- Algol (1959~1960) cũng dùng nhiều cách diễn đạt như “procedure call”, “called procedure”, “during the call”
- Trong báo cáo Algol 60 của Peter Naur, còn xuất hiện sự phân biệt về mặt thời gian giữa “call for” và “during the call”
- Trong Burroughs Algebraic Compiler (1961), dạng động từ “to call” xuất hiện rõ ràng lần đầu tiên
- Từ Corbató và cộng sự (1963) trở đi, cách dùng hiện đại “to call a subroutine” trở nên phổ biến
Kết luận
- Lệnh
CALL X của Fortran II đã giúp cách diễn đạt “call” bám rễ vào khái niệm gọi hàm/subroutine
- Nó được gợi ý từ khái niệm thư viện trước đó (gọi bằng số hiệu), nhưng đã được mở rộng nghĩa mới trong ngôn ngữ lập trình
- Sau đó, Algol, JOVIAL và nhiều ngôn ngữ khác tiếp nhận các thuật ngữ như “call”, “call site”
- Từ khoảng năm 1961, cách nói “to call X” bắt đầu được định hình trong các tài liệu lập trình chính thức và cộng đồng
- Ngày nay, gọi hàm chỉ toàn bộ chuỗi thao tác tạm thời chuyển quyền điều khiển, nhận kết quả rồi quay lại, và “call” trở thành thuật ngữ tiêu chuẩn cho quá trình đó
1 bình luận
Ý kiến trên Hacker News
call(bắt nguồn từcall number, dùng để sắp xếp tài liệu trong thư viện vật lý) cũng đã ảnh hưởng đến sự ra đời của thuật ngữcompiler. Mỗi chương trình con được gán mộtcall word, và khái niệm tạo nên chương trình bắt nguồn từ việc lấy tài liệu ra khỏi thư viện rồi kết hợp chúng lạicall numberindextrong thuật ngữ máy tính bắt nguồn từ phần mục lục ở cuối sách. Tôi chưa từng nối nó vớiindex cardskutsua, nếu dịch ngược sang tiếng Anh thì làinvitehoặcsummon. Tức là nó mang nghĩa "gọi" như "mẹ gọi con từ ngoài sân vào", chứ không phải kiểucallnhư "Joe gọi điện cho bạn" hay "gọi màu này là gì". Chỉ muốn chia sẻ vậy thôiaufrufen, nếu dịch từng mảnh thì gần như là "gọi lên". Khi dùng với tân ngữ trực tiếp, như lúc giáo viên điểm danh học sinh ở trường, nó có nghĩa là gọi ai đó bằng tên hoặc số. Từ tương ứng với gọi điện làanrufensummonđôi khi cũng rất hợp, vì có lúc nó tạo cảm giác như đang gọi ra một nỗi kinh hoàng huyền thuật trong mã nguồn.invitethì đôi khi khiến tôi nghĩ đến việc mời quỷ dữ hoặc ma cà rồng vào nhàfunksjonskall, dịch sát nghĩa làfunction call. Nó đơn giản là nghĩa gọi một cái gì đócall inđược dùng cho việc thực thi chương trình con. Ở trang 31 có các câu như "nếu chương trình con không được gọi đúng cách thì máy sẽ dừng" và "có thể tự do gọi chương trình con trong bất kỳ chương trình nào". Trong báo cáo ban đầu về EDSAC năm 1950 cũng có chú thíchcall in auxiliary sub-routine, có thể thấy trong bài thuyết trình nàyinvokehoặcexecutethay chocall, nhưng đó là các thuật ngữ dài hơn và mang tính chung chung hơn. Tuy vậy, tôi thường nghe sinh viên CS không phải người bản ngữ dùng sai từcalltrong những ngữ cảnh như "calling a command" hay "calling a button", và điều đó hơi gây khó chịuinvokebắt nguồn từ tiếng Latin invocō, invocāre (gọi ra), nên không phải là sai mà chỉ là cách nói rút gọnreturn. Tôi từng nghe câu kiểu: "bây giờ gọi từ khóa return thì hàm sẽ kết thúc"Invokeở những chỗ như delegate hoặc reflection, trong khi debugger lại dùngCall Stackcommandcommandsalty, vàcallcũng vậy. Nó ngắn, dùng thường xuyên nên rất thuận miệng; các sắc thái nhưcall up/call in/summon/invoke(kiểu như câu thần chú) đều cho cảm giác khá khớp. Khi đó điện thoại cũng là một công nghệ mới mẻ và thú vị, nên hình ảnh gọi điện cho người khác hẳn đã được liên hệ rất dễ với việc gọi chương trình con. Những từ nhưjumpthì đã được dùng theo nghĩa khác rồi, nên tôi nghĩcallmới có thể phổ biến rộng rãisaltychẳng liên quan mấy đến nước mắt. Trong thói quen ngôn ngữ của tôi, ai đósaltykhông có nghĩa là buồn mà là đang cáu kỉnh hoặc khó chịu. Tức là ẩn dụ đến từ hình ảnh vị mặn như thứ gì đó gắt và mạnh. Nói cách khác, dù cách diễn giải khác nhau thì ẩn dụ vẫn hoạt động tốt, và điều đó cho thấycallcũng có thể lan truyền theo cách như vậylibrarythực sự bắt nguồn từ những giá tài liệu có dán nhãn ngoài đờilibraryđược gọi bằng tên nào khác. Ví dụ điển hình là phần mở rộng tệp.libcall. Hàm thường trả về giá trị nên có thể dùng ngay trong câu lệnh gán. Thứ cầncalllà subroutine (thực chất là một địa chỉ/nhãn có tên). Thực ra cũng có thể nhảy trực tiếp đến địa chỉ đó bằng GOTO rồi quay lại. Từ khóa CALL giúp luồng thực thi trông rõ ràng hơn. Giống như sếp giao Sam xử lý việc tính toán rồi lại giao Bill in báo cáo TPS, luồng công việc cứ thế tiếp diễn. Rồi cuối cùng mọi thứ đều biến thành function và subroutine thì bị gán biệt danh làspaghetti. Nhưng tôi vẫn thắc mắc vì sao lại có cả hai thuật ngữ routine (chương trình) và subroutinecallkhông chỉ cho hàm mà còn cho cả tham số. Ví dụ nhưcall by value,call by name; ở mục 4.7.5.3 có cấu trúc như "trong trường hợp call by value". Ngày nay người ta nói procedure/function/subroutine thì đượccall, còn argument/parameter thì đượcpass, nênpass by value/reference/namerõ ràng hơn. Tuy vậy, các thuật ngữ cũ nhưcall by valuevẫn còn tồn tại trong một số ngữ cảnh. Khái niệm gọi (call) argument hay parameter thì đã biến mất, nhưng những thuật ngữ legacy như vậy vẫn còn tồn tại