This original sense of 'call' (deriving from the 'call number' used to organize books and other materials in physical libraries) was also responsible for the coinage of 'compiler', according to Grace Hopper: 'The reason it got called a compiler [around 1952] was that each subroutine was given a "call word", because the subroutines were in a library, and when you pull stuff out of a library you compile things. It's as simple as that.'
In Excel formulas everything is a function. IF, AND, OR, NOT are all functions. It is awkward and goes against what software devs are familiar with, but there are probably more people familiar with the Excel IF function than any other forms. Here is an example taken from the docs... =IF(AND(A3>B2,A3<C2),TRUE,FALSE)
Sounds like something Prof. John Ousterhout would say:-; The place where this was literally accurate would be Tcl.
I don't know enough Smalltalk to be sure but I think to remember it has a similar approach of everything is an object and I wouldn't be surprised if they'd coerced control flow somehow into this framework.
Also Forth comes to mind, but that would probably be a stretch.
Try implementing that in most languages and you'll run into problems.
In an imperative programming language with eager evaluation, i.e. where arguments are evaluated before applying the function, implementing `if` as a function will evaluate both the "then" and "else" alternatives, which will have undesirable behavior if the alternatives can have side effects.
In a pure but still eager functional language this can work better, if it's not possible for the alternatives to have side effects. But it's still inefficient, because you're evaluating expressions whose result will be discarded, which is just wasted computation.
In a lazy functional language, you can have a viable `if` function, because it will only evaluate the argument that's needed. But even in the lazy functional language Haskell, `if` is implemented as built-in syntax, for usability reasons - if the compiler understands what `if` means as opposed to treating it as an ordinary function, it can optimize better, produce better messages, etc.
In a language with the right kind of macros, you can define `if` as a macro. Typically in that case, its arguments might be wrapped in lambdas, by the macro, to allow them to be evaluated only as needed. But Scheme and Lisp, which have the right kind of macros, don't define `if` as a macro for similar reasons to Haskell.
One language in which `if` is a function is the pure lambda calculus, but no-one writes real code in that.
The only "major" language I can think of in which `if` is actually a function (well, a couple of methods) is Smalltalk, and in that case it works because the arguments to it are code blocks, i.e. essentially lambdas.
tl;dr: `if` as a function isn't practical in most languages.
"Command" is a better term for what we call "statements" in imperative programming languages. "Statement" in this context is an unfortunate historical term; except in Prolog, these "statements" don't have a truth-value, just an effect. (And in Prolog we call them "clauses" instead.)
I'm Finnish and in in Finnish we translate "call" in function context as "kutsua", which when translated back into English becomes "invite" or "summon".
So at least in Finnish the word "call" is considered to mean what it means in a context like "a mother called her children back inside from the yard" instead of "call" as in "Joe made a call to his friend" or "what do you call this color?".
> ... but those of any complexity presumably ought to be in a library â that is, a set of magnetic tapes in which previously coded problems of permanent value are stored.
Oddly, I never thought of the term library as originating from a physical labelled and organized shelf of tapes, until now.
I don't see .lib being all that common, but it might just be what I'm used to. `.so` or `.dll` or such sure (though to be fair, the latter does include the word library.)
.lib is the traditional extension for static libraries and import libraries on Windows. Every .dll has an accompanying .lib. (Msys2 uses their own extensions, namely .a for static libraries and .dll.a for import libraries.)
Not a scientific theory, but an observation. New words propagate when they "click". They are often short, and for one reason or another enable people to form mental connections and remember what they mean. They spread rapidly between people like a virus. Sometimes they need to be explained, sometimes people get it from context, but afterward people tend to remember them and use them with others, further propagating the word.
A fairly recent example, "salty". It's short, and kinda feels like it describes what it means (salty -> tears -> upset).
It sounds like "call" is similar. It's short, so easy to say for an often used technical term, and there are a couple of ways it can "feel right": calling up, calling in, summoning, invoking (as a magic spell). People hear it, it fits, and the term spreads. I doubt there were be many competing terms, because terms like "jump" would have been in use to refer to existing concepts. Also keep in mind that telephones were hot, magical technology that would have become widespread around this same time period. The idea of being able to call up someone would be at the forefront of people's brains, so contemporary programmers would likely have easily formed a mental connection/analogy between calling people and calling subroutines.
I always thought it was just a metaphor for suddenly leaving whatever you were doing at the time. Youâre doing something else, and then you jump on a call. You donât mosey on over and show up on the call fifteen minutes later.
I love this sort of cs history. Iâm also curiousâwhy do we âthrowâ an error or âraiseâ an exception? Why did the for loop use âforâ instead of, say, âloopâ?
It's been ages, but I think an earlier edition of Stroustrup's The C++ Programming Language explains that he specifically chose "throw" and "catch" because more obvious choices like "signal" were already taken by established C programs and choosing "unusual" words (like "throw" and "catch") reduced chance of collision. (C interoperability was a pretty big selling point in the early days of C++.)
The design of exception handling in C++ was inspired by ML, which used 'raise', and C++ might itself have used that word, were it not already the name of a function in the C standard library (as was 'signal'). The words 'throw' and 'catch' were introduced by Maclisp, which is how Stroustrup came to know of them. As he told Guy Steele at the second ACM History of Programming Languages (HOPL) conference in 1993, 'I also think I knew whatever names had been used in just about any language with exceptions, and "throw" and "catch" just were the ones I liked best.'
I think âraiseâ comes from the fact that the exception propagates âupwardâ through the call stack, delegating the handling of it to the next level âup.â âThrowâ may have to do with the idea of not knowing what to do/how to handle an error case, so you just throw it away (or throw your hands up in frustration xD). Totally just guessing
I suspect it comes from raising flags/signals (literally as one might run a flag up a flag pole?) to indicates CPU conditions, and then that terminology getting propagated from hw to sw.
That's a great question. The first language I learned was python, and "for i in range(10)" makes a lot of sense to me. But "for (int i = 0; i < 10; i++)" must have come first, and in that case "for" is a less obvious choice.
It's interesting to think of "calling" as "summoning" functions. We could also reasonably say "instantiating", "evaluating", "computing", "running", "performing" (as in COBOL), or simply "doing".
In Mauchly's "Preparation of Problems for EDVAC-Type Machines", quoted in part in the blog post, he writes:
> The total number of operations for which instructions must be provided will
usually be exceedingly large, so that the instruction sequence would be far in excess of the
internal memory capacity. However, such an instruction sequence is never a random sequence,
and can usually be synthesized from subsequences which frequently recur.
> By providing the necessary subsequences, which may be utilized as often as desired, together
with a master sequence directing the use of these subsequences, compact and easily set up
instructions for very complex problems can be achieved.
The verbs he uses here for subroutine calls are "utilize" and "direct". Later in the paper he uses the term "subroutine" rather than "subsequence", and does say "called for" but not in reference to the subroutine invocation operation in the machine:
> For these,
magnetic tapes containing the series of orders required for the operation can be prepared once
and be made available for use when called for in a particular problem. In order that such
subroutines, as they can well be called, be truly general, the machine must be endowed with
the ability to modify instructions, such as placing specific quantities into general subroutines.
Thus is created a new set of operations which might be said to form a calculus of instructions.
Of course nowadays we do not pass arguments to subroutines by modifying their code, but index registers had not yet been invented, so every memory address referenced had to be contained in the instructions that referenced it. (This was considered one of the great benefits of keeping the program in the data memory!)
A little lower down he says "initiate subroutines" and "transferring control to a subroutine", and talks about linking in subroutines from a "library", as quoted in the post.
He never calls subroutines "functions"; I'm not sure where that usage comes from, but certainly by BASIC and LISP there were "functions" that were at least implemented by subroutines. He does talk about mathematical functions being computed by subroutines, including things like matrix multiplication:
> If the subroutine is merely to calculate a
function for a single argument, (...)
"He never calls subroutines "functions"; I'm not sure where that usage comes from, but certainly by BASIC and LISP there were "functions" that were at least implemented by subroutines."
I think the early BASIC's used the subroutine nomenclature for GOSUB, where there was no parameter passing or anything, just a jump that automatically remembered the place to return.
Functions in BASIC, as I remember it, were something quite different. I think they were merely named abbreviations for arithmetic expressions and simple one line artithmetic expressions only. They were more similar to very primitive and heavily restricted macros than to subroutines or functions.
The answer is in the article. You "call" functions because they are stored in libraries, like books, and like books in libraries, when you want them, you identify which one you want by specifying its "call number".
I seem to remember people used to say "call it up" when asking an operator to perform a function on a computer when the result was displayed in front of the user.
I'd like to point at CALL, a CPU instruction, and its origins. I'm not familiar with this, but it could reveal more than programming languages. The instruction is present at least since first intel microprocessors and microcontrollers were designed.
> Dennis Ritchie encouraged modularity by telling all and sundry that function calls were really, really cheap in C. Everybody started writing small functions and modularizing. Years later we found out that function calls were still expensive on the PDP-11, and VAX code was often spending 50% of its time in the CALLS instruction. Dennis had lied to us! But it was too late; we were all hooked...
The first Intel microcontrollers were the 8008 and the 4004, designed in 01971. This is 13 years after this post documents the "CALL X" statement of FORTRAN II in 01958, shortly after which (he documents) the terminology became ubiquitous. (FORTRAN I didn't have subroutines.)
> A procedure statement serves to initiate (call for) the execution of a procedure, which is a closed and self-contained process with a fixed ordered set of input and output parameters, permanently defined by a procedure declaration. (cf. procedure declaration.)
Note that this does go to extra pains to include the term "call for", but does not use the phraseology "call a procedure". Rather, it calls for not the procedure itself, but the execution of the procedure.
However, it also uses the term "procedure call" to describe either the initiation or the execution of the procedure:
> The procedure declaration defining the called procedure contains, in its heading, a string of symbols identical in form to the procedure statement, and the formal parameters occupying input and output parameter positions there give complete information concerning the admissibility of parameters used in any procedure call, (...)
Algol 58 has a different structure for defining functions rather than procedures, but those too are invoked by a "function call"âbut not by "calling the function".
I'm not sure when the first assembly language with a "call" instruction appeared, but it might even be earlier than 01958. The Burroughs 5000 seems like it would be a promising thing to look at. But certainly many assembly languages from the time didn't; even MIX used a STJ instruction to set the return address in the return instruction in the called subroutine and then just jumped to its entry point, and the PDP-10 used PUSHJ IIRC. The 360 used BALR, branch and link register, much like RISC-V's JALR today.
This original sense of 'call' (deriving from the 'call number' used to organize books and other materials in physical libraries) was also responsible for the coinage of 'compiler', according to Grace Hopper: 'The reason it got called a compiler [around 1952] was that each subroutine was given a "call word", because the subroutines were in a library, and when you pull stuff out of a library you compile things. It's as simple as that.'
Somewhat less frequently, I also hear "invoke" or "execute", which is more verbose but also more generic.
Incidentally, I find strange misuses of "call" ("calling a command", "calling a button") one of the more grating phrases used by ESL CS students.
Invoke comes from Latin invocĹ, invocÄre, meaning âto call uponâ. I wouldnât view it as a misuse, but rather a shortening.
> Invoke comes from Latin invocĹ, invocÄre, meaning âto call uponâ.
(In the way you'd call upon a skill, not in the way you'd call upon a neighbor.)
> strange misuses of "call"
My favourite (least favourite?) is using âcallâ with âreturnâ. On more than one occasion Iâve heard:
âWhen we call the return keyword, the function ends.â
I remember someone in university talking about the if function (which ostensibly takes one boolean argument).
In Excel formulas everything is a function. IF, AND, OR, NOT are all functions. It is awkward and goes against what software devs are familiar with, but there are probably more people familiar with the Excel IF function than any other forms. Here is an example taken from the docs... =IF(AND(A3>B2,A3<C2),TRUE,FALSE)
Excel cell formulas are the most widely used functional programming language in the world.
Sounds like something Prof. John Ousterhout would say:-; The place where this was literally accurate would be Tcl.
I don't know enough Smalltalk to be sure but I think to remember it has a similar approach of everything is an object and I wouldn't be surprised if they'd coerced control flow somehow into this framework.
Also Forth comes to mind, but that would probably be a stretch.
Try implementing that in most languages and you'll run into problems.
In an imperative programming language with eager evaluation, i.e. where arguments are evaluated before applying the function, implementing `if` as a function will evaluate both the "then" and "else" alternatives, which will have undesirable behavior if the alternatives can have side effects.
In a pure but still eager functional language this can work better, if it's not possible for the alternatives to have side effects. But it's still inefficient, because you're evaluating expressions whose result will be discarded, which is just wasted computation.
In a lazy functional language, you can have a viable `if` function, because it will only evaluate the argument that's needed. But even in the lazy functional language Haskell, `if` is implemented as built-in syntax, for usability reasons - if the compiler understands what `if` means as opposed to treating it as an ordinary function, it can optimize better, produce better messages, etc.
In a language with the right kind of macros, you can define `if` as a macro. Typically in that case, its arguments might be wrapped in lambdas, by the macro, to allow them to be evaluated only as needed. But Scheme and Lisp, which have the right kind of macros, don't define `if` as a macro for similar reasons to Haskell.
One language in which `if` is a function is the pure lambda calculus, but no-one writes real code in that.
The only "major" language I can think of in which `if` is actually a function (well, a couple of methods) is Smalltalk, and in that case it works because the arguments to it are code blocks, i.e. essentially lambdas.
tl;dr: `if` as a function isn't practical in most languages.
There are languages in which `if` is a function.
In in Tcl, `if` is called a "command".
Also in Smalltalk and sclang (Supercollider language)
Eh, "return" is just a very restricted continuation with special syntax⌠it's a stretch to say you "call" it, but not unjustified.
I've heard that too --- the voice in my head automatically read it in the customary thick Indian accent.
C# seems to like to use "Invoke" for things like delegates or reflected methods. Then it proceeds to use "Call Stack" in the debugger view.
I actually see the converse often with novices often, referring to statements (or even entire function decls) as "commands".
"Command" is a better term for what we call "statements" in imperative programming languages. "Statement" in this context is an unfortunate historical term; except in Prolog, these "statements" don't have a truth-value, just an effect. (And in Prolog we call them "clauses" instead.)
I'm Finnish and in in Finnish we translate "call" in function context as "kutsua", which when translated back into English becomes "invite" or "summon".
So at least in Finnish the word "call" is considered to mean what it means in a context like "a mother called her children back inside from the yard" instead of "call" as in "Joe made a call to his friend" or "what do you call this color?".
Just felt like sharing.
> ... but those of any complexity presumably ought to be in a library â that is, a set of magnetic tapes in which previously coded problems of permanent value are stored.
Oddly, I never thought of the term library as originating from a physical labelled and organized shelf of tapes, until now.
I've never heard of a library being called anything else - look at the common file extension .lib, for example.
I don't see .lib being all that common, but it might just be what I'm used to. `.so` or `.dll` or such sure (though to be fair, the latter does include the word library.)
.lib is the traditional extension for static libraries and import libraries on Windows. Every .dll has an accompanying .lib. (Msys2 uses their own extensions, namely .a for static libraries and .dll.a for import libraries.)
Not a scientific theory, but an observation. New words propagate when they "click". They are often short, and for one reason or another enable people to form mental connections and remember what they mean. They spread rapidly between people like a virus. Sometimes they need to be explained, sometimes people get it from context, but afterward people tend to remember them and use them with others, further propagating the word.
A fairly recent example, "salty". It's short, and kinda feels like it describes what it means (salty -> tears -> upset).
It sounds like "call" is similar. It's short, so easy to say for an often used technical term, and there are a couple of ways it can "feel right": calling up, calling in, summoning, invoking (as a magic spell). People hear it, it fits, and the term spreads. I doubt there were be many competing terms, because terms like "jump" would have been in use to refer to existing concepts. Also keep in mind that telephones were hot, magical technology that would have become widespread around this same time period. The idea of being able to call up someone would be at the forefront of people's brains, so contemporary programmers would likely have easily formed a mental connection/analogy between calling people and calling subroutines.
There is also the phrase in music, "call and response" - even referencing a return value.
Off topic somewhat but where the hell did the verb 'jump' come from for video calls? I'm always being asked to jump on a call
I thought it's like hopping onto a bus. Then it doesn't take a lot for "hop" to change into "jump".
It seems like it has the connotation of being spontaneous and not requiring preparation.
I assume it's because you're doing something you'd rather not do to benefit somebody else, much like you'd jump on a grenade :p
I'll henceforth take this as the canonical explanation :)
You would jump on a call before video was involved. Not even necessarily a conference call either, you could jump on the horn etc.
It just means to start doing something, no great mystery.
I always thought it was just a metaphor for suddenly leaving whatever you were doing at the time. Youâre doing something else, and then you jump on a call. You donât mosey on over and show up on the call fifteen minutes later.
That's just a standard meaning of the word jump. You're jumping from whatever you were doing to a video call.
This was a result of Zoom's acquisition of the band House of Pain.
Thought it was Kris Kross.
When in reality it was Van Halen.
Maybe it's a hint that the operation is irreversible! :-)
Another interesting one is in games when an effect is said to "proc", which I guess is from a procedure getting called.
Basically, yeah. It actually has its origin in MUDs, from 'spec_proc', short for special procedure.
I love this sort of cs history. Iâm also curiousâwhy do we âthrowâ an error or âraiseâ an exception? Why did the for loop use âforâ instead of, say, âloopâ?
I'm guessing "throw" came about after someone decided to "catch" errors.
As for "raise", maybe exceptions should've been called objections.
It's been ages, but I think an earlier edition of Stroustrup's The C++ Programming Language explains that he specifically chose "throw" and "catch" because more obvious choices like "signal" were already taken by established C programs and choosing "unusual" words (like "throw" and "catch") reduced chance of collision. (C interoperability was a pretty big selling point in the early days of C++.)
The design of exception handling in C++ was inspired by ML, which used 'raise', and C++ might itself have used that word, were it not already the name of a function in the C standard library (as was 'signal'). The words 'throw' and 'catch' were introduced by Maclisp, which is how Stroustrup came to know of them. As he told Guy Steele at the second ACM History of Programming Languages (HOPL) conference in 1993, 'I also think I knew whatever names had been used in just about any language with exceptions, and "throw" and "catch" just were the ones I liked best.'
You throw something catchable and if you fail to catch it itâll break. Unless itâs a steel ball.
You raise flags or issues, which are good descriptions of an exception.
I think âraiseâ comes from the fact that the exception propagates âupwardâ through the call stack, delegating the handling of it to the next level âup.â âThrowâ may have to do with the idea of not knowing what to do/how to handle an error case, so you just throw it away (or throw your hands up in frustration xD). Totally just guessing
I suspect it comes from raising flags/signals (literally as one might run a flag up a flag pole?) to indicates CPU conditions, and then that terminology getting propagated from hw to sw.
Sounds plausuble. Some of the earliest exception handling systems did not have any semantic difference between CPU exceptions and software exceptions.
I would have thought it came from the concept of 'raising an issue' or even 'raising a stink'.
That's a great question. The first language I learned was python, and "for i in range(10)" makes a lot of sense to me. But "for (int i = 0; i < 10; i++)" must have come first, and in that case "for" is a less obvious choice.
BASIC had the FOR-NEXT loop back in 1964.
10 FOR N = 1 TO 10
20 PRINT " ";
30 NEXT N
C language would first release in 1972, that had the three-part `for` with assignment, condition, and increment parts.
This reminds me of a little bit of trivia. In very old versions of BASIC, "FORD=STOP" would be parsed as "FOR D = S TO P".
I found that amusing circa 1975.
In Fortran, it is a do-loop :)
Fortran has grown a lot over time. If somebody said it donât have a do loop in 196X, I wouldnât be too surprised.
Really itâs just syntactic sugar, just use a goto.
The entire point of Fortran was being an effective optimizing compiler for DO loops.
FOR comes from ALGOL in which as far as I know is was spelled:
Algol 58 had "for i:=0(1)9". C's for loop is a more general variant.
"For" for loop statements fits with math jargon: "for every integer i in the set [1:20], ..."
âforâ is short for âfor eachâ, presumably. `for i in 1..=10` is short for âfor each integer i in the range 1 to 10â.
It's interesting to think of "calling" as "summoning" functions. We could also reasonably say "instantiating", "evaluating", "computing", "running", "performing" (as in COBOL), or simply "doing".
In Mauchly's "Preparation of Problems for EDVAC-Type Machines", quoted in part in the blog post, he writes:
> The total number of operations for which instructions must be provided will usually be exceedingly large, so that the instruction sequence would be far in excess of the internal memory capacity. However, such an instruction sequence is never a random sequence, and can usually be synthesized from subsequences which frequently recur.
> By providing the necessary subsequences, which may be utilized as often as desired, together with a master sequence directing the use of these subsequences, compact and easily set up instructions for very complex problems can be achieved.
The verbs he uses here for subroutine calls are "utilize" and "direct". Later in the paper he uses the term "subroutine" rather than "subsequence", and does say "called for" but not in reference to the subroutine invocation operation in the machine:
> For these, magnetic tapes containing the series of orders required for the operation can be prepared once and be made available for use when called for in a particular problem. In order that such subroutines, as they can well be called, be truly general, the machine must be endowed with the ability to modify instructions, such as placing specific quantities into general subroutines. Thus is created a new set of operations which might be said to form a calculus of instructions.
Of course nowadays we do not pass arguments to subroutines by modifying their code, but index registers had not yet been invented, so every memory address referenced had to be contained in the instructions that referenced it. (This was considered one of the great benefits of keeping the program in the data memory!)
A little lower down he says "initiate subroutines" and "transferring control to a subroutine", and talks about linking in subroutines from a "library", as quoted in the post.
He never calls subroutines "functions"; I'm not sure where that usage comes from, but certainly by BASIC and LISP there were "functions" that were at least implemented by subroutines. He does talk about mathematical functions being computed by subroutines, including things like matrix multiplication:
> If the subroutine is merely to calculate a function for a single argument, (...)
"He never calls subroutines "functions"; I'm not sure where that usage comes from, but certainly by BASIC and LISP there were "functions" that were at least implemented by subroutines."
I think the early BASIC's used the subroutine nomenclature for GOSUB, where there was no parameter passing or anything, just a jump that automatically remembered the place to return.
Functions in BASIC, as I remember it, were something quite different. I think they were merely named abbreviations for arithmetic expressions and simple one line artithmetic expressions only. They were more similar to very primitive and heavily restricted macros than to subroutines or functions.
Right, that's what Algol-58 functions were, too. I think FORTRAN also has a construct like this, but I forget.
Because, obviously, we stand out in a field of the code segment and shout the address we which to jump to or push onto the stack. ;)
Also interesting to contrast this to invocation or application (e.g. to invoke or apply). I'm sure there are fair few 'functional dialects' out there!
You âcall uponâ the function to perform a task, or return a value as the case may be. Just as you may call upon a servant or whatever.
The answer is in the article. You "call" functions because they are stored in libraries, like books, and like books in libraries, when you want them, you identify which one you want by specifying its "call number".
I seem to remember people used to say "call it up" when asking an operator to perform a function on a computer when the result was displayed in front of the user.
Also exists: âactivateâ from activation record
I'd like to point at CALL, a CPU instruction, and its origins. I'm not familiar with this, but it could reveal more than programming languages. The instruction is present at least since first intel microprocessors and microcontrollers were designed.
I kept scrolling expecting to see this story:
> Dennis Ritchie encouraged modularity by telling all and sundry that function calls were really, really cheap in C. Everybody started writing small functions and modularizing. Years later we found out that function calls were still expensive on the PDP-11, and VAX code was often spending 50% of its time in the CALLS instruction. Dennis had lied to us! But it was too late; we were all hooked...
https://www.catb.org/~esr/writings/taoup/html/modularitychap...
The first Intel microcontrollers were the 8008 and the 4004, designed in 01971. This is 13 years after this post documents the "CALL X" statement of FORTRAN II in 01958, shortly after which (he documents) the terminology became ubiquitous. (FORTRAN I didn't have subroutines.)
In the Algol 58 report https://www.softwarepreservation.org/projects/ALGOL/report/A... we have "procedures" and "functions" as types of subroutines. About invoking procedures, it says:
> 9. Procedure statements
> A procedure statement serves to initiate (call for) the execution of a procedure, which is a closed and self-contained process with a fixed ordered set of input and output parameters, permanently defined by a procedure declaration. (cf. procedure declaration.)
Note that this does go to extra pains to include the term "call for", but does not use the phraseology "call a procedure". Rather, it calls for not the procedure itself, but the execution of the procedure.
However, it also uses the term "procedure call" to describe either the initiation or the execution of the procedure:
> The procedure declaration defining the called procedure contains, in its heading, a string of symbols identical in form to the procedure statement, and the formal parameters occupying input and output parameter positions there give complete information concerning the admissibility of parameters used in any procedure call, (...)
Algol 58 has a different structure for defining functions rather than procedures, but those too are invoked by a "function call"âbut not by "calling the function".
I'm not sure when the first assembly language with a "call" instruction appeared, but it might even be earlier than 01958. The Burroughs 5000 seems like it would be a promising thing to look at. But certainly many assembly languages from the time didn't; even MIX used a STJ instruction to set the return address in the return instruction in the called subroutine and then just jumped to its entry point, and the PDP-10 used PUSHJ IIRC. The 360 used BALR, branch and link register, much like RISC-V's JALR today.