Swift has a compiler (swiftc) and a REPL. I like using the REPL to learn and play with language constructs.
In one of my experiments I came across a notable difference w.r.t how "let" works.
The following is, as I would expect, not allowed in swiftc, but the REPL allows it.
let x = 10
let x = 20 // ok in REPL
And now I am wondering what other differences there are. Are they documented anywhere?
In a REPL environment, you'd want to be able to redeclare variables, right? Otherwise, as you keep using the REPL, and you declare more and more variables, let
constants, functions, classes, whatever, you'll run out of names to use!
For example, let's say you want to try out string interpolation:
let x = 10
print("x is \(x)!")
And then a while later, you learn about string concatenation, and you want to try that out as well. At this point, you'd want to be able to redeclare a let
constant x
, right?
let x = "A"
let y = "B"
print(x + y)
You could argue that you could use a
or b
, but as time goes on, you'll slowly run out of names. REPL is designed like this so that you don't have to restart the REPL very frequently.
So each time you submit something, previously declared symbols that are also declared in the submission will get overwritten. This is documented here.
swiftc
has a completely different use case - you usually use it to compile larger programs, with more than just a few lines of code. In these situations, the global scope will have a lot less symbols, and redeclaring variables isn't really practical to implement, because the code execution isn't linear from top to bottom. There could be multiple files as well that talk to each other. How do you figure out what redeclares what? It just doesn't make sense to do this in anywhere other than a REPL.
Other REPLs have this feature too, like csharppad.com
for C#, ghci
for Haskell, and python
, just to name a few. So it's really just a common thing you do when you implement REPLs, not something special to Swift.
In fact, you can reproduce the swiftc
behaviour in a REPL by writing the two lines in a function, because now the two lines are in the same submission, and will not overwrite each other.