In earlier drafts I wrote "the existence of some set of best essays follows necessarily" but it sounded so pedantic that it didn't seem worth keeping just to protect myself from being accused of not understanding the distinction between a partial and total order. I assumed anyone reading it in good faith would understand what I was saying.
HN user
pg
Bug fixer.
It's not available yet. And in any case if this is the future there should be multiple companies doing it, not just Apple.
Thanks, but as I learned when I was running HN, being a regular user of a forum (which the moderator necessarily is) and writing essays are fundamentally incompatible.
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'm not leaving Twitter. It seems more likely than not that Elon will reverse the ban on links to other social media sites. I just don't want to hang out there in the meantime. Plus given the way things are going, it seemed like a good time to learn about alternatives.
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.
Yes. The root of the problem is that the hospitals' supply chain is brittle, and broke under the stress. One hopes it will get redesigned to be more robust. But in the meantime Flexport can get PPE now, and now is when it's needed.
This looks pretty good. The only thing I don't like is the coloring of tokens in the examples. It doesn't make them easier to read; it's just distracting.
As names, car and cdr are great: short, and just the right visual distance apart. The only argument against them is that they're not mnemonic. But (a) more mnemonic names tend to be over-specific (not all cdrs are tails), and (b) after a week of using Lisp, car and cdr mean the two halves of a cons cell, and languages should be designed for people who've used them for more than a week.
This was something I'd meant to do for a long time, and wanting to work on it was one of the reasons I retired from YC. Being overtly ambitious would have provoked haters, but few will see this thread now, so I'll tell you: the goal was to discover the Platonic form of Lisp, which is something I could always sense lurking beneath the surface of the many dialects I've used, but hidden by mistaken design choices. (T was probably the best in this respect.)
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.
It would not be clearer to use 1 instead of car when you were using a pair to represent a tree, rather than a list, and you were traversing the left and right branches using car and cdr.
An infinite number, in theory. Even (sign n d) does, since you can have anything in d.
What this
(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)You wouldn't learn much more from reading it, because (to an almost comical extent in retrospect) the internal code was just like HN. In fact, not just like; it was mostly the same code.
One answer to this question (and an exciting idea in itself) is that the difference between conciseness and many of these apparently unrelated matters approaches zero. E.g. that all other things being equal, the debuggability of a language, and the pleasure one feels in using it, will be inversely proportional to the length of programs written in it.
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.
It's still the case. bel.bel is generated by software. Most of the actual code is Arc that I turn into Bel in generating it. E.g. the interpreter and anything called by it, and the reader. But code that's only used in Bel programs, rather than to interpret or read Bel programs, can be and is written in Bel.
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.
Initially I would have preferred that. I did it that way in Arc. But since functions are lists in Bel, I couldn't do that, or you wouldn't be able to call a function on a number.
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.
I don't expect implementations to be compliant. Starting with an initial phase where you care just about the concepts and not at all about efficient implementation almost guarantees you're going to have to discard some things from that phase when you make a version to run on the computers of your time. But I think it's still a good exercise to start out by asking "what would I do if I didn't count the cost?" before switching to counting the cost, instead of doing everything in one phase and having your thinking constrained by worries about efficiency.
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 (cadr x)) would be ((b c) a).
where tells you what to set, and setting the cadr of (a b c) means setting the car of (b c).
In the same way it's an improvement over other Lisp dialects. There's no huge hole in Arc that Bel fixes. Just a lot of things that are weaker or more awkward or more complicated than they should be.
I talk about this in the first section of the The Bel Language: http://paulgraham.com/lib/paulgraham/bellanguage.txt
Because falsity is also the empty list.
Numbers are represented using pairs. Specifically
(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.That was once true, but it's all been rewritten.
I originally did call it flip, but then I took that name for the current flip:
(def flip (f)
(fn args (apply f (rev args))))It's so broadly the goal of the language that many things do, often in small ways. For example, it turns out to be really convenient that strings are simply lists of characters. It means all the list manipulation functions just work on them. And the where special form and zap macro make it much easier to define operators that modify things. The advantage of Bel is a lot of small things like that rather than a single killer feature.
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.
I think the point of a high-level language is to make your programs shorter. All other things (e.g. libraries) being equal, language A is better than language B if programs are shorter in A. (As measured by the size of the parse tree, obviously, not lines or characters.) The goal of Bel is to be a good language. This can be measured in the length of programs written in it.
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.
Because it's not a primitive. It's handled by a special case in the interpreter,
(= f apply) (applyf (car args) (reduce join (cdr args)) a s r m)
rather than being something whose behavior you have to assume.At first it was not just all one codebase, but all one thread. If HN was busy, all our internal software would run a little slower.
One thing you can say for Bel for sure is that it will give implementors lots of opportunities to develop new optimization techniques. That's partly humorously euphemistic, but also true.
The code I wrote to generate and test the Bel source is written in Arc, and Bel copies some things from Arc. Otherwise they're separate.
It's used to implement a generalization of assignment. If you have a special form that can tell you where something is stored, you can make macros to set it. E.g.
> (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.