27

I was wondering about the origins of the "let" used in Lisp, Clojure, and Haskell. Does anyone know which language it appeared in first?

6
  • Assembler uses MOV instead of LET from 1954. Isn't it enough?
    – Gangnus
    Commented Feb 22, 2014 at 22:44
  • 1
    LISP is old enough to be a good candidate.
    – mouviciel
    Commented Jul 2, 2014 at 9:05
  • 3
    for any question "In what programming language did X first appear" lisp is a pretty good guess for a correct answer
    – Zachary K
    Commented Jul 15, 2014 at 10:21
  • 2
    let origins are from math, not from other programming languages.
    – Pieter B
    Commented Aug 20, 2014 at 11:05
  • You make the incorrect assumption that the first use of "let" in a programminglanguage is the origin of "let"-use in Lisp, Clojure, and Haskell.
    – Pieter B
    Commented Aug 20, 2014 at 11:20

5 Answers 5

40

Well, BASIC had LET for assignment as part of the syntax from the start in 1964, so that would predate the use of let in Lisp, which as Chris Jester-Young points out didn't appear until the 1970s according to Evolution of Lisp.

I don't believe COBOL, Fortran, or ALGOL have LET in their syntax either. So I'm going to go with BASIC.

9
  • 12
    But semantics is very different - let in basic is not a lexically scoped binding. So, the correct answer would be something like "it first appeared in English, before 12th century".
    – SK-logic
    Commented Apr 8, 2013 at 8:12
  • 12
    But the questions is: What programming language did the "let" first appear? I don't really consider English a programming language (at least in this context).
    – Greg
    Commented Apr 8, 2013 at 12:54
  • 7
    let in this context (let x is something in the following expression) first appeared in mathematical texts in English, and this is where it came into programming. I see no difference between formal systems - mathematical languages, programming languages, whatever else - they're all the same.
    – SK-logic
    Commented Apr 8, 2013 at 16:43
  • 3
    "let x is 3" is not proper grammar. You would never see that in any English text book. You have the wrong tense of the verb "to be". It should be "let x be 3" or "let x equal 3". Either way, semantics or not, the question author was asking for a programming language. So unless you know of a computer that takes English instructions that predates BASIC, I'm not buying it. Otherwise, we could have just answered "psuedo-code" and that would be valid, but wouldn't honor the spirit of her question.
    – Greg
    Commented Apr 9, 2013 at 12:00
  • 1
    of course I used ML notation, and I meant equals, not is. And, yes, pseudo-code is the best answer so far.
    – SK-logic
    Commented Apr 9, 2013 at 12:42
31

I'd like to add a theoretical point of view: In classical lambda calculi, let is just syntactic sugar. For example

let x = N in M

can be rewritten simply as

(λx.M)N

So its first appearance in early (functional) languages isn't that interesting.

However, it become very important with the invention of Hindley-Milner type system and its type inference algorithm. In this type system let is indispensable, because it's polymorphic (unlike λ-abstraction in HM). For example, consider this simple expression:

let id = λx . x in id id

Here id is polymorphic, it has type ∀α.α → α, and therefore id id type-checks - it's type is id id : τ → τ for arbitrary τ. (For the first id we assign τ → τ to α and for the second id we assign τ for α.)

However, we can't rewrite it using λ abstraction and application. Expression

(λid . id id)(λx.x)

doesn't type-check, because within the first λ abstraction id must be assigned a monomorphic type id : σ for some σ, and there is no σ such that we could apply id : σ to id : σ.

You can try this yourself in Haskell. While let id = \x -> x in id id :: t -> t type-checks, typing (\id -> id id)(\x -> x) fails with

Occurs check: cannot construct the infinite type: t0 = t0 -> t0
In the first argument of id, namely id
In the expression: id id
In the expression: \id -> id id

9
  • +1 for a very interesting answer. As a side topic, if you know one, could you post (in a comment, since this is not related to the main question) a reference to a rigorous definition of "syntactic sugar".
    – Giorgio
    Commented Apr 8, 2013 at 17:32
  • 3
    @Giorgio To quote The New hacker's dictionary: Features added to a language or other formalism to make it "sweeter" for humans, features which do not affect the expressiveness of the formalism. Used esp. when there is an obvious and trivial translation of the "sugar" feature into other constructs already present in the notation. C's a[i] notation is syntactic sugar for *(a + i). The Wikipedia article also has a nice explanation.
    – Petr
    Commented Apr 8, 2013 at 17:56
  • 3
    interesting stuff but hardly related to let's introduction
    – wirrbel
    Commented Jun 13, 2013 at 7:14
  • 2
    It is a well written answer, but it does not answer the original question. Commented Jul 15, 2014 at 10:10
  • 1
    @JohanKarlsson I'm not claiming it is a direct answer, but I think this is also relevant to the topic. In particular why was let introduced, as the question starts with I was wondering about the origins of the "let" ...
    – Petr
    Commented Jul 15, 2014 at 17:38
22

Lisp is the oldest language of these having LET now. But BASIC was the first that got it, for Lisp had obtained it much later.

In Ada Lovelace Analytical Engine (1843) - no LET, a program looks as:

N0 6 N1 1 N2 1 × L1 L0 S1  L0 L2 S0 L2 L0 CB?11 '

In Plankalkül of Zuse (1943-45) the program looks:

P1 max3 (V0[:8.0],V1[:8.0],V2[:8.0]) → R0[:8.0]
max(V0[:8.0],V1[:8.0]) → Z1[:8.0]
max(Z1[:8.0],V2[:8.0]) → R0[:8.0]
END

Short Code was proposed by John Mauchly in 1949

X3 =  (  X1 +  Y1 )  /  X1 * Y1   

Intermediate PL of Burks, 1950, used for assignment ->

Rutishauser in 1952 used =>=

Böhms compiler, 1952, used ->

At the University of Manchester, Alick Glennie developed Autocode in the early 1950s. The first code and compiler was developed in 1952 for the Mark 1 computer at the University of Manchester and is considered to be the first compiled high-level programming language. Again, -> for assignment

Charles Adams, FORTRAN 0 of Backus's group , Brooker's Autocode 2, ПП1 of Lubimsky and Kamynin; all in 1954, again =

BACAIC (Grems, Porter), 1954, * for assignment!

Kompiler, ADES, 1955, =

IT, 1956, <-

FORTRAN, 1957, =

AT-3 (1956), Math-Matic (1957), again =,

but Flow-Matic in 1957 had two assignments, and both are in words

TRANSFER a TO b and MOVE a TO b

Bauer and Samelson's machine, 1957: =>


Sorry, I can't cover all languages between 1957 and 1964, but greater languages

1957 - COMTRAN (forerunner to COBOL)
1958 - LISP
1958 - ALGOL 58
1959 - FACT (forerunner to COBOL)
1959 - COBOL
1959 - RPG
1962 - APL
1962 - Simula
1962 - SNOBOL
1963 - CPL (forerunner to C)

have not LET for assignment. Or had not, in the case of LISP.


Dartmouth BASIC is the original version of the BASIC programming language. The first interactive version was made available to general users in June 1964;

 LET / = — assign formula results to a variable
14

Well, between those three, Lisp definitely had it first. Haskell came about in the 80s, and Clojure in the 00s, and let had been around long before either of those dates. :-)

As to whether Lisp was the language to have invented it, I can't vouch for that yet, but I'll do some research and see. :-)

Update: According to Evolution of Lisp (see page 46), it mentioned that let was invented in the 70s:

LET—itself a macro first invented and reinvented locally at each site—was a late-comer to the MacLisp world; according to Lisp Archive, it was retroactively absorbed into PDP-10 MacLisp from Lisp-Machine Lisp in 1979 at the same time as DEFMACRO and the complex Lisp Machine DEFUN argument syntax.

Still doesn't quite answer whether it was invented in another language earlier, of course, but still another data point. :-)

2
  • 4
    ML was also developed during the 70s so it might be that the idea was introduced in both ML and Lisp in that period.
    – Giorgio
    Commented Apr 8, 2013 at 9:04
  • Peter Landin's "Correspondence Between ALGOL 60 and Church's Lambda Notation" was published in 1965 and had "let" in it. His 1964 "The mechanical evaluation of expressions" already has where.
    – Will Ness
    Commented Oct 15, 2020 at 20:15
9

The first Revised Scheme report AIM-452 from January 1978 has LET. Page 9.

note that Lisp used earlier a different construct PROG to introduce local variables.

(let ((a 1)
      (b 1))
  (+ a b))

would have been written earlier approximately as

(prog (a b)
  (setq a 1)
  (setq b 1)
  (+ a b))
3
  • was let always lexically scoped in Lisp dialects?
    – wirrbel
    Commented Jun 13, 2013 at 7:15
  • 1
    AIM-452 is the first revised report on Scheme. The first report is AIM-349 from 1975. And AIM-848 is the revised revised report. And the one after that, called the "revised^3" report (i.e. first one to use the "R^nRS" naming) was the first that was not an AIM but an actual language specification. Googling around a bit will find you the PDFs of all these documents so you can read them for yourself. If you want to go further back you can find an old MacLisp manual from the Software Preservation Group, and maybe you'll be able to find some LISP 1.5 reports too. Commented Aug 20, 2014 at 8:11
  • @wirrbel, it seems let is about as old as lexical scoping (Scheme, '75), and it took a while for lexical scoping to gain acceptance, so I would guess that the first instances of let were in the context of dynamically scoped Lisps. Today, Emacs Lisp still has dynamic scope by default, with lambda and let (the latter sugar for the former anyway) binding their parameters dynamically. Commented Aug 20, 2014 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.