Hello. And it’s time now
for the Post JavaScript Apocalypse. So, I think a lot about
what happens after JavaScript. JavaScript,
unexpectedly has become the most important programming
language in the world. Nobody expected that,
nobody wanted that. It just happened. So, JavaScript is everywhere, right? It’s the language of the browser. It’s now taking over the servers. It’s getting into embedded systems. It’s everywhere. And I’ve been thinking about,
how are we going to get rid of it? What’s going to happen next? Because if it turns out that JavaScript
is the last programming language, that would be really sad. We need to do better
than that for the kids. We can’t leave JavaScript to your kids.
That doesn’t make any sense. So, there’s going to have to be a language
that comes after JavaScript. I spent a lot of time thinking
about what that’s going to be. Now, there’s some experts
who are upset at the title of this talk. They think it should be the
“The Put JavaScript Apocalypse.” There are other experts who say, “No, you’re an idiot.
It’s The Patch JavaScript Apocalypse.” This confusion between post,
put and patch is due to HTTP, the hyper-text transport protocol. It contains three methods
with three commands for moving a document from one end
of the network to the other, which are almost identical. They all kind of do the same thing, but there are a few
edge cases or corner cases where they do something different. It’s really confusing to use them because it’s not clear
what those special conditions are. There’s some authorities who say that if you use the wrong one
at the wrong time, disaster can occur. I don’t know if that’s true
but it sounds pretty scary and maybe we should pay
attention to that. So, it seems to me that
in a well-designed system, it should be obvious
what the right thing to do is. So, we don’t have to have
discussions and arguments, and write essays about
what the right one to use is. There should be just one and not three. Then, it’ll be clear what we do. So, having this extra stuff,
I perceive as clutter. Having clutter in our systems makes
our systems more difficult to use, more difficult to learn, makes it more difficult for us
to work together well. So, in thinking about the language,
I’m also thinking about, how do we get the clutter
out of our languages so that we can be more effective? We often think of life
as the accumulation of stuff. You live, you work,
you make money and you buy stuff. So, you’re accumulating stuff. You think of the value of your stuff as the cost as acquisition
or maybe a cost of replacement. But that’s not really the value to it. It turns out,
if you accumulate enough stuff, your stuff starts to have negative value. That you can’t find
the stuff you really want because it’s hidden behind something
that you don’t care about at the moment. Sometimes, you’ve got stuff
which is destroying other stuff because it’s on top of it
and the weight of it is crushing it or it’s leaking onto it. So, it’s actually, itself not very valuable, but it’s destroying the value
of stuff which maybe you do value. So, eventually you get too much
stuff and you should get rid of it because some of the stuff has negative
value and you want to put it on eBay, recycle it, gift it,
or something— That there may be a better way of
having it provide value to the world than by holding it on yourself. So, thinking about how we remove clutter from our programming languages
and how we remove clutter from our lives. Is there anything we can learn
from that process? It turns out the world’s greatest
authority on this is Marie Kondo, or KonMari. She’s a brilliant Japanese woman who’s the world’s greatest expert
on organizing households. She’s authoritative
on how to put things away, how to organize,
how fold, stack,
and all that stuff. She’s really good at this. She has this amazing practice in which she helps people
to shed their stuff. What she teaches is that
you go into a room and you take everything
out of the drawers, off the shelves,
out of the closets. You put it in the middle of the floor. Then, you pick up each item
and you ask it a question. In Japanese you could ask,
“Tokimeku [unintelligible]?” Which means, “Are you throbbing?
Do you vibrate?” That’s the thing communicating to you, telling to you,
“Yes, I have value. Save me." "Don’t put me on eBay.
You need to keep me.” When she teaches in English, she doesn’t say throb or vibrate
because people giggle. Like that guy. So, instead she says,
“Does it spark joy?” Which is just lovely. Isn’t that lovely?
Does it spark joy? You hold it up,
if it sparks joy, then that means it meaningful to you. You want to keep it. If it doesn’t spark joy,
then why do you even have it? You should probably get rid of it. I would like to apply
that discipline to programming, except it doesn’t work. We’re hoarders. Basically, in our programming systems,
we love the clutter. Everything sparks joy. So, we have no practice
at getting rid of the stuff. So, I want to take us through an exercise in which we’ll look
at some things and try to determine, is this really necessary
and can we get rid of it? Because unless we approach
it in a particular way, we’ll never understand it. So, we’ll start ASCII. The American Standard Code
for Information Interchange. This was an early standard
for connecting telegraphs together, and eventually it became
the standard character set for programming languages and computers. It still survives today as the first
128 characters of the Unicode. It’s brilliant.
It was a really important step forward. It contains two characters
that were adopted from the mechanical typewriter. If you remember the old style… You push a button and a key goes up. There are two codes that
were inspired by that typewriter. The TAB character and the SPACE character. The space character
was inspired by the spacebar. You press the spacebar
and it would release a ratchet, which would allow the carriage
to move one character position. The tab button was inspired by
the tabulate button on the type writer, which would release the carriage
and allow it swing freely until it was halted by a mechanical
obstruction called a tab stop. The purpose for the tab key
was to make it easier to enter columns of numbers
or tables of numbers. These two characters survive today. Unfortunately, the specification
of the tab character in ASCII didn’t provide any way
of indicating what a tab stop was. There was no suggestion
for what a default tab spacing would be. So, we argue about it
because there is no standard. We even argue about,
should we have them at all? It’s a thing that goes on and on, and it wastes a huge amount of time and provides no value. So, who has seen Silicon Valley? There should be more hands going up. So, everybody,
buy HBO. Don’t steal it. Do you steal cable here?
I don’t know if that’s a thing. Where I come from,
they steal cable. But you shouldn’t do that. You should be buying HBO
because HBO deserves to be compensated for making the best program ever
about programing. It’s about the adventures
of Richard Hendricks, who is a brilliant programmer
living in Silicon Valley and his adventures in trying
to start a software company. He’s a guy who works really hard, he’s spending all of his time
writing software and trying to start his company. He doesn’t have time to find a girlfriend. You probably know the type
or are the type. But in Season 3,
he finally finds someone. She’s great. She is smart,
she's nice, she’s a programmer and she seems
to like him for some reason. But she uses spaces instead of tabs. It turns out that his affection
for invisible control character is deeper than anything he could ever
feel for another human being. So, he destroys
the relationship over tabs. Looking at the human misery that tab-space conflict creates. It turns out that there’s no value in it. There are people who don’t use tab,
who manage to do stuff successfully. So, we have a large amount of evidence
that shows that the tab is unnecessary. Does it add enough value to justify
all of the misery that it causes? I think, objectively,
it doesn’t. So, I propose that from this point on, no more tabs. Don’t misunderstand this. The argument is not which way is better. The argument is:
which one can we get rid of? We can’t get rid of space,
so the one that has to go is tab. Tab does not spark joy. ASCII had two characters for quoting. JavaScript and other languages
use them both. JavaScript uses them interchangeably. So, you can use single quotes
to wrap a string or double quotes to wrap a string. Either works. For a long time,
I tried to make sense out of that. So, I tried to develop rules for; in these situations you use that one,
in other situations you use that one. I saw other people
had different sets of rules and their rules seemed to make
as much sense as mine did. So, there’s all this clutter. Two different ways of doing things, no value for having
two different ways of doing things. So, I recommend
that we get rid of one of them. The one we should get rid
of is the single quote because it is overloaded. It is also used as the apostrophe. So, if we stopped using
it as a single quote, then we can just say
it’s the apostrophe. Everything is cleaner and less cluttered. That’s good. In ES6 JavaScript got a let statement, which is similar to the var statement
except it respects block scope. So, I’ve seen people trying to figure out
when to use let and when to use var, and trying to use them
together at the same time, which doesn’t make any sense. We should just use one of them. So, the one I propose that we use is let. Let has the advantage that it doesn’t
confuse the Java guys so much. So, we should stop using var
and we should use let, unless you have to support IE6
because it’s a syntax error. There are IE7,
IE8, IE9 or IE10. Let’s just stop doing IE,
what do you say? Edge is pretty good
and all the other browsers are great. So, let’s just stop doing IE. Internet Explorer does not spark joy. So, we get rid of the var statement. ES6 also introduced the const statement, which is similar to let
except you can’t assign to that variable. That’s even better. Given a choice,
I’d rather use const than let. So, JavaScript has two bottom values: null and undefined. Now, there’s an argument
among language designers; should a language have any bottom values? There’s nobody who thinks
you should have two of them. JavaScript has these two bottom values
and it doesn’t make any sense. So, I recommend
getting rid of one of them. We shouldn’t use both of them. Usually, if there’s a choice between
a longer thing and a shorter thing, I’ll take the shorter thing but this time,
I’m going with the longer thing. I’m saying we should get rid of null, as it’s currently practiced in JavaScript
because type of null is broken is anyway, so let’s just stop doing null
and do everything with undefined. Now, the idea of null
as a special kind of pointer, as a feature of the programming language, was due to Tony Hoare,
a brilliant British programmer, who has since recognized that the null pointer
was a billion dollar mistake. He came to that by totaling the cost
of all null pointer exceptions. He figures he’s at least
into billions now. So, the idea of a special kind of pointer
to nowhere doesn’t make sense, but a special object
representing something which is not something else is an important idea. I think that’s what we should have. So, in the next language,
I think we should have null as an immutable,
empty object. It’s possible to make such a thing
today in JavaScript. So, null would be a const, meaning you can’t assign to null. And it is an object
which contains nothing, which inherits nothing,
which is immutable. That’s how you would write that ES6. The thing that we can’t do
in ES6 right now, if you try to extract
something from that object, it should return null itself. It shouldn’t return
undefined as it does now. If we had such a thing, then you could have
a long dotted expression. If anything along that line
doesn’t resolve to an object, instead of throwing an exception, you just get null at the end, which is what it should’ve always done. So, I’d like to see that
in the next language. There’s a lot of talk today
about pure functional programming. Functional programming,
after a long delay, is suddenly becoming
really important. It’s because functions are the key to solving a lot of
our most important problems. Then, there’s this idea
of going even further, of adopting some of the conventions
of mathematical functions. Mathematical functions are quite different
than software functions because they’re not about computation, they’re about mapping
of one set of values to another set. There are interesting
properties of such functions. For example, a given input
will always yield exactly the same output. That’s not generally true
of software functions but it is true of
mathematical functions. The idea is,
let’s write software functions that have the same property. It also means that functions
can cause no mutation, can cause no side effects. The only thing they do is return values. So, why would we want this? Well, turns out you get
some interesting things. One is greatly improved testability. Because if you can demonstrate that,
given a certain input, a function will always return that output, you don’t have to test it again. You don’t have to worry about what else
is happening in the environment, which could cause
this thing to eventually fail. That can’t happen
if your functions are pure. You get composability. It turns out pure functions can
be composed in really interesting ways. That provides a much more effective way
of doing higher order programming. Maybe the best advantage
is you get parallelism. Because if you’re trying to make
things go faster in multiple cores, with multiple threads,
with shared memory, bad things happen
called races and deadlocks. But if your functions are pure, they do not read,
modify, write, because they’re not causing mutation, which means that they don’t cause races
and they never need to synchronize. They don’t block. So, everything can be running full speed,
everywhere. So, we can potentially get
the fastest possible programs from such a model. So, it turns out we can turn JavaScript into a pure functional language, simply by removing the impurities. We don’t even need to change
the standard to do that. We can do that ourselves. We can use a pure subset
of JavaScript and just program in that, we just have to remove some things. For example,
we have to remove the date function because every time
you call the date function you get a new date. Which is a different time
than any date that came before, that’s not pure. So, we have to get rid of that. Similarly,
Math.random. Every time you call random,
you get a different random number. That’s not pure,
so that’s got to go. We have to get rid of the delete operator
because it will modify an object and we can’t cause mutation anymore. Object.assign and other object methods, which similarly would change
the content of an object, we have to get rid of those. Array.splice and all of the other
methods that modify an array, we can’t use those either. Array.sort could have
been a pure function. Had it been designed properly, it would have returned a new array, which was like the original array,
except sorted. But it doesn’t do that. It sorts in place,
it’s mutating. That has to go. Regular expression exec function,
it keeps some state. So, that’s got to go. Assignment.
You can’t use assignment anymore. That’s actually good because we can get
the equality operator back. We should never have used
the equal sign for assignment. So, since we’re not assigning, that becomes free. We have to get rid of the var statement
because we’re not going to have variables, because you mutate variables
and we’re not going to have mutation. We’re going to get rid of let as well. We can keep const.
Const is actually okay. You only assign to something once,
so it’s not causing a mutation. We have to get rid of the for statement because it wants to be modifying
an induction variable and we don’t modify things anymore. Users. It turns out, every time you talk to a user, they’re going to tell you
something different. Users are not pure.
So, they have to go. The network. Every time you talk to the network,
it’s liable to tell you something else. So, there’s no purity there as well. So, the difficulty with doing
pure functional programming is that… Well, if all you’re doing is computation,
then it’s great. It’s brilliant and it works really well. If your programs have to interact
with the universe in any way, it becomes really difficult
because the universe is mutating. If it’s going to interact in any way
with the universe, you need to mutate. So, I recommend a style in which
you’re as pure as much as you can. Try to get as much of your system
into pure functions because then you get the performance,
the testability and all of that, but you’re still going to need mutation
for dealing with the universe. An account balance
cannot be a constant, right? We need to deal with that somehow. ES6 added a feature called generators,
which I think was a mistake. It’s weird syntax and it really changes the way
that the language works, I think,
in an unproductive way. More than that,
it’s completely unnecessary. So, it was like a gift
that was being offered to us. But I recommend,
you don’t want to hoard that. Just pass it on. What you really need
is just to understand how, in JavaScript, we can have one
function that returns another function. So, here’s a pattern for a generator. We start with a factory function, which is a thing that will return
a generator function. It will initialize a generator
and provide its state variables. Then, will return a generator function. Each time the generator
function gets called, it will compute the next value, update the state variables,
and return the value. So, it’s a really simple thing.
Just a function that returns a function. So, here’s an example.
This is the element function. The element function takes an array
and returns a generator, which will return
each element of the array. That’s a useful thing to have
in certain compositional patterns. It’s really straightforward
and it doesn’t need loops. Really nice. Callbacks have become a really
important feature of our languages, because they are the primitive mechanism
by which we deal with asynchronicity, and asynchronicity is really important
because the universe is asynchronous. So, being able to deal
with that is important. It turns out there are
two ways you can specify a callback in a calling sequence. You can have it be the first argument with a function that will receive the result of the computation, or it could be the last one. JavaScript didn’t care. So, you could do it first,
you could do it last. Some people would do it first,
some people would do it last. Then, they argue about it. Who’s right,
who’s wrong? For a long time,
we had no way of resolving this argument. It’s a problem in having
these two conventions because it makes it difficult
to have systems work together. It turns out though,
ES6 teaches us, finally, what the right answer is. That is the callback argument
should be first. The reason is we can now have functions with a variable number of arguments
using the ellipsis operator. The ellipsis has to come at the end. So, it means the callback has to be first. So, anybody who’s putting them
at the wrong end, you’re on notice. You’ve got some code to fix. One of the places where we get really emotional about our languages is in the syntax. Syntax is all about fashion,
it’s not about functionality. But we get really upset about syntax. We love the syntax.
We’re completely irrational about syntax. So, let me show you a little bit
of syntax through the ages. We’ll start with FORTRAN IV. This was my first language. FORTRAN was developed
before lowercase was discovered. FORTRAN had an interesting parsing rule, in that spaces were not significant. So, the compiler effectively
deletes all of the spaces before it starts parsing. So, in order to distinguish
a variable called IFA, versus IF A, it required parenthesis
around the condition. So, it could break those things. FORTRAN made the mistake, it wasn’t the first language to make this
mistake but it was an influential one, of using the equality symbol
to mean assignment. Because it did that, it came up with this wacky .EQ. thing to do equality. BCPL was the first good-parts language. It was the good parts
of a bigger language called CPL. BCPL was this really small,
elegant, portable,
wonderful, brilliant little language. It was the first curly brace language. This is its IF statement and I think it’s a pretty nice
looking IF statement. It got a lot of things right. For example,
it’s using the equal sign for equality, it gets big points for that. The parenthesis around the condition
are now optional and the curly braces around
the consequence are now required, which is exactly right. It got that exactly right. It used the Pascal assignment operator
for assignment, which is okay. BCPL was the model for B. Unfortunately B went backwards and adopted the FORTRAN convention. So, today when we look at JavaScript, we see that the parenthesis
around the condition are now required again and the curly braces around
the consequence are now optional, which is awful. So, I recommend you should always put the curly
braces in on every if on every else, every time,
no matter what. Because it makes your code more agile. It means that it’s more
likely that someone else, including future you, might come along someday
and make this code even better without stumbling over
an unnecessary error. I hear from people all the time, “I can’t…
You have to go…” Just do it. Put the curly braces in
for crying out loud. So, you’ve probably heard of ALGOL 60. ALGOL 60 was the best language
designed by a committee in history, maybe the only good language
designed by a committee in history. They advanced
the state of the art tremendously. It was a great piece of work
and it was so successful they thought, “Let’s do it again.” So, a few years later they convened
another committee of very bright people and they developed ALGOL 68. ALGOL 68 is huge,
messy, weird,
and it didn’t work out very well. But I really liked their IF statement. There was an elegance that
they come up with in the IF statement, which I think is quite attractive. They got rid of the blocks. So, the curly braces,
the begin, end. All of the blocks are gone. Instead, they’ve got
balanced pairs of letters. So, they got IF to start the thing
and FI to end it. The nice thing about that is that you can be looking
at a piece of program— and we use end curly brace
to end of an object literal, the end of a function,
the end of a block. So, scanning down the page,
you’re seeing a lot of curly braces and it’s hard to know
what that matches up with. If a bunch of them are FI’s instead, then parsing the program,
mentally, becomes much easier. We buy a legibility in our programs,
which I think is a very valuable thing. I think we can improve
on this a little bit more. So, here’s a suggestion, something that we might
see in the next language, we take advantage
of what we’ve learned from Python to make white space significant. So, we require a line break
after the condition and that means we can now
get rid of the "then," we can get rid of the semi colon. We’re getting kind of minimal. There was a brilliant language
called Rebel, which used the colon
as the assignment statement, which I think looks really nice. So, maybe we can get down to that, just a suggestion. So, what language is this? Any guesses? Anyone? Java, yeah.
Obviously. Who else would write crap like that? So, what this is it’s not a language a feature,
it’s a symptom. It’s a symptom of problems
in the type system of the language. So, for example,
Java originally did not have functions. Instead, it needed “finally” because there are lots of ways
of moving through this code, and they wanted some place
of putting the cleanup code that they only had to specify it once. The correct way to do that
would be to write a function, then you could call a function
from all those places but they didn’t have functions. That was a major error
in the design of Java. So, instead they had this “finally” thing, which is strange,
weird, and turns out,
ultimately is unnecessary. If you look at how “finally”
is implemented in the JVM, they introduced
a call return pair of codes just for “finally.” Then there are all these catch clauses. Why are there so many catch clauses? It’s because often, there are multiple things
that a function might want to return. There is the normal thing
but sometimes you want to signal, “That’s all folks,
we’ve reached the end of it,” or, “Here’s something a little out
of the ordinary but that had to happen.” The Java type system didn’t allow
for all of those other things. It only allows one type
of object to be returned but there are other things which
normally need to be returned also. So, they overloaded
the exception system to do that. They’re using the exception system
as a work around for the type system. Since the type system doesn't allow you
to do the correct thing, instead we take normal things
and call them exceptions, which is a problem
because they’re not exceptions. They’re things that happen all the time. Exceptions should only be
for the things that never happen. So, as a result of that, we get very complicated control flows where some other piece of software,
someplace else, is determining which of these things
we’re going to execute. The thing this most reminds me of
is the FORTRAN assign to go to. In FORTRAN, you could put
a line number in a variable and say, “Go to that variable
and end up some place.” That’s what this is like. So, in well written JavaScript,
we don’t do this. Instead, in JavaScript,
we’ll try something. If it doesn’t work,
then we’ll try something else and then we’ll clean up if we have to. So, we don’t even care why it failed. It shouldn’t have failed,
so it didn’t matter; but it did,
so we have to do something but that’s it. So, we don’t need to have
all these complicated control flows because we can have functions
return all of the things that are meaningful
for that function to return. As a result of Java having
this broken type system, we get weirdness in some of the APIs. For example the indexOf method, where you search
for a substring in a string and if you find it, you return
the position at which you found it. If it fails,
it returns as -1, which is at least confusing
because -1 is an int. So, if you want to take this result
and put it into a computation, it could go really bad
and there’s no warning, there’s no exception,
there’s no nothing. So, the type system is supposed
to be preventing errors, it’s actually inviting errors
in this case. JavaScript did not need
to repeat this error, but it did. JavaScript has a better type system, so it could’ve returned null or undefined if you tried to search for something
and it wasn’t there. Then, if you try to add with it, then it’ll be much easier to detect that. Here’s a problem. You’re going to add two int32’s together. What is the type of the sum?
Any guesses? Oh, close. It’s int33. The correct answer is int33
because it turns out, if you add two int32’s
and if they’re big, the result is going to overflow
if you try to put an int32. So, you need an int33
to contain that result. Let’s try another one. int32 times int32. What’s this type?
Any guesses? int64?
Close. It’s int63,
but real close. But you were much closer than Java. Java said it’s int32,
which is wildly off. So, again,
the theory in these type systems is that the types
are protecting us from errors but in this case,
the types are actually inducing errors. There are things that
can go horribly in our program, which the types are not preventing,
which are actually causing. There’s an even bigger problem. 0.1 + 0.2 = 0.3
is false. Which I think is shocking.
This is quite awful. This is true in almost all
modern programming languages. Everything designed
over the last 20 years or so contains this horrible error. It’s due to the IEEE’s and 54 format, which is a binary
floating point specification. It turns out binary floating point cannot accurately represent
decimal fractions, which is only a problem if you’re
on a planet that uses a decimal system. But it causes problems for us. If you’re adding up people’s money, they have a reasonable expectation
you’re going to get the right sum. That’s not guaranteed by our type system. Even worse than that,
it breaks associativity. So, associativity works
in computer arithmetic only if the two inputs
are represented exactly and if the output can
be represented exactly, otherwise associativity breaks, which means the order in which
you add things will change the result, which again,
is shocking. We shouldn’t have this. We’re in the 21st century now, we should’ve figured this out by now
but we haven’t. So, I propose to fix this. So, I’m proposing a new number type which should be the only number type
in the next language. It does arithmetic in the way
that you were trained to arithmetic, so you’re not going to be
surprised by the results. It’ll just do it much faster
and more accurately than you can but it’s not going to get 0.1 + 0.2 wrong. It fits in the 64 bit value. The coefficient is 56 bits, which gets us a lot of precision. The exponent is 8 bits,
and I put it at the bottom end because on Intel architecture,
we can unpack that for free, so it allows us to have very fast
emulators of this format. The key thing here is that a number is the coefficient times 10
raised to the exponent. So, that’s it.
There are no other tricks in this. It’s really simple and straightforward. So, there is
a reference implementation available on GITHUB
for dec64 assembly language. If you’re designing the next language, I recommend you take a look at this
and incorporate it in your design. It can do an add of two integers
in five instructions, which might say,
“Well, that’s five more than adding ints,” except those five instructions also
give you overflow protection and mans, which are useful things to have. In a hardware implementation, it should be able to add integers or any two numbers with equal exponents in one cycle, which should eliminate the performance
argument for why we should have ints, because we shouldn’t have ints anymore. So, what is 0 divided by 0? Any guesses? So, mathematicians
will say it’s undefined. They don’t mean that in the silly way
that JavaScript means undefined. They mean it doesn’t make sense
to ask the question. You shouldn’t be saying that.
Shh! That makes sense,
except that computers have to compute. It’s inevitable somebody’s going to do it. So, what should happen
if someone tries to do this thing which is undefined
that should never happen? There’s one theory that says
the machine should catch fire. Because no one’s ever going to do it,
so it doesn’t matter, right? Probably not going to get
to five 9’s that way. There’s another argument
that says it should return NaN or some other sentinel value which says, “This isn’t the number
you’re looking for.” That’s a reasonable thing. There’s another argument
that says it should be zero, because zero of anything ought to be zero. There’s some mathematicians
who actually like this. There are more that don’t. In business processing,
this actually makes sense. If we didn’t sell anything this month but we want to know what the average
profit for a thing we didn’t sell was, zero divided by zero is going to be zero. That’s fine.
Nothing’s going to catch fire. No one’s going to get upset. “But that’s undefined!” It’s just,
“We didn’t sell anything.” So, for business purposes,
zero is actually the right answer. There’s one argument that says it’s one because an overhand is one. I once worked on a mainframe
where it was two. It was exactly two. This was a mainframe
that was designed Seymour Cray, the best computer designer in history. I can imagine the conversation
that happened at control data. Someone said,
“Hey, Seymour, there’s a problem
with the divide circuit; that zero divided by zero is two." He says,
“Yeah, so what?” “Shouldn’t it catch fire
or do something else?” I think he said,
“Look, if I had to fix this, it’s going to add more
complexity to the thing, it’s going to raise
the cost of the machine, and it’s already one of the
world’s most expensive machines. And it’s going to add
a cycle to every divide, and divide is already
the slowest in the instruction set, so I’m going to slow
everybody’s program down, just for the idiot who’s going to divide
something that he shouldn’t divide. I’m not going to do it.” As far as anybody knows,
I’m the only person who ever did it and it was fine. So, why do I care
about zero divided by zero? I’m actually more concerned
with zero times n. So, what is zero times n? Any guesses? Zero seems an obvious answer,
shouldn’t it? There were compiler writers
who understood, like you did, that if they can determine
that if one of the operands of a multiplication is known
at compile time to be zero, and if the thing on
the other side is pure, has no side effects, we don’t have to generate that code. We can just plug in
a constant and we’re done. So, not only does the program get faster,
the compilation gets faster. This is a huge win. When the IEEE floating point
standard was published, those programs were now in error. Those compilers were in error
because it says if N is NaN, then the result has to be NaN. That there are values that we can
multiply by zero that do not produce zero. Which means that you now
have to evaluate both sides, even if you know it’s useless to look for the chance
where this thing is a NaN, so that we can punish the wicked. Because this is not something
that good programs do, this is just weirdness. We’re slowing everything
down for moral reasons, not for mathematical reasons. So, who would write code like that? Often humans don’t but machines do. For example,
code generators, macro processers,
partial evaluators. They can all make really good use
of multiplication by zero. Also, it turns out modern CPUs, one of the slowest things
they do is conditional jump. So, there are idioms in which
we can avoid conditional jump by multiplying one thing by something
which might be zero or one, then we subtract that thing from one
and multiply another thing by it and then add them together. Doing two multiplications where you want
to do an assignment can actually be faster than doing conditional jumps but only if the hardware
allows it to be faster. So, I propose that all
of these forms should produce zero because why not? They allow things to go faster and there are idioms
that benefit from this, and I think we would all
actually benefit from that. In fact,
the dec64 standard requires this. So, next language,
I think that’s how math should work. Our languages have reserved words in them and reserved words are a problem. They make things harder for programmers because you have to be aware
of the list of reserved words. If you forget something
that’s on the list, then your program won’t compile. It’s a problem for language maintainers because they can’t add
new features easily; because it might be that somebody
has already used that word as a variable. For example,
exceptions used throw instead of raise. Raise was the ideal word
for causing an exception but the word raise had already
been used for other purposes. What’s a word no one would ever use? They came up with throw. Most of you have never
seen anything but throw, so you’re used to seeing that
but that was not an ideal consequence. The reason for that was because compilers used to have to be written in machines that had just a few K in them. By not having them have to figure out
what the meaning of a word was, they didn’t need to use
quite as much memory, but we now have gigabytes. Soon, maybe, we’ll have
terabytes of memory in our machines. Those concerns don’t exist anymore. So, I recommend a new reserved word policy
which is actually easy to implement. In any function, a word may be used as
a language keyword such as “if,” or as a name of a variable but not both. The programmer decides
how it’s going to be used. It turns out that’s easy to implement, so we should do that
and it makes everything better. One other argument:
camelCase or under_bar? Do we need two of these? Again, it causes endless argument, incompatibility,
and all this weird stuff. This is one of these arguments
that goes on and on because everybody’s wrong. It turns out the right answer
is names with spaces. Names with spaces. So, why didn’t we always have
names with spaces? FORTRAN actually had them
but we stopped doing that. Again, it was because we had machines with not enough memory in them
and it made it hard. So, here’s an algorithm for doing that. It’s pretty simple. Names with spaces in the next language. One of the really good ideas
in language design was contracts, programming by contract,
that was in the Eiffel language. Contract allowed you,
in a function, to specify preconditions
and post conditions, which were sets of booleans which would be true if everything
is good for calling this function and if everything is good after
having called the function. These contracts can give you much better
information than type systems can, and they’re in the program,
so they act as self-documentation. For some purposes, they work better than unit testing
because it’s built in there. If you’re smart, you’ll leave them
enabled during production but you don’t have to,
you can turn them off. Unfortunately, that language got lost
in the object oriented thing but we should try to get
the idea of contracts back. I think that should be
in the next language. Security is a vitally important topic because so much
of our lives are now online and everything is connected, and our programming
systems are not up to it. Our programming systems are failing us. So, I’m hoping that the first requirement in the next language is security, that they will look at that stuff
from the beginning, not try to tack it on later
because that has never worked. Then, finally,
distribution. All of our languages since FORTRAN, had been dealing with trying
to do sequential things, doing one thing after another. Now, we’ve got multi cores, we’ve got lots of processers
that want to have lots of things happening at the same time and our sequential programming
languages are really bad at that, and we’ve got the network. So, we want to put stuff out on the Cloud,
distribute our program over thousands, millions of machines potentially, and our languages are not good
at that either. So, I’m hoping that the next language
will have actors or maybe some other,
may better way of dealing with it. Some way of not having
just one thing after another. It’d be really disappointing
if it turns out that the next language is just FORTRAN
with new syntax again, because we’ve done that so many times. The next language
should be a new paradigm. So, that’s the end of my speculation
about the next language. I’d like to leave you with a warning. Be careful out there because the web is cluttered
and full of errors. Thank you.
I am probably just too entrenched to be a visionary of new language, but the concept of names with spaces makes my skin curl.
You know why you can't put comments in JSON?
Douglas Crockford. That's why.
/shakes fist
tl;dw: get rid of the non-essentials.
so no more tabs, no more single-quotes, use
let
instead ofvar
(orconst
instead oflet
if you can), stop supporting I.E. as a target, stop usingnull
and only useundefined
, write more pure functions by not using impure javascript features, don't use generators, put the callback first in a parameter list so you can use the ... operator at the end, always put curly braces in if-else statements, etc. There's some other stuff in there about dec64, but just watch the video if you actually care.This reminds me of an excellent and absolutely hilarious talk by /u/garybernhardt about the future importance, and inevitable irrelevance, of JavaScript:
https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript
Can't be worse than the javascript apocalypse we've been band-aiding our way through
Excellent talk.
However,
int32 * int32
does requireint64
.INT32_MIN * INT32_MIN
is 4611686018427387904, which can only be stored in anint64
. If you try to store it in an int63, you'll end up overflowing toINT63_MIN
(-4611686018427387904).It's kind of funny how he compares the type system of JS favrourably to the one of Java.
Elm seams to be offering an idea about what a sane language could look like. It still has a long way to go until it reaches 1.0 but it's already quite usable.
What a tedious, dreary, rambling talk full of nonsense and bad advice.
Its not entirely wrong, but probably 90% of it is bullshit. Douglas Crockford doesn't understand why decimal arithmetic is worse than binary (hint: decimals give you larger errors and worse failures than binary), thinks that NANs are a moral decision to "punish" people, fails to understand the advantage of keywords, doesn't see any problem with
0/0
returning 2 (yes, you heard me, 2) ... I could go on, but then I'd be as tedious and boring as his talk.Talk "does not spark joy". Get rid of it.