31

In this Stack Overflow question the original code made the mistake of using the function name as a variable, and assigned the return value to it. A commenter mentioned that he once used a language where this was the way you returned the value from functions. The comment reads "I know I once used a language where the return value of a function needed to be assigned to the name of the function. It's so ancient and obsolete I can't even remember which language it was."

That sounds familiar to me as well, but I also can't remember what language it was.

Does anyone have better memory than us and can tell us which language it is?

6
  • 4
    There are (or were) many such languages. Are we being asked to identify the single language that the 'commenter' had in mind? ;-) Jan 18, 2021 at 18:25
  • 2
    Obviously when I wrote the question I thought it was just an obscure language. The answers show that it was actually pretty common among mainstream languages in the 60's and 70's.
    – Barmar
    Jan 18, 2021 at 18:27
  • 1
    @another-dave I too was unaware it was such a common feature. I'm pretty sure it was Fortran that I was thinking of, but I'm surprised to find Pascal mentioned too. That was my go-to language for many years, and you'd think I'd remember a detail like that. Jan 18, 2021 at 19:02
  • @MarkRansom I programmed in BASIC all through high school, but I barely remember it now. But it was 40 years ago and I've programmed in close to a dozen languages since then, so I hope I'm excused.
    – Barmar
    Jan 18, 2021 at 23:29
  • 2
    A cheeky answer could be Haskell (and probably a number of other functional languages) but those are not very retro.
    – Peter
    Jan 19, 2021 at 8:47

13 Answers 13

55

Pascal does this, I don't know of others. Don't know if the practice move forward with other Wirth languages.

12
  • 10
    I had to look up some old Pascal code I'd written to be sure. Not only is this true, but I knew it back in the day. Jan 18, 2021 at 19:12
  • 3
    Modula-2 and Oberon (Wirth's successors to Pascal) do not use the name-assignment form, and instead introduce a RETURN statement as is common with other modern languages. Jan 18, 2021 at 21:51
  • 7
    Delphi still supports this. In fact, new code is produced today using this feature (but it is more common to use the Result variable instead of the function name variable). Jan 19, 2021 at 10:45
  • 2
    It seems I don't know Pascal anymore - how does this cope with recursion? Does the compiler tell "assign to self" from "call to self"? Jan 19, 2021 at 16:32
  • 10
    @mgarciaisaia That name is only magic on the left side of the := operator, AFAIK.
    – Ingix
    Jan 19, 2021 at 18:50
53

The languages in the Visual Basic family do exactly this. This includes VBScript, VBA, Visual Basic and earlier. I believe these inherit the "feature" from QBASIC. For example

Public Function AddTwo(something as Integer)
    AddTwo = something + 2
End Function
6
  • 7
    This is true for the current VB.NET, for Visual Basic for Applications (i.e. the automation language in Microsoft Office apps), and for “classic” Visual Basic (e.g. VB6). It is also true for VB’s predecessor, QuickBasic (an MSDOS product). Notice that some of these languages are still in use and actively supported, so it’s not a syntax just used by “retro” languages. Jan 18, 2021 at 17:22
  • 1
    @EuroMicelli probably every language ever used is "still in use" somewhere. Basic was the first language I learned but I haven't touched it since, so for me it's very much retro. Jan 18, 2021 at 19:10
  • 16
    @MarkRansom, I don’t disagree, but we need to draw a line somewhere, or this very site becomes meaningless. We call QuickBasic “retro” (unsupported, hard to obtain, waning documentation), VB.NET not-retro (fully supported by currently shipping tools by vendor), and VB6 is (sadly) somewhere near the edge. Jan 18, 2021 at 19:24
  • 1
    If we take this as a history question, I don’t think it matters that much whether the languages count as ‘retro’. Jan 19, 2021 at 13:09
  • Also classic ASP and the VB version of ASP.Net
    – JeremyP
    Jan 20, 2021 at 8:46
31

Fortran, for sure:

      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

(from Clive G. Page's Professional Programmer's Guide to Fortran77).

It's also defined that way in the Fortran ANSI X 3.9 1966 Fortran 66 standard.

3
  • 2
    "Computes the area of a triangle from lengths of sides." What? It turns out this uses Heron's formula.
    – Graham Nye
    Jan 19, 2021 at 1:05
  • 4
    @GrahamNye but the comment isn't wrong.
    – Ruslan
    Jan 19, 2021 at 9:00
  • @Ruslan Indeed not though I didn't claim it was. I was just adding a link to Heron's formula for the benefit of anyone else who can only recall the more common ½ base x height formula.
    – Graham Nye
    Jan 19, 2021 at 14:44
23

The earliest such languages I can find are FORTRAN II and ALGOL 58, both published in the same year 1958; though the original FORTRAN (1956) can arguably also be included.

For FORTRAN, the first page of the manual chapter covering functions contains this example (p. 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 also includes another function syntax (p. 10), the single-line function definition, inherited from its prececessor:

FIRSTF(X) = A*X + B

It’s not hard to see how the former syntax is a natural extension of the latter, in turn coming from mathematical usage.

ALGOL 58, similarly to FORTRAN, defines both single-line ‘functions’:

A function declaration declares a given expression to be a function of certain of its variables. Thereby, the declaration gives (for certain simple functions) the computing rule for assigning values to the function (cf. functions) whenever this function appears in an expression.

Form: Δ ~ In (I, I, ~, I) := E where the I are identifiers and E is an expression which, among its constituents, may contain simple variables named by identifiers appearing in the parentheses.

and ‘procedures’, equivalent to a today’s definition of function (in imperative/procedural programming languages, at least). The return value is indicated as follows (p. 19):

For each single output procedure I(Pi) listed in the heading, a value must be assigned within the procedure by an assignment statement “I := E” where I is the identifier naming that procedure.

These syntaxes were later taken up by some dialects of BASIC (in the form of DEF FN and later FUNCTION) and ALGOL’s descendant Pascal: in Borland’s Pascal compilers, assigning to the function name was the only supported syntax before the introduction of the Result variable in Delphi 1.0.

It is probably Pascal that the mentioned commenter remembered; some universities still teach programming in it, and usually stick to the original, standard variety, instead of modern extended dialects like Object Pascal. (This isn’t really part of the question, but I’d assume the StackOverflow asker’s misunderstanding came from that as well.)

20

TL;DR:

I'd say, most likely it is Pascal you remember, as it was rather popular in the early 80s, used in University courses all thru the 80s way into the 90s and still had some fellowship there after, most notably Delphi.


Some History

The basic idea is that the function name is not only already reserved, so no need to come up with anything different, and using it is a clear statement that this is the result. It also simplifies compiler design, as a dedicated data item can be allocated within the calling convention.

There are essentially two lines of heritage, FORTRAN and ALGOL.

For both some of their descendants kept it, like

  • some BASIC variants from FORTRAN and
  • Pascal and Modula from ALGOL.

Others dropped it, like the ALGOL follow up

  • BCPL, which introduced the return() syntax,

which is quite common today as C took it from BCPL.

Language ideas are like genes jumping between hosts. For example Ada, in many ways an ALGOL/Pascal grandchild, also turned to using a return element.

Granddaddy FORTRAN has, over the years, varied the way it returns function results.

  • Originally the result of a function was assigned to the identifier of the function
  • with FORTRAN 90 the explicit definition of a return name in the function head was introduced.

While this is essentially just syntactical sugar, it features a change in style. The reasoning applied was that with recursion constructions like Foo = Foo(x-1) would look strange. But I guess that is up to interpretation.

Interestingly here as well is that FORTRAN II of 1958 did introduce a RETURN statement in its strive to add procedural programming, but it's usage was simply to return execution to a caller, the return value had to be set separate.

12
  • 2
    Aside from looking strange, a bigger confusion in Fortran is that you (1) can pass a function name as a parameter to another function and (2) with the original syntax you could use the return value within a function like any other variable. So in a function with no parameters, like FUNCTION FOO .. CALL BAR(FOO) ... END FUNCTION FOO, what is the parameter to BAR - is it a function that will be called from within BAR, or the value returned from FOO? Of course this was not a problem until the Fortran standard (as compared with non-standard extensions) supported recursion.
    – alephzero
    Jan 18, 2021 at 19:29
  • 1
    Another language which inherited the function-name assignment form from ALGOL is Simula.
    – gidds
    Jan 19, 2021 at 0:41
  • The issue with function name assignment is what happens after that statement. Does it leave the function, or does it continue. What happens on multiple assignments, etc. with return it is obvious. Jan 19, 2021 at 8:22
  • 2
    @PatrickSchlüter There is no reason why the function should exit on that assignment. It is just a variabe. In many functions you assign to it repeatedly. Functions only exit when reaching END or RETURN. Jan 19, 2021 at 9:59
  • 1
    Slightly inaccurate about BCPL. It had a RETURN statement that returned from a procedure. If it appeared in a function, it just returned 0. To return a value, it had syntax like Algol-60's one-line function such as LET f(x) = x + 1 or there was also VALOF { ... ; RESULTIS x } Aug 16, 2022 at 10:17
14

Fortran has used this syntax, from the earliest version which had functions at all right up to Fortran 2008 and beyond.

However Fortran 2008 has an (even more confusing?) option where you can declare a different variable name that is used to return a function value! For example

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

instead of the old style

...
xyz = 42
...
3
  • 1
    The change was, IIRC, already introduced with Fortran 90. 2008 only changed some terms used around functions (again IIRC).
    – Raffzahn
    Jan 18, 2021 at 17:30
  • MATLAB’s function return mechanism is kinda similar (mathworks.com/help/matlab/ref/function.html)—is this where it came from, I wonder? Jan 19, 2021 at 2:23
  • 1
    The new style is the preferred approach as it explicitly declares the output (result) of the function. In Fortran, the function result can only be a single object or an array of objects of the same type. If a tuple (by which I mean, a collection of multiple separate objects) has to be returned, then subroutine (the equivalent of void in C) is the solution. As such, the new function syntax absolutely makes sense. Fortran functions are meant to resemble the mathematical functions.
    – Scientist
    Jan 19, 2021 at 17:34
10

Algol 60 for one.

Here's the relevant words from the Revised Report on the Algorithmic Language Algol 60.

5.4.4. Values of function designators.

For a procedure declaration to define the value of a function designator there must, within the procedure declaration body, occur one or more explicit assignment statements with the procedure identifier in a left part; at least one of these must be executed, and the type associated with the procedure identifier must be declared through the appearance of a type declarator as the very first symbol of the procedure declaration. The last value so assigned is used to continue the evaluation of the expression in which the function designator occurs.

Any occurrence of the procedure identifier within the body of the procedure other than in a left part in an assignment statement denotes activation of the procedure.

The last sentence is significant -- it shows that the name of the type procedure (function) is not treated 'just like' a variable within the procedure (function) body; rather, it is only assignment that is special-cased.

In Algol 60, a call to a function that takes no arguments is not followed by empty parentheses: thus n := read rather than n := read().

The last sentence is also famous as being the sentence that got recursive procedures into the language. But that's not germane to this answer.

5
  • It was already in ALGOL 58, as I mentioned in my answer. (Also, better to use > for quoting instead of indentation.) Jan 18, 2021 at 18:04
  • 2
    Re quoting - was already fixing it (clicked on wrong button before!). Re Algol 58 - I specifically wanted to add Algol 60 (the question has 'list' tendencies) Jan 18, 2021 at 18:08
  • It does, which is rather unfortunate; the StackExchange model presupposes that answers compete rather than complement one another. But even then, does it really make sense to list every single revision of what is essentially the same language? I think it’s enough to mention Pascal once, not separately Turbo Pascal 1.0, Turbo Pascal 2.0, etc. Jan 18, 2021 at 18:20
  • 1
    In my opinion they are not close to being the same language. An Algol 60 compiler cannot compile Algol 58. (And then there's Algol 68, which no-one thinks is the same language...) Jan 18, 2021 at 18:23
  • Fair enough then; I’m not that well-versed in ALGOL. (In fact, I only knew that ALGOL had this feature because I remember reading that the last sentence you quoted from the report was subject to some controversy.) Jan 18, 2021 at 18:30
6

BASIC is another language with functions where some dialects used assignment to the function name to provide the return value. The earliest dialects were similar to Fortran single-line functions:

DEF FND(x) = x*x

But later dialects allowed more complex variants, similar to Fortran multi-line functions:

DEF FNPeekWord& (A&)
  FNPeekWord& = PEEK(A&) + 256& * PEEK(A& + 1)
END DEF
6

MATLAB / Octave also does this.

It is from 1984; so not as old as some of the others.

It was probably imitating Fortran, since it was orginally concieved as a high-level tool. On top of the Fortran libraries like Linpack and Eispack.

5

I believe that SNOBOL4 did this. http://berstis.com/greenbook.pdf

The following is an example of the definition and use of a function to compute factorials of numbers:

   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

3
  • 2
    Those lower-case comments don't look very retro :-) Jan 20, 2021 at 23:18
  • 1
    @another-dave SNOBOL is cutting edge development of the early 70s, you know, the time when all these hipsters already had brand new 7 bit teletypes.
    – Raffzahn
    Jan 21, 2021 at 3:26
  • Oh, I know. Tell that to the kids of today and their silly "regular expressions" built out of flimsy ASCII characters. Actually, I used SPITBOL on the DEC-10 where we had lower case, and on the ICL-1900 where (mostly) we did not. But still, I think you won't find lower case in the green book. Jan 21, 2021 at 3:31
4

Verilog (1995/2001) also returns by assignment to implicit variable. SystemVerilog added the "return" statement but the classic assignment is still available.

1

Pascal is one that I personally used that does it. Common Lisp kinda-sorta-but-not-really does it, in that return values are almost always implicit (ie. every statement has a value, and the last value in a block is the block's return value), so you very rarely see an explicit return statement, but when you need to return a value and can't use the implicit way, the way to do it is by using the RETURN-FROM[*] statement, like so: (return-from function-name value).

[*]There's also a RETURN statement, but it's a shorthand for (return-from nil value), and will not have the effect of making VALUE the value of the function in which it was executed. It's a great pitfall for newbies coming from C and its descendants.

2
  • 2
    I wouldn't consider Common Lisp to be like this. You're not using the function name as a variable, the purpose of RETURN-FROM is to deal with nested blocks. The name in RETURN-FROM doesn't even have to be a function name, it's for any named block.
    – Barmar
    Jan 19, 2021 at 6:22
  • 3
    @Barmar: you're right of course, which is why I said it was only kinda-sorta-but-not-really an example. I meant it more as a curiosity than a strict example of what OP was asking about. As for the name being any block, I didn't really want to overly complicate the answer with technical explanations that don't make much sense if you're not familiar with CL concepts, especially since it's not really an example to begin with.
    – mathrick
    Jan 19, 2021 at 6:29
1

Haskell (from 1990) does this as well:

doubleMe x = x + x  

defines a function doubleMe of one parameter x and assigns the function body x+x to it, see the great Learn You A Haskell For Great Good

3
  • Different case than asked for. It assigns the return value to a paramer, not to the function (name)
    – Raffzahn
    Jan 20, 2021 at 22:03
  • 3
    I doubt a Haskell function definition should be considered an "assignment".
    – das-g
    Jan 21, 2021 at 1:58
  • If this counts, then so does DEF FN A(X) = ... in BASIC, and maybe even func = lambda x: ... in Python. But I sort of included an analogous construct in ALGOL 58, so maybe it should. Jan 21, 2021 at 6:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .