I was wondering about the origins of the "let" used in Lisp, Clojure, and Haskell. Does anyone know which language it appeared in first?
-
Assembler uses MOV instead of LET from 1954. Isn't it enough?– GangnusCommented Feb 22, 2014 at 22:44
-
1LISP is old enough to be a good candidate.– mouvicielCommented Jul 2, 2014 at 9:05
-
3for any question "In what programming language did X first appear" lisp is a pretty good guess for a correct answer– Zachary KCommented Jul 15, 2014 at 10:21
-
2let origins are from math, not from other programming languages.– Pieter BCommented 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 BCommented Aug 20, 2014 at 11:20
5 Answers
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.
-
12But 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-logicCommented Apr 8, 2013 at 8:12 -
12But 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).– GregCommented Apr 8, 2013 at 12:54
-
7
let
in this context (let
xis
somethingin
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-logicCommented 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.– GregCommented Apr 9, 2013 at 12:00
-
1of course I used ML notation, and I meant
equals
, notis
. And, yes, pseudo-code is the best answer so far.– SK-logicCommented Apr 9, 2013 at 12:42
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 ofid
, namelyid
In the expression:id id
In the expression:\id -> id id
-
+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".– GiorgioCommented 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.– PetrCommented Apr 8, 2013 at 17:56 -
3
-
2It 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" ...– PetrCommented Jul 15, 2014 at 17:38
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
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 asDEFMACRO
and the complex Lisp MachineDEFUN
argument syntax.
Still doesn't quite answer whether it was invented in another language earlier, of course, but still another data point. :-)
-
4ML was also developed during the 70s so it might be that the idea was introduced in both ML and Lisp in that period.– GiorgioCommented 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
. Commented Oct 15, 2020 at 20:15
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))
-
-
1AIM-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 oflet
were in the context of dynamically scoped Lisps. Today, Emacs Lisp still has dynamic scope by default, withlambda
andlet
(the latter sugar for the former anyway) binding their parameters dynamically. Commented Aug 20, 2014 at 8:49