157,316 karma · joined October 9, 2006
If you're known to be a regular user of a forum, then when someone says something about you and you don't reply, it reads as a tacit admission that they're correct. And when you write essays people say all kinds of things about you. The combination is a disaster. Forum users can sense that you're compelled to respond, and it encourages them to pick fights with you.
Back when I used to moderate HN, hitting publish on an essay was usually followed by several hours of saying various forms of "No, what I said was..." Life is much better now that I never look at the HN threads on them.
I still think Elon is a smart guy. His work on cars and rockets speaks for itself. Nor do I think he's the villain a lot of people try to make him out to be. He's eccentric, definitely, but that should be news to no one. Plus I don't think he realizes that the techniques that work for cars and rockets don't work in social media. Those two facts are sufficient to explain most of his behavior.
He could still salvage the situation. He's the sort of person it would be a big mistake to write off. And I hope he does. I would be delighted to go back to using Twitter regularly.
I don't know how much my experience translates to other people, because my "career" has been unusually random, but when I retired from YC what I was thinking was that at 49, if there was something I'd been meaning to do, I'd better do it.
(def typecheck ((var f) arg env s r m)
(mev (cons (list (list f (list 'quote arg)) env)
(fu (s r m)
(if (car r)
(pass var arg env s (cdr r) m)
(sigerr 'mistype s r m)))
s)
r
m))
says is, first create a function call (list f (list 'quote arg))
in which the function describing the type (e.g. int) is called on the argument that came in for that parameter. Its value will end up on the return value stack, r. So in the next step you look at the first thing on the return value stack (car r)
If it's true, you keep going as if the parameter had been a naked one, with no type restriction (pass var arg env s (cdr r) m)
and if it's false, you signal an error (sigerr 'mistype s r m)I'm not sure how true that statement is, but my experience so far suggests that it is not only true a lot of the time, but that its truth is part of a more general pattern extending even to writing, engineering, architecture, and design.
As for the question of catching errors at compile time, it may be that there are multiple styles of programming, perhaps suited to different types of applications. But at least some programming is "exploratory programming" where initially it's not defined whether code is correct because you don't even know what you're trying to do yet. You're like an architect sketching possible building designs. Most programming I do seems to be of this type, and I find that what I want most of all is a flexible language in which I can sketch ideas fast. The constraints that make it possible to catch lots of errors at compile time (e.g. having to declare the type of everything) tend to get in the way when doing this.
Lisp turned out to be good for exploratory programming, and in Bel I've tried to stick close to Lisp's roots in this respect. I wasn't even tempted by schemes (no pun intended) for hygienic macros, for example. Better to own the fact that you're generating code in its full, dangerous glory.
More generally, I've tried to stick close to the Lisp custom of doing everything with lists, at least initially, without thinking or even knowing what types of things you're using lists to represent.
I had to change Arc a fair amount to make this work.
Curiously, enough, though, I found doing development in Bel was sufficiently better that I'd often edit code in bel.bel, then paste a translated version into the file of Arc code, rather than doing development in the latter. This seemed a good sign.
As often happened with things I was forced into, though, I not only got used to putting numbers first but started to prefer it. It means for example you can compose them with other callable things.
So cleverness in implementation won't translate into compliance, but rather into inventing declarations that programmers can use that will make their programs dramatically faster. E.g. if programmers are willing to declare that they're not going to look inside or modify literals, you don't have to actually represent functions as lists. And maybe into making really good programming tools.
As I said elsewhere, half jokingly but also seriously, this language is going to give implementors lots of opportunities for discovering new optimization techniques.
where tells you what to set, and setting the cadr of (a b c) means setting the car of (b c).
(lit num (sign n d) (sign n d))
where the first (sign n d) is the real component and the second the
imaginary component. A sign is either + or -, and n and d are unary
integers (i.e. lists of t) representing a numerator and denominator. (def flip (f)
(fn args (apply f (rev args))))Making bel.bel shorter was one of my main goals during this project. It has a double benefit. Since the Bel source is a Bel program, the shorter I can make it, the more powerful Bel must be. Plus a shorter source is (pathological coding tricks excepted) easier to understand, which means Bel is better in that way too. There were many days when I'd make bel.bel 5 lines shorter and consider it a successful day's work.
One of the things I found helped most in making programs shorter was higher order functions. These let you get rid of variables, which are a particularly good thing to eliminate from code when you can. I found that higher order functions combined with intrasymbol syntax could often collapse something that had been a 4 line def into a 1 line set.
Lisp dialects have as a rule been good at making programs short. Bel is meant to do the same sorts of things previous dialects have, but more so.
It's also meant to be simple and clear. If you want to understand Bel's semantics, you can read the source.
(= f apply) (applyf (car args) (reduce join (cdr args)) a s r m)
rather than being something whose behavior you have to assume. > (set x '(a b c))
(a b c)
> (set (2 x) 'z)
z
> x
(a z c)
which you can do in Common Lisp, and > (set ((if (coin) 1 3) x) 'y)
y
> x
(y z c)
which you can't.