Being Popular
Эссе Пола Грэма (май 2001), задуманное как бизнес-план для нового языка программирования (будущего Arc). Грэм утверждает: язык не обязан быть хорошим, чтобы стать популярным, но он обязан быть популярным, чтобы быть хорошим, — потому что развитие и улучшения приходят от реальных требовательных пользователей. Главными судьями языков он считает не обычных программистов, а узкое меньшинство экспертов-хакеров, которые пишут весь хороший софт и влияют на выбор остальных. Чтобы язык полюбили хакеры, ему нужны лаконичность (краткость), возможность лезть внутрь и нарушать модель («hackability»), пригодность для одноразовых программ, мощные библиотеки, хороший профайлер вместо ставки на скорость компиляции и время на органический рост через ранних адоптеров. Грэм критикует Common Lisp за слабые библиотеки и отсутствие связи с ОС, противопоставляет органический рост (Unix, MacLisp) методу «большого взрыва» (Multics, Common Lisp) и доказывает, что есть надежда на новый Lisp — краткий, простой, «хакабельный» и заточенный под серверные приложения.
May 2001
Май 2001
(This article was written as a kind of business plan for a
new language.
So it is missing (because it takes for granted) the most important
feature of a good programming language: very powerful abstractions.)
(Эта статья была написана как своего рода бизнес-план для нового языка. Поэтому в ней отсутствует (поскольку принимается как само собой разумеющееся) самая важная черта хорошего языка программирования: очень мощные абстракции.)
A friend of mine once told an eminent operating systems
expert that he wanted to design a really good
programming language. The expert told him that it would be a
waste of time, that programming languages don't become popular
or unpopular based on their merits, and so no matter how
good his language was, no one would use it. At least, that
was what had happened to the language he had designed.
Один мой друг как-то сказал видному эксперту по операционным системам, что хочет спроектировать действительно хороший язык программирования. Эксперт ответил ему, что это пустая трата времени, что языки программирования становятся популярными или непопулярными не из-за своих достоинств, и потому, каким бы хорошим ни был его язык, им никто не воспользуется. По крайней мере, именно так произошло с языком, который спроектировал он сам.
What does make a language popular? Do popular
languages deserve their popularity? Is it worth trying to
define a good programming language? How would you do it?
Что же делает язык популярным? Заслуживают ли популярные языки своей популярности? Стоит ли вообще пытаться определить, что такое хороший язык программирования? И как бы вы это сделали?
I think the answers to these questions can be found by looking
at hackers, and learning what they want. Programming
languages are for hackers, and a programming language
is good as a programming language (rather than, say, an
exercise in denotational semantics or compiler design)
if and only if hackers like it.
Я думаю, ответы на эти вопросы можно найти, если посмотреть на хакеров и понять, чего они хотят. Языки программирования существуют для хакеров, и язык программирования хорош как язык программирования (а не как, скажем, упражнение в денотационной семантике или проектировании компиляторов) тогда и только тогда, когда он нравится хакерам.
1 The Mechanics of Popularity
1 Механика популярности
It's true, certainly, that most people don't choose programming
languages simply based on their merits. Most programmers are told
what language to use by someone else. And yet I think the effect
of such external factors on the popularity of programming languages
is not as great as it's sometimes thought to be. I think a bigger
problem is that a hacker's idea of a good programming language is
not the same as most language designers'.
Действительно, верно, что большинство людей выбирают язык программирования не просто по его достоинствам. Большинству программистов кто-то другой говорит, каким языком пользоваться. И всё же я считаю, что влияние таких внешних факторов на популярность языков не так велико, как иногда думают. Я думаю, что бóльшая проблема в том, что представление хакера о хорошем языке программирования не совпадает с представлением большинства проектировщиков языков.
Between the two, the hacker's opinion is the one that matters.
Programming languages are not theorems. They're tools, designed
for people, and they have to be designed to suit human strengths
and weaknesses as much as shoes have to be designed for human feet.
If a shoe pinches when you put it on, it's a bad shoe, however
elegant it may be as a piece of sculpture.
Из этих двух мнений значение имеет мнение хакера. Языки программирования — это не теоремы. Это инструменты, созданные для людей, и они должны проектироваться так, чтобы соответствовать сильным и слабым сторонам человека, точно так же, как обувь должна проектироваться под человеческую ногу. Если туфля жмёт, когда ты её надеваешь, это плохая туфля, какой бы изящной она ни была как предмет скульптуры.
It may be that the majority of programmers can't tell a good language
from a bad one. But that's no different with any other tool. It
doesn't mean that it's a waste of time to try designing a good
language. Expert hackers
can tell a good language when they see
one, and they'll use it. Expert hackers are a tiny minority,
admittedly, but that tiny minority write all the good software,
and their influence is such that the rest of the programmers will
tend to use whatever language they use. Often, indeed, it is not
merely influence but command: often the expert hackers are the very
people who, as their bosses or faculty advisors, tell the other
programmers what language to use.
Возможно, большинство программистов не способны отличить хороший язык от плохого. Но с любым другим инструментом всё точно так же. Это не значит, что пытаться спроектировать хороший язык — пустая трата времени. Хакеры-эксперты способны распознать хороший язык, когда видят его, и они будут им пользоваться. Хакеры-эксперты, признаю, — крошечное меньшинство, но именно это крошечное меньшинство пишет весь хороший софт, и их влияние таково, что остальные программисты склонны пользоваться тем языком, которым пользуются они. Часто, более того, это даже не просто влияние, а приказ: нередко хакеры-эксперты — это как раз те самые люди, которые в роли начальников или научных руководителей указывают другим программистам, каким языком пользоваться.
The opinion of expert hackers is not the only force that determines
the relative popularity of programming languages — legacy software
(Cobol) and hype (Ada, Java) also play a role — but I think it is
the most powerful force over the long term. Given an initial critical
mass and enough time, a programming language probably becomes about
as popular as it deserves to be. And popularity further separates
good languages from bad ones, because feedback from real live users
always leads to improvements. Look at how much any popular language
has changed during its life. Perl and Fortran are extreme cases,
but even Lisp has changed a lot. Lisp 1.5 didn't have macros, for
example; these evolved later, after hackers at MIT had spent a
couple years using Lisp to write real programs. [1]
Мнение хакеров-экспертов — не единственная сила, определяющая относительную популярность языков программирования (свою роль играют и унаследованный софт (Cobol), и шумиха (Ada, Java)), но я считаю, что в долгосрочной перспективе это самая мощная сила. При наличии начальной критической массы и достаточного времени язык программирования, вероятно, становится примерно настолько популярным, насколько того заслуживает. И популярность дополнительно отделяет хорошие языки от плохих, потому что обратная связь от реальных живых пользователей всегда ведёт к улучшениям. Посмотрите, насколько любой популярный язык изменился за время своего существования. Perl и Fortran — крайние случаи, но даже Lisp сильно изменился. В Lisp 1.5, например, не было макросов; они появились позже, после того как хакеры из MIT пару лет писали на Lisp реальные программы. [1]
So whether or not a language has to be good to be popular, I think
a language has to be popular to be good. And it has to stay popular
to stay good. The state of the art in programming languages doesn't
stand still. And yet the Lisps we have today are still pretty much
what they had at MIT in the mid-1980s, because that's the last time
Lisp had a sufficiently large and demanding user base.
Так что, независимо от того, обязан ли язык быть хорошим, чтобы стать популярным, я считаю, что язык обязан быть популярным, чтобы быть хорошим. И он должен оставаться популярным, чтобы оставаться хорошим. Состояние дел в области языков программирования не стоит на месте. И всё же сегодняшние Lisp'ы — это во многом то же самое, что было в MIT в середине 1980-х, потому что это последний раз, когда у Lisp была достаточно большая и требовательная база пользователей.
Of course, hackers have to know about a language before they can
use it. How are they to hear? From other hackers. But there has to
be some initial group of hackers using the language for others even
to hear about it. I wonder how large this group has to be; how many
users make a critical mass? Off the top of my head, I'd say twenty.
If a language had twenty separate users, meaning twenty users who
decided on their own to use it, I'd consider it to be real.
Конечно, хакеры должны узнать о языке, прежде чем смогут им пользоваться. Откуда им узнать? От других хакеров. Но должна быть какая-то начальная группа хакеров, использующих язык, чтобы остальные вообще о нём услышали. Интересно, насколько большой должна быть эта группа; сколько пользователей составляют критическую массу? Навскидку я бы сказал — двадцать. Если бы у языка было двадцать отдельных пользователей, то есть двадцать пользователей, которые сами решили им воспользоваться, я бы счёл его настоящим.
Getting there can't be easy. I would not be surprised if it is
harder to get from zero to twenty than from twenty to a thousand.
The best way to get those initial twenty users is probably to use
a trojan horse: to give people an application they want, which
happens to be written in the new language.
Дойти до этого непросто. Я бы не удивился, если бы оказалось, что от нуля до двадцати труднее, чем от двадцати до тысячи. Лучший способ заполучить эти первые двадцать пользователей — вероятно, использовать троянского коня: дать людям приложение, которое им нужно и которое по случайности написано на новом языке.
2 External Factors
2 Внешние факторы
Let's start by acknowledging one external factor that does affect
the popularity of a programming language. To become popular, a
programming language has to be the scripting language of a popular
system. Fortran and Cobol were the scripting languages of early
IBM mainframes. C was the scripting language of Unix, and so, later,
was Perl. Tcl is the scripting language of Tk. Java and Javascript
are intended to be the scripting languages of web browsers.
Начнём с признания одного внешнего фактора, который действительно влияет на популярность языка программирования. Чтобы стать популярным, язык программирования должен быть скриптовым языком популярной системы. Fortran и Cobol были скриптовыми языками ранних мейнфреймов IBM. C был скриптовым языком Unix, а позже им же стал и Perl. Tcl — скриптовый язык Tk. Java и Javascript задумывались как скриптовые языки веб-браузеров.
Lisp is not a massively popular language because it is not the
scripting language of a massively popular system. What popularity
it retains dates back to the 1960s and 1970s, when it was the
scripting language of MIT. A lot of the great programmers of the
day were associated with MIT at some point. And in the early 1970s,
before C, MIT's dialect of Lisp, called MacLisp, was one of the
only programming languages a serious hacker would want to use.
Lisp не является массово популярным языком, потому что он не является скриптовым языком массово популярной системы. Та популярность, что у него осталась, восходит к 1960-м и 1970-м годам, когда он был скриптовым языком MIT. Многие из великих программистов того времени в какой-то момент были связаны с MIT. И в начале 1970-х, до C, диалект Lisp от MIT, называвшийся MacLisp, был одним из немногих языков программирования, которыми серьёзный хакер вообще захотел бы пользоваться.
Today Lisp is the scripting language of two moderately popular
systems, Emacs and Autocad, and for that reason I suspect that most
of the Lisp programming done today is done in Emacs Lisp or AutoLisp.
Сегодня Lisp — скриптовый язык двух умеренно популярных систем, Emacs и Autocad, и по этой причине я подозреваю, что бóльшая часть программирования на Lisp, которая ведётся сегодня, делается на Emacs Lisp или AutoLisp.
Programming languages don't exist in isolation. To hack is a
transitive verb — hackers are usually hacking something — and in
practice languages are judged relative to whatever they're used to
hack. So if you want to design a popular language, you either have
to supply more than a language, or you have to design your language
to replace the scripting language of some existing system.
Языки программирования не существуют в изоляции. «Хакать» — переходный глагол: хакеры обычно что-то хакают, — и на практике языки оцениваются относительно того, для хака чего они используются. Так что если вы хотите спроектировать популярный язык, вам нужно либо поставлять нечто большее, чем просто язык, либо проектировать свой язык так, чтобы он заменил скриптовый язык какой-нибудь уже существующей системы.
Common Lisp is unpopular partly because it's an orphan. It did
originally come with a system to hack: the Lisp Machine. But Lisp
Machines (along with parallel computers) were steamrollered by the
increasing power of general purpose processors in the 1980s. Common
Lisp might have remained popular if it had been a good scripting
language for Unix. It is, alas, an atrociously bad one.
Common Lisp непопулярен отчасти потому, что он — сирота. Изначально он действительно поставлялся с системой, которую можно было хакать: Lisp Machine. Но Lisp-машины (наряду с параллельными компьютерами) были раздавлены катком растущей мощности процессоров общего назначения в 1980-х. Common Lisp мог бы остаться популярным, если бы он был хорошим скриптовым языком для Unix. Но он, увы, отвратительно плох в этой роли.
One way to describe this situation is to say that a language isn't
judged on its own merits. Another view is that a programming language
really isn't a programming language unless it's also the scripting
language of something. This only seems unfair if it comes as a
surprise. I think it's no more unfair than expecting a programming
language to have, say, an implementation. It's just part of what
a programming language is.
Один из способов описать эту ситуацию — сказать, что язык оценивают не по его собственным достоинствам. Другая точка зрения: язык программирования по-настоящему не является языком программирования, если он не является ещё и скриптовым языком чего-либо. Это кажется несправедливым, только если становится неожиданностью. Я считаю, что это не более несправедливо, чем ожидать от языка программирования наличия, скажем, реализации. Это просто часть того, что вообще такое язык программирования.
A programming language does need a good implementation, of course,
and this must be free. Companies will pay for software, but individual
hackers won't, and it's the hackers you need to attract.
Языку программирования, конечно, нужна хорошая реализация, и она должна быть бесплатной. Компании заплатят за софт, а отдельные хакеры — нет, а ведь именно хакеров вам нужно привлечь.
A language also needs to have a book about it. The book should be
thin, well-written, and full of good examples. K&R is the ideal
here. At the moment I'd almost say that a language has to have a
book published by O'Reilly. That's becoming the test of mattering
to hackers.
Языку также нужна книга о нём. Книга должна быть тонкой, хорошо написанной и полной хороших примеров. K&R — идеал в этом смысле. На данный момент я бы почти сказал, что у языка должна быть книга, изданная O'Reilly. Это становится критерием того, что язык что-то значит для хакеров.
There should be online documentation as well. In fact, the book
can start as online documentation. But I don't think that physical
books are outmoded yet. Their format is convenient, and the de
facto censorship imposed by publishers is a useful if imperfect
filter. Bookstores are one of the most important places for learning
about new languages.
Должна быть и онлайн-документация. Собственно, книга может начаться как онлайн-документация. Но я не думаю, что бумажные книги уже устарели. Их формат удобен, а фактическая цензура, налагаемая издателями, — полезный, пусть и несовершенный фильтр. Книжные магазины — одно из важнейших мест, где узнают о новых языках.
3 Brevity
3 Краткость
Given that you can supply the three things any language needs — a
free implementation, a book, and something to hack — how do you
make a language that hackers will like?
Учитывая, что вы можете обеспечить три вещи, нужные любому языку, — бесплатную реализацию, книгу и нечто, что можно хакать, — как сделать язык, который понравится хакерам?
One thing hackers like is brevity. Hackers are lazy, in the same
way that mathematicians and modernist architects are lazy: they
hate anything extraneous. It would not be far from the truth to
say that a hacker about to write a program decides what language
to use, at least subconsciously, based on the total number of
characters he'll have to type. If this isn't precisely how hackers
think, a language designer would do well to act as if it were.
Одна из вещей, которую любят хакеры, — краткость. Хакеры ленивы — в том же смысле, в каком ленивы математики и архитекторы-модернисты: они ненавидят всё лишнее. Будет недалеко от истины сказать, что хакер, собираясь писать программу, решает, каким языком воспользоваться, — по крайней мере, подсознательно, — исходя из общего числа символов, которые ему придётся набрать. Если хакеры мыслят и не совсем так, то проектировщику языка имело бы смысл действовать так, как будто это правда.
It is a mistake to try to baby the user with long-winded expressions
that are meant to resemble English. Cobol is notorious for this
flaw. A hacker would consider being asked to write
Это ошибка — нянчиться с пользователем, подсовывая ему многословные выражения, призванные напоминать английский язык. Cobol печально известен этим недостатком. Хакер счёл бы просьбу написать
add x to y giving z
add x to y giving z
instead of
вместо
z = x+y
z = x+y
as something between an insult to his intelligence and a sin against
God.
чем-то средним между оскорблением его интеллекта и грехом против Бога.
It has sometimes been said that Lisp should use first and rest
instead of car and cdr, because it would make programs easier to
read. Maybe for the first couple hours. But a hacker can learn
quickly enough that car means the first element of a list and cdr
means the rest. Using first and rest means 50% more typing. And
they are also different lengths, meaning that the arguments won't
line up when they're called, as car and cdr often are, in successive
lines. I've found that it matters a lot how code lines up on the
page. I can barely read Lisp code when it is set in a variable-width
font, and friends say this is true for other languages too.
Иногда говорят, что Lisp следовало бы использовать first и rest вместо car и cdr, потому что это сделало бы программы легче для чтения. Может, в течение первых пары часов. Но хакер достаточно быстро выучивает, что car означает первый элемент списка, а cdr — остаток. Использование first и rest означает на 50% больше набора текста. К тому же они разной длины, а значит, аргументы не будут выравниваться, когда они вызываются — как часто бывает с car и cdr — в идущих подряд строках. Я обнаружил, что то, как код выравнивается на странице, имеет большое значение. Я едва могу читать код на Lisp, когда он набран моноширинным… то есть шрифтом переменной ширины, и друзья говорят, что это верно и для других языков.
Brevity is one place where strongly typed languages lose. All other
things being equal, no one wants to begin a program with a bunch
of declarations. Anything that can be implicit, should be.
Краткость — одно из мест, где строго типизированные языки проигрывают. При прочих равных никто не хочет начинать программу с кучи объявлений. Всё, что может быть неявным, должно быть неявным.
The individual tokens should be short as well. Perl and Common Lisp
occupy opposite poles on this question. Perl programs can be almost
cryptically dense, while the names of built-in Common Lisp operators
are comically long. The designers of Common Lisp probably expected
users to have text editors that would type these long names for
them. But the cost of a long name is not just the cost of typing
it. There is also the cost of reading it, and the cost of the space
it takes up on your screen.
Отдельные токены тоже должны быть короткими. Perl и Common Lisp занимают противоположные полюса в этом вопросе. Программы на Perl бывают почти криптически плотными, тогда как имена встроенных операторов Common Lisp комично длинны. Проектировщики Common Lisp, вероятно, рассчитывали, что у пользователей будут текстовые редакторы, которые будут набирать эти длинные имена за них. Но цена длинного имени — это не только цена его набора. Есть ещё цена его чтения и цена места, которое оно занимает на экране.
4 Hackability
4 Хакабельность
There is one thing more important than brevity to a hacker: being
able to do what you want. In the history of programming languages
a surprising amount of effort has gone into preventing programmers
from doing things considered to be improper. This is a dangerously
presumptuous plan. How can the language designer know what the
programmer is going to need to do? I think language designers would
do better to consider their target user to be a genius who will
need to do things they never anticipated, rather than a bumbler
who needs to be protected from himself. The bumbler will shoot
himself in the foot anyway. You may save him from referring to
variables in another package, but you can't save him from writing
a badly designed program to solve the wrong problem, and taking
forever to do it.
Есть одна вещь, более важная для хакера, чем краткость: возможность делать то, что хочешь. В истории языков программирования удивительно много усилий было потрачено на то, чтобы помешать программистам делать вещи, считающиеся неподобающими. Это опасно самонадеянный замысел. Откуда проектировщику языка знать, что программисту понадобится сделать? Я думаю, проектировщикам языков было бы лучше считать своего целевого пользователя гением, которому понадобится делать вещи, каких они никогда не предвидели, а не растяпой, которого нужно защищать от самого себя. Растяпа всё равно прострелит себе ногу. Вы можете уберечь его от обращения к переменным в другом пакете, но не убережёте от написания плохо спроектированной программы, решающей не ту задачу, да ещё и бесконечно долго.
Good programmers often want to do dangerous and unsavory things.
By unsavory I mean things that go behind whatever semantic facade
the language is trying to present: getting hold of the internal
representation of some high-level abstraction, for example. Hackers
like to hack, and hacking means getting inside things and second
guessing the original designer.
Хорошие программисты часто хотят делать опасные и неблаговидные вещи. Под неблаговидными я подразумеваю вещи, которые заходят за тот семантический фасад, что пытается представить язык: например, добраться до внутреннего представления какой-нибудь высокоуровневой абстракции. Хакеры любят хакать, а хакать — значит залезать внутрь вещей и переигрывать замысел исходного проектировщика.
Let yourself be second guessed. When you make any tool, people use
it in ways you didn't intend, and this is especially true of a
highly articulated tool like a programming language. Many a hacker
will want to tweak your semantic model in a way that you never
imagined. I say, let them; give the programmer access to as much
internal stuff as you can without endangering runtime systems like
the garbage collector.
Позвольте себя переиграть. Когда вы создаёте любой инструмент, люди используют его не так, как вы задумывали, и это особенно верно для столь тонко устроенного инструмента, как язык программирования. Не один хакер захочет подкрутить вашу семантическую модель способом, какого вы и вообразить не могли. Я говорю: пусть подкручивают; дайте программисту доступ к как можно бóльшему количеству внутренностей, не подвергая опасности системы времени исполнения вроде сборщика мусора.
In Common Lisp I have often wanted to iterate through the fields
of a struct — to comb out references to a deleted object, for example,
or find fields that are uninitialized. I know the structs are just
vectors underneath. And yet I can't write a general purpose function
that I can call on any struct. I can only access the fields by
name, because that's what a struct is supposed to mean.
В Common Lisp я часто хотел пройтись по полям структуры — например, чтобы вычистить ссылки на удалённый объект или найти неинициализированные поля. Я знаю, что под капотом структуры — это просто векторы. И всё же я не могу написать функцию общего назначения, которую мог бы вызвать на любой структуре. Я могу обращаться к полям только по имени, потому что именно это структура и должна означать.
A hacker may only want to subvert the intended model of things once
or twice in a big program. But what a difference it makes to be
able to. And it may be more than a question of just solving a
problem. There is a kind of pleasure here too. Hackers share the
surgeon's secret pleasure in poking about in gross innards, the
teenager's secret pleasure in popping zits. [2] For boys, at least,
certain kinds of horrors are fascinating. Maxim magazine publishes
an annual volume of photographs, containing a mix of pin-ups and
grisly accidents. They know their audience.
Хакер, возможно, захочет подорвать задуманную модель вещей лишь раз или два за всю большую программу. Но какая же это разница — иметь такую возможность. И дело может быть не просто в решении задачи. Здесь есть ещё и своего рода удовольствие. Хакеры разделяют тайное удовольствие хирурга копаться в неприглядных внутренностях, тайное удовольствие подростка давить прыщи. [2] Для мальчишек, по крайней мере, определённого рода ужасы завораживают. Журнал Maxim ежегодно выпускает том фотографий, содержащий смесь пин-апа и жутких аварий. Они знают свою аудиторию.
Historically, Lisp has been good at letting hackers have their way.
The political correctness of Common Lisp is an aberration. Early
Lisps let you get your hands on everything. A good deal of that
spirit is, fortunately, preserved in macros. What a wonderful thing,
to be able to make arbitrary transformations on the source code.
Исторически Lisp хорошо умел давать хакерам делать по-своему. Политкорректность Common Lisp — это аберрация. Ранние Lisp'ы позволяли добраться до всего. Изрядная доля того духа, к счастью, сохранилась в макросах. Какая чудесная вещь — иметь возможность производить произвольные преобразования над исходным кодом.
Classic macros are a real hacker's tool — simple, powerful, and
dangerous. It's so easy to understand what they do: you call a
function on the macro's arguments, and whatever it returns gets
inserted in place of the macro call. Hygienic macros embody the
opposite principle. They try to protect you from understanding what
they're doing. I have never heard hygienic macros explained in one
sentence. And they are a classic example of the dangers of deciding
what programmers are allowed to want. Hygienic macros are intended
to protect me from variable capture, among other things, but variable
capture is exactly what I want in some macros.
Классические макросы — настоящий хакерский инструмент: простой, мощный и опасный. Так легко понять, что они делают: вы вызываете функцию на аргументах макроса, и то, что она возвращает, вставляется на место вызова макроса. Гигиенические макросы воплощают противоположный принцип. Они пытаются защитить вас от понимания того, что делают. Я никогда не слышал, чтобы гигиенические макросы объяснили одним предложением. И они — классический пример опасности решать за программистов, что им позволено хотеть. Гигиенические макросы призваны, среди прочего, защищать меня от захвата переменных, но захват переменных — это как раз то, чего я хочу в некоторых макросах.
A really good language should be both clean and dirty: cleanly
designed, with a small core of well understood and highly orthogonal
operators, but dirty in the sense that it lets hackers have their
way with it. C is like this. So were the early Lisps. A real hacker's
language will always have a slightly raffish character.
По-настоящему хороший язык должен быть одновременно и чистым, и грязным: чисто спроектированным, с небольшим ядром из хорошо понятных и в высшей степени ортогональных операторов, но грязным в том смысле, что он позволяет хакерам делать с ним что им угодно. C таков. Таковы были и ранние Lisp'ы. У настоящего хакерского языка всегда будет слегка беспутный характер.
A good programming language should have features that make the kind
of people who use the phrase "software engineering" shake their
heads disapprovingly. At the other end of the continuum are languages
like Ada and Pascal, models of propriety that are good for teaching
and not much else.
У хорошего языка программирования должны быть черты, заставляющие людей, употребляющих выражение «программная инженерия», неодобрительно качать головой. На другом конце спектра — языки вроде Ada и Pascal, образцы благопристойности, годные для обучения и мало для чего ещё.
5 Throwaway Programs
5 Одноразовые программы
To be attractive to hackers, a language must be good for writing
the kinds of programs they want to write. And that means, perhaps
surprisingly, that it has to be good for writing throwaway programs.
Чтобы быть привлекательным для хакеров, язык должен хорошо подходить для написания тех программ, какие они хотят писать. А это означает — возможно, неожиданно — что он должен хорошо подходить для написания одноразовых программ.
A throwaway program is a program you write quickly for some limited
task: a program to automate some system administration task, or
generate test data for a simulation, or convert data from one format
to another. The surprising thing about throwaway programs is that,
like the "temporary" buildings built at so many American universities
during World War II, they often don't get thrown away. Many evolve
into real programs, with real features and real users.
Одноразовая программа — это программа, которую вы быстро пишете для какой-то ограниченной задачи: программа, чтобы автоматизировать какую-нибудь задачу системного администрирования, или сгенерировать тестовые данные для симуляции, или преобразовать данные из одного формата в другой. Удивительная вещь в одноразовых программах в том, что, подобно «временным» зданиям, построенным во многих американских университетах во время Второй мировой войны, их часто так и не выбрасывают. Многие превращаются в настоящие программы, с настоящими функциями и настоящими пользователями.
I have a hunch that the best big programs begin life this way,
rather than being designed big from the start, like the Hoover Dam.
It's terrifying to build something big from scratch. When people
take on a project that's too big, they become overwhelmed. The
project either gets bogged down, or the result is sterile and
wooden: a shopping mall rather than a real downtown, Brasilia rather
than Rome, Ada rather than C.
У меня есть догадка, что лучшие большие программы рождаются именно так, а не проектируются большими с самого начала, как плотина Гувера. Строить нечто большое с нуля — страшно. Когда люди берутся за слишком большой проект, их захлёстывает. Проект либо вязнет, либо результат выходит стерильным и деревянным: торговый центр вместо настоящего центра города, Бразилиа вместо Рима, Ada вместо C.
Another way to get a big program is to start with a throwaway
program and keep improving it. This approach is less daunting, and
the design of the program benefits from evolution. I think, if one
looked, that this would turn out to be the way most big programs
were developed. And those that did evolve this way are probably
still written in whatever language they were first written in,
because it's rare for a program to be ported, except for political
reasons. And so, paradoxically, if you want to make a language that
is used for big systems, you have to make it good for writing
throwaway programs, because that's where big systems come from.
Другой способ получить большую программу — начать с одноразовой программы и продолжать её улучшать. Этот подход менее устрашающ, и дизайн программы выигрывает от эволюции. Я думаю, если бы кто-то присмотрелся, оказалось бы, что именно так разрабатывалось большинство больших программ. И те, что эволюционировали таким образом, вероятно, до сих пор написаны на том языке, на котором их написали впервые, потому что программу редко портируют — разве что по политическим причинам. И вот, парадоксальным образом, если вы хотите сделать язык, используемый для больших систем, вам нужно сделать его хорошим для написания одноразовых программ, потому что именно оттуда большие системы и берутся.
Perl is a striking example of this idea. It was not only designed
for writing throwaway programs, but was pretty much a throwaway
program itself. Perl began life as a collection of utilities for
generating reports, and only evolved into a programming language
as the throwaway programs people wrote in it grew larger. It was
not until Perl 5 (if then) that the language was suitable for
writing serious programs, and yet it was already massively popular.
Perl — яркий пример этой идеи. Он был не только спроектирован для написания одноразовых программ, но и сам по сути был одноразовой программой. Perl начал жизнь как набор утилит для генерации отчётов и превратился в язык программирования лишь по мере того, как одноразовые программы, которые на нём писали люди, становились всё больше. Лишь к версии Perl 5 (если вообще к ней) язык стал пригоден для написания серьёзных программ, и всё же он уже был массово популярен.
What makes a language good for throwaway programs? To start with,
it must be readily available. A throwaway program is something that
you expect to write in an hour. So the language probably must
already be installed on the computer you're using. It can't be
something you have to install before you use it. It has to be there.
C was there because it came with the operating system. Perl was
there because it was originally a tool for system administrators,
and yours had already installed it.
Что делает язык хорошим для одноразовых программ? Для начала он должен быть легко доступен. Одноразовая программа — это то, что вы рассчитываете написать за час. Так что язык, вероятно, должен быть уже установлен на компьютере, которым вы пользуетесь. Это не может быть нечто, что вам приходится устанавливать перед использованием. Оно должно быть прямо тут. C был тут, потому что поставлялся вместе с операционной системой. Perl был тут, потому что изначально был инструментом для системных администраторов, и ваш админ уже его установил.
Being available means more than being installed, though. An
interactive language, with a command-line interface, is more
available than one that you have to compile and run separately. A
popular programming language should be interactive, and start up
fast.
Впрочем, быть доступным — это больше, чем быть установленным. Интерактивный язык с интерфейсом командной строки доступнее, чем тот, который нужно компилировать и запускать отдельно. Популярный язык программирования должен быть интерактивным и быстро запускаться.
Another thing you want in a throwaway program is brevity. Brevity
is always attractive to hackers, and never more so than in a program
they expect to turn out in an hour.
Ещё одна вещь, которую вы хотите видеть в одноразовой программе, — краткость. Краткость всегда привлекательна для хакеров, и никогда более, чем в программе, которую они рассчитывают выдать за час.
6 Libraries
6 Библиотеки
Of course the ultimate in brevity is to have the program already
written for you, and merely to call it. And this brings us to what
I think will be an increasingly important feature of programming
languages: library functions. Perl wins because it has large
libraries for manipulating strings. This class of library functions
are especially important for throwaway programs, which are often
originally written for converting or extracting data. Many Perl
programs probably begin as just a couple library calls stuck
together.
Конечно, предел краткости — это когда программа уже написана за вас, и вам остаётся лишь её вызвать. И это подводит нас к тому, что, как я думаю, станет всё более важной чертой языков программирования: библиотечным функциям. Perl выигрывает, потому что у него есть большие библиотеки для работы со строками. Этот класс библиотечных функций особенно важен для одноразовых программ, которые часто изначально пишутся для преобразования или извлечения данных. Многие программы на Perl, вероятно, начинаются просто как пара склеенных вместе библиотечных вызовов.
I think a lot of the advances that happen in programming languages
in the next fifty years will have to do with library functions. I
think future programming languages will have libraries that are as
carefully designed as the core language. Programming language design
will not be about whether to make your language strongly or weakly
typed, or object oriented, or functional, or whatever, but about
how to design great libraries. The kind of language designers who
like to think about how to design type systems may shudder at this.
It's almost like writing applications! Too bad. Languages are for
programmers, and libraries are what programmers need.
Я думаю, что многие достижения, которые произойдут в языках программирования в ближайшие пятьдесят лет, будут связаны с библиотечными функциями. Я думаю, у будущих языков программирования будут библиотеки, спроектированные так же тщательно, как и само ядро языка. Проектирование языков программирования будет не о том, делать ли язык строго или слабо типизированным, объектно-ориентированным, функциональным или ещё каким-нибудь, а о том, как проектировать великолепные библиотеки. Те проектировщики языков, что любят размышлять о том, как проектировать системы типов, могут содрогнуться от этого. Это же почти как писать приложения! Очень жаль. Языки существуют для программистов, а библиотеки — это то, что программистам нужно.
It's hard to design good libraries. It's not simply a matter of
writing a lot of code. Once the libraries get too big, it can
sometimes take longer to find the function you need than to write
the code yourself. Libraries need to be designed using a small set
of orthogonal operators, just like the core language. It ought to
be possible for the programmer to guess what library call will do
what he needs.
Проектировать хорошие библиотеки трудно. Дело не просто в написании кучи кода. Когда библиотеки становятся слишком большими, иногда найти нужную функцию может занять больше времени, чем написать код самому. Библиотеки нужно проектировать на основе небольшого набора ортогональных операторов, точно так же, как и само ядро языка. У программиста должна быть возможность угадать, какой библиотечный вызов сделает то, что ему нужно.
Libraries are one place Common Lisp falls short. There are only
rudimentary libraries for manipulating strings, and almost none
for talking to the operating system. For historical reasons, Common
Lisp tries to pretend that the OS doesn't exist. And because you
can't talk to the OS, you're unlikely to be able to write a serious
program using only the built-in operators in Common Lisp. You have
to use some implementation-specific hacks as well, and in practice
these tend not to give you everything you want. Hackers would think
a lot more highly of Lisp if Common Lisp had powerful string
libraries and good OS support.
Библиотеки — одно из мест, где Common Lisp не дотягивает. Есть лишь рудиментарные библиотеки для работы со строками и почти никаких для взаимодействия с операционной системой. По историческим причинам Common Lisp пытается делать вид, что ОС не существует. А поскольку вы не можете общаться с ОС, вы вряд ли сможете написать серьёзную программу, используя только встроенные операторы Common Lisp. Вам придётся прибегать ещё и к специфичным для реализации хакам, а на практике они, как правило, не дают вам всего, что нужно. Хакеры были бы куда более высокого мнения о Lisp, если бы у Common Lisp были мощные строковые библиотеки и хорошая поддержка ОС.
7 Syntax
7 Синтаксис
Could a language with Lisp's syntax, or more precisely, lack of
syntax, ever become popular? I don't know the answer to this
question. I do think that syntax is not the main reason Lisp isn't
currently popular. Common Lisp has worse problems than unfamiliar
syntax. I know several programmers who are comfortable with prefix
syntax and yet use Perl by default, because it has powerful string
libraries and can talk to the os.
Мог бы язык с синтаксисом Lisp — или, точнее, с его отсутствием синтаксиса — когда-нибудь стать популярным? Я не знаю ответа на этот вопрос. Я считаю, что синтаксис — не главная причина того, что Lisp сейчас непопулярен. У Common Lisp есть проблемы похуже непривычного синтаксиса. Я знаю несколько программистов, которым комфортно с префиксным синтаксисом, и которые всё же по умолчанию пользуются Perl, потому что у него мощные строковые библиотеки и он может общаться с ОС.
There are two possible problems with prefix notation: that it is
unfamiliar to programmers, and that it is not dense enough. The
conventional wisdom in the Lisp world is that the first problem is
the real one. I'm not so sure. Yes, prefix notation makes ordinary
programmers panic. But I don't think ordinary programmers' opinions
matter. Languages become popular or unpopular based on what expert
hackers think of them, and I think expert hackers might be able to
deal with prefix notation. Perl syntax can be pretty incomprehensible,
but that has not stood in the way of Perl's popularity. If anything
it may have helped foster a Perl cult.
С префиксной нотацией есть две возможные проблемы: что она непривычна программистам и что она недостаточно плотна. Общепринятое мнение в мире Lisp состоит в том, что первая проблема — настоящая. Я не так уверен. Да, префиксная нотация заставляет обычных программистов паниковать. Но я не думаю, что мнения обычных программистов имеют значение. Языки становятся популярными или непопулярными в зависимости от того, что о них думают хакеры-эксперты, а я думаю, хакеры-эксперты, пожалуй, способны справиться с префиксной нотацией. Синтаксис Perl бывает довольно непостижимым, но это не встало на пути популярности Perl. Если что, это, возможно, помогло взрастить культ Perl.
A more serious problem is the diffuseness of prefix notation. For
expert hackers, that really is a problem. No one wants to write
(aref a x y) when they could write a[x,y].
Более серьёзная проблема — расплывчатость префиксной нотации. Для хакеров-экспертов это действительно проблема. Никто не хочет писать (aref a x y), когда можно написать a[x,y].
In this particular case there is a way to finesse our way out of
the problem. If we treat data structures as if they were functions
on indexes, we could write (a x y) instead, which is even shorter
than the Perl form. Similar tricks may shorten other types of
expressions.
В этом конкретном случае есть способ ловко выкрутиться из проблемы. Если мы будем трактовать структуры данных так, словно они — функции от индексов, мы могли бы писать вместо этого (a x y), что даже короче формы Perl. Похожие трюки могут укоротить и другие типы выражений.
We can get rid of (or make optional) a lot of parentheses by making
indentation significant. That's how programmers read code anyway:
when indentation says one thing and delimiters say another, we go
by the indentation. Treating indentation as significant would
eliminate this common source of bugs as well as making programs
shorter.
Мы можем избавиться от множества скобок (или сделать их необязательными), сделав отступы значимыми. Программисты всё равно так читают код: когда отступы говорят одно, а разделители — другое, мы ориентируемся на отступы. Трактовка отступов как значимых устранила бы этот распространённый источник багов, а заодно сделала бы программы короче.
Sometimes infix syntax is easier to read. This is especially true
for math expressions. I've used Lisp my whole programming life and
I still don't find prefix math expressions natural. And yet it is
convenient, especially when you're generating code, to have operators
that take any number of arguments. So if we do have infix syntax,
it should probably be implemented as some kind of read-macro.
Иногда инфиксный синтаксис легче читать. Это особенно верно для математических выражений. Я пользуюсь Lisp всю свою жизнь программиста и всё равно не нахожу префиксные математические выражения естественными. И всё же удобно, особенно когда вы генерируете код, иметь операторы, принимающие любое число аргументов. Так что если у нас и будет инфиксный синтаксис, его, вероятно, следует реализовать как некий read-макрос.
I don't think we should be religiously opposed to introducing syntax
into Lisp, as long as it translates in a well-understood way into
underlying s-expressions. There is already a good deal of syntax
in Lisp. It's not necessarily bad to introduce more, as long as no
one is forced to use it. In Common Lisp, some delimiters are reserved
for the language, suggesting that at least some of the designers
intended to have more syntax in the future.
Я не думаю, что мы должны быть религиозно настроены против введения синтаксиса в Lisp — до тех пор, пока он понятным образом транслируется в лежащие в основе s-выражения. В Lisp уже есть изрядное количество синтаксиса. Введение ещё немного — не обязательно плохо, пока никого не заставляют им пользоваться. В Common Lisp некоторые разделители зарезервированы за языком, что наводит на мысль, что хотя бы часть проектировщиков намеревалась добавить больше синтаксиса в будущем.
One of the most egregiously unlispy pieces of syntax in Common Lisp
occurs in format strings; format is a language in its own right,
and that language is not Lisp. If there were a plan for introducing
more syntax into Lisp, format specifiers might be able to be included
in it. It would be a good thing if macros could generate format
specifiers the way they generate any other kind of code.
Один из самых вопиюще нелисповых кусков синтаксиса в Common Lisp встречается в строках формата; format — это сам по себе язык, и этот язык — не Lisp. Если бы существовал план по введению большего синтаксиса в Lisp, спецификаторы format можно было бы в него включить. Было бы хорошо, если бы макросы могли генерировать спецификаторы format так же, как они генерируют любой другой код.
An eminent Lisp hacker told me that his copy of CLTL falls open to
the section format. Mine too. This probably indicates room for
improvement. It may also mean that programs do a lot of I/O.
Один видный хакер Lisp сказал мне, что его экземпляр CLTL раскрывается на разделе format. У меня тоже. Это, вероятно, указывает на пространство для улучшений. Это также может означать, что программы делают много ввода-вывода.
8 Efficiency
8 Эффективность
A good language, as everyone knows, should generate fast code. But
in practice I don't think fast code comes primarily from things
you do in the design of the language. As Knuth pointed out long
ago, speed only matters in certain critical bottlenecks. And as
many programmers have observed since, one is very often mistaken
about where these bottlenecks are.
Хороший язык, как всем известно, должен генерировать быстрый код. Но на практике я не думаю, что быстрый код берётся в первую очередь из того, что вы делаете при проектировании языка. Как давным-давно указал Knuth, скорость имеет значение лишь в определённых критических узких местах. И, как с тех пор замечали многие программисты, очень часто ошибаешься в том, где эти узкие места.
So, in practice, the way to get fast code is to have a very good
profiler, rather than by, say, making the language strongly typed.
You don't need to know the type of every argument in every call in
the program. You do need to be able to declare the types of arguments
in the bottlenecks. And even more, you need to be able to find out
where the bottlenecks are.
Так что на практике способ получить быстрый код — иметь очень хороший профайлер, а не, скажем, делать язык строго типизированным. Вам не нужно знать тип каждого аргумента в каждом вызове в программе. Вам нужно иметь возможность объявлять типы аргументов в узких местах. И, что ещё важнее, вам нужно иметь возможность узнать, где эти узкие места.
One complaint people have had with Lisp is that it's hard to tell
what's expensive. This might be true. It might also be inevitable,
if you want to have a very abstract language. And in any case I
think good profiling would go a long way toward fixing the problem:
you'd soon learn what was expensive.
Одна из претензий к Lisp состоит в том, что трудно понять, что обходится дорого. Это, возможно, правда. Это, возможно, также неизбежно, если вы хотите иметь очень абстрактный язык. И в любом случае я думаю, что хорошее профилирование сильно продвинуло бы решение этой проблемы: вы бы быстро узнали, что обходится дорого.
Part of the problem here is social. Language designers like to
write fast compilers. That's how they measure their skill. They
think of the profiler as an add-on, at best. But in practice a good
profiler may do more to improve the speed of actual programs written
in the language than a compiler that generates fast code. Here,
again, language designers are somewhat out of touch with their
users. They do a really good job of solving slightly the wrong
problem.
Часть проблемы здесь — социальная. Проектировщики языков любят писать быстрые компиляторы. Именно так они меряют своё мастерство. Профайлер они считают, в лучшем случае, дополнением. Но на практике хороший профайлер может сделать для скорости реальных программ, написанных на языке, больше, чем компилятор, генерирующий быстрый код. Здесь, опять же, проектировщики языков несколько оторваны от своих пользователей. Они действительно хорошо решают слегка не ту задачу.
It might be a good idea to have an active profiler — to push
performance data to the programmer instead of waiting for him to
come asking for it. For example, the editor could display bottlenecks
in red when the programmer edits the source code. Another approach
would be to somehow represent what's happening in running programs.
This would be an especially big win in server-based applications,
where you have lots of running programs to look at. An active
profiler could show graphically what's happening in memory as a
program's running, or even make sounds that tell what's happening.
Возможно, была бы хорошая идея иметь активный профайлер — проталкивать данные о производительности программисту, а не ждать, пока он сам придёт за ними. Например, редактор мог бы подсвечивать узкие места красным, когда программист редактирует исходный код. Другой подход — как-то представлять, что происходит в работающих программах. Это был бы особенно большой выигрыш в серверных приложениях, где у вас есть множество работающих программ для наблюдения. Активный профайлер мог бы графически показывать, что происходит в памяти по мере работы программы, или даже издавать звуки, сообщающие, что происходит.
Sound is a good cue to problems. In one place I worked, we had a
big board of dials showing what was happening to our web servers.
The hands were moved by little servomotors that made a slight noise
when they turned. I couldn't see the board from my desk, but I
found that I could tell immediately, by the sound, when there was
a problem with a server.
Звук — хорошая подсказка о проблемах. В одном месте, где я работал, у нас была большая панель циферблатов, показывающая, что происходит с нашими веб-серверами. Стрелки двигались маленькими сервомоторами, которые издавали лёгкий шум, когда поворачивались. Я не мог видеть панель со своего стола, но обнаружил, что по звуку могу сразу понять, когда с сервером возникала проблема.
It might even be possible to write a profiler that would automatically
detect inefficient algorithms. I would not be surprised if certain
patterns of memory access turned out to be sure signs of bad
algorithms. If there were a little guy running around inside the
computer executing our programs, he would probably have as long
and plaintive a tale to tell about his job as a federal government
employee. I often have a feeling that I'm sending the processor on
a lot of wild goose chases, but I've never had a good way to look
at what it's doing.
Возможно, удалось бы даже написать профайлер, который автоматически выявлял бы неэффективные алгоритмы. Я бы не удивился, если бы определённые паттерны обращения к памяти оказались верными признаками плохих алгоритмов. Если бы внутри компьютера бегал маленький человечек, исполняющий наши программы, у него, вероятно, нашлась бы такая же длинная и жалобная повесть о своей работе, как у служащего федерального правительства. У меня часто бывает ощущение, что я отправляю процессор в кучу погонь за дикими гусями, но у меня никогда не было хорошего способа посмотреть, чем он занимается.
A number of Lisps now compile into byte code, which is then executed
by an interpreter. This is usually done to make the implementation
easier to port, but it could be a useful language feature. It might
be a good idea to make the byte code an official part of the
language, and to allow programmers to use inline byte code in
bottlenecks. Then such optimizations would be portable too.
Ряд Lisp'ов теперь компилируется в байт-код, который затем исполняется интерпретатором. Обычно это делается, чтобы облегчить портирование реализации, но это могло бы быть полезной чертой языка. Возможно, была бы хорошая идея сделать байт-код официальной частью языка и позволить программистам использовать встроенный (inline) байт-код в узких местах. Тогда такие оптимизации тоже были бы переносимыми.
The nature of speed, as perceived by the end-user, may be changing.
With the rise of server-based applications, more and more programs
may turn out to be i/o-bound. It will be worth making i/o fast.
The language can help with straightforward measures like simple,
fast, formatted output functions, and also with deep structural
changes like caching and persistent objects.
Природа скорости, как её воспринимает конечный пользователь, может меняться. С ростом серверных приложений всё больше и больше программ могут оказаться ограничены по вводу-выводу (i/o-bound). Стоит делать ввод-вывод быстрым. Язык может помочь как простыми мерами вроде простых, быстрых функций форматированного вывода, так и глубокими структурными изменениями вроде кэширования и устойчивых (persistent) объектов.
Users are interested in response time. But another kind of efficiency
will be increasingly important: the number of simultaneous users
you can support per processor. Many of the interesting applications
written in the near future will be server-based, and the number of
users per server is the critical question for anyone hosting such
applications. In the capital cost of a business offering a server-based
application, this is the divisor.
Пользователей интересует время отклика. Но другой вид эффективности будет приобретать всё большее значение: число одновременных пользователей, которое вы можете обслуживать на один процессор. Многие из интересных приложений, которые будут написаны в ближайшем будущем, будут серверными, и число пользователей на сервер — критический вопрос для всякого, кто хостит такие приложения. В капитальных затратах бизнеса, предлагающего серверное приложение, это знаменатель.
For years, efficiency hasn't mattered much in most end-user
applications. Developers have been able to assume that each user
would have an increasingly powerful processor sitting on their
desk. And by Parkinson's Law, software has expanded to use the
resources available. That will change with server-based applications.
In that world, the hardware and software will be supplied together.
For companies that offer server-based applications, it will make
a very big difference to the bottom line how many users they can
support per server.
Годами эффективность мало что значила в большинстве пользовательских приложений. Разработчики могли исходить из того, что у каждого пользователя на столе будет всё более мощный процессор. И по закону Паркинсона софт раздувался, чтобы использовать доступные ресурсы. С серверными приложениями это изменится. В этом мире железо и софт будут поставляться вместе. Для компаний, предлагающих серверные приложения, очень большая разница для итоговой прибыли — сколько пользователей они смогут обслуживать на один сервер.
In some applications, the processor will be the limiting factor,
and execution speed will be the most important thing to optimize.
But often memory will be the limit; the number of simultaneous
users will be determined by the amount of memory you need for each
user's data. The language can help here too. Good support for
threads will enable all the users to share a single heap. It may
also help to have persistent objects and/or language level support
for lazy loading.
В некоторых приложениях ограничивающим фактором будет процессор, и скорость выполнения будет самой важной вещью для оптимизации. Но часто пределом будет память; число одновременных пользователей будет определяться объёмом памяти, нужным под данные каждого пользователя. Язык может помочь и здесь. Хорошая поддержка потоков позволит всем пользователям делить одну кучу (heap). Также может помочь наличие устойчивых объектов и/или поддержки ленивой загрузки на уровне языка.
9 Time
9 Время
The last ingredient a popular language needs is time. No one wants
to write programs in a language that might go away, as so many
programming languages do. So most hackers will tend to wait until
a language has been around for a couple years before even considering
using it.
Последний ингредиент, нужный популярному языку, — время. Никто не хочет писать программы на языке, который может исчезнуть, как исчезает столь много языков программирования. Так что большинство хакеров склонны выжидать, пока язык не просуществует пару лет, прежде чем хотя бы задуматься о том, чтобы им воспользоваться.
Inventors of wonderful new things are often surprised to discover
this, but you need time to get any message through to people. A
friend of mine rarely does anything the first time someone asks
him. He knows that people sometimes ask for things that they turn
out not to want. To avoid wasting his time, he waits till the third
or fourth time he's asked to do something; by then, whoever's asking
him may be fairly annoyed, but at least they probably really do
want whatever they're asking for.
Изобретатели чудесных новых вещей часто с удивлением обнаруживают это, но вам нужно время, чтобы донести любую мысль до людей. Один мой друг редко делает что-либо, когда его просят в первый раз. Он знает, что люди иногда просят о том, чего, как потом выясняется, на самом деле не хотят. Чтобы не тратить своё время впустую, он ждёт до третьего или четвёртого раза, когда его о чём-то попросят; к тому времени тот, кто просит, может быть изрядно раздражён, но зато он, вероятно, действительно хочет того, о чём просит.
Most people have learned to do a similar sort of filtering on new
things they hear about. They don't even start paying attention
until they've heard about something ten times. They're perfectly
justified: the majority of hot new whatevers do turn out to be a
waste of time, and eventually go away. By delaying learning VRML,
I avoided having to learn it at all.
Большинство людей научились применять похожего рода фильтрацию к новым вещам, о которых слышат. Они даже не начинают обращать внимание, пока не услышат о чём-то раз десять. И они совершенно правы: большинство модных новых «чего бы то ни было» действительно оказываются пустой тратой времени и со временем исчезают. Откладывая изучение VRML, я избежал того, чтобы вообще его изучать.
So anyone who invents something new has to expect to keep repeating
their message for years before people will start to get it. We
wrote what was, as far as I know, the first web-server based
application, and it took us years to get it through to people that
it didn't have to be downloaded. It wasn't that they were stupid.
They just had us tuned out.
Так что всякий, кто изобретает что-то новое, должен ожидать, что ему придётся повторять своё сообщение годами, прежде чем люди начнут его понимать. Мы написали то, что, насколько мне известно, было первым серверным веб-приложением, и нам потребовались годы, чтобы донести до людей, что его не нужно скачивать. Дело не в том, что они были глупы. Они просто пропускали нас мимо ушей.
The good news is, simple repetition solves the problem. All you
have to do is keep telling your story, and eventually people will
start to hear. It's not when people notice you're there that they
pay attention; it's when they notice you're still there.
Хорошая новость в том, что простое повторение решает проблему. Всё, что вам нужно, — продолжать рассказывать свою историю, и в конце концов люди начнут слышать. Внимание обращают не тогда, когда замечают, что ты здесь; а тогда, когда замечают, что ты всё ещё здесь.
It's just as well that it usually takes a while to gain momentum.
Most technologies evolve a good deal even after they're first
launched — programming languages especially. Nothing could be better,
for a new techology, than a few years of being used only by a small
number of early adopters. Early adopters are sophisticated and
demanding, and quickly flush out whatever flaws remain in your
technology. When you only have a few users you can be in close
contact with all of them. And early adopters are forgiving when
you improve your system, even if this causes some breakage.
Оно и к лучшему, что набрать обороты обычно занимает некоторое время. Большинство технологий изрядно эволюционируют даже после первого запуска — особенно языки программирования. Ничего не может быть лучше для новой технологии, чем несколько лет использования лишь небольшим числом ранних адоптеров. Ранние адоптеры искушённы и требовательны, и быстро вымывают любые недостатки, какие остались в вашей технологии. Когда у вас лишь несколько пользователей, вы можете быть в тесном контакте со всеми ними. И ранние адоптеры снисходительны, когда вы улучшаете свою систему, даже если это что-то ломает.
There are two ways new technology gets introduced: the organic
growth method, and the big bang method. The organic growth method
is exemplified by the classic seat-of-the-pants underfunded garage
startup. A couple guys, working in obscurity, develop some new
technology. They launch it with no marketing and initially have
only a few (fanatically devoted) users. They continue to improve
the technology, and meanwhile their user base grows by word of
mouth. Before they know it, they're big.
Есть два способа, которыми внедряется новая технология: метод органического роста и метод большого взрыва. Метод органического роста олицетворяется классическим, действующим по наитию, недофинансированным гаражным стартапом. Пара ребят, работая в безвестности, разрабатывают какую-то новую технологию. Они запускают её без всякого маркетинга и поначалу имеют лишь нескольких (фанатично преданных) пользователей. Они продолжают улучшать технологию, а тем временем их пользовательская база растёт из уст в уста. Не успеют они оглянуться, как они уже большие.
The other approach, the big bang method, is exemplified by the
VC-backed, heavily marketed startup. They rush to develop a product,
launch it with great publicity, and immediately (they hope) have
a large user base.
Другой подход, метод большого взрыва, олицетворяется стартапом с венчурными деньгами и мощным маркетингом. Они спешат разработать продукт, запускают его с большой шумихой и сразу (как они надеются) получают большую пользовательскую базу.
Generally, the garage guys envy the big bang guys. The big bang
guys are smooth and confident and respected by the VCs. They can
afford the best of everything, and the PR campaign surrounding the
launch has the side effect of making them celebrities. The organic
growth guys, sitting in their garage, feel poor and unloved. And
yet I think they are often mistaken to feel sorry for themselves.
Organic growth seems to yield better technology and richer founders
than the big bang method. If you look at the dominant technologies
today, you'll find that most of them grew organically.
Как правило, гаражные ребята завидуют ребятам большого взрыва. Ребята большого взрыва гладкие, уверенные и уважаемые венчурными инвесторами. Они могут позволить себе всё самое лучшее, а PR-кампания вокруг запуска имеет побочный эффект — делает из них знаменитостей. Ребята органического роста, сидя в своём гараже, чувствуют себя бедными и нелюбимыми. И всё же я думаю, что они часто напрасно жалеют себя. Органический рост, похоже, даёт лучшую технологию и более богатых основателей, чем метод большого взрыва. Если вы посмотрите на доминирующие сегодня технологии, вы обнаружите, что большинство из них выросли органически.
This pattern doesn't only apply to companies. You see it in sponsored
research too. Multics and Common Lisp were big-bang projects, and
Unix and MacLisp were organic growth projects.
Этот паттерн применим не только к компаниям. Вы видите его и в финансируемых исследованиях. Multics и Common Lisp были проектами большого взрыва, а Unix и MacLisp — проектами органического роста.
10 Redesign
10 Перепроектирование
"The best writing is rewriting," wrote E. B. White. Every good
writer knows this, and it's true for software too. The most important
part of design is redesign. Programming languages, especially,
don't get redesigned enough.
«Лучшее письмо — это переписывание», — написал E. B. White. Каждый хороший писатель это знает, и для софта это тоже верно. Важнейшая часть проектирования — перепроектирование. Языки программирования, в особенности, перепроектируют недостаточно.
To write good software you must simultaneously keep two opposing
ideas in your head. You need the young hacker's naive faith in
his abilities, and at the same time the veteran's skepticism. You
have to be able to think
how hard can it be? with one half of
your brain while thinking
it will never work with the other.
Чтобы писать хороший софт, вам нужно одновременно удерживать в голове две противоположные идеи. Вам нужна наивная вера юного хакера в свои способности и в то же время скептицизм ветерана. Вы должны уметь думать да насколько это может быть сложно? одной половиной мозга, думая при этом это никогда не сработает другой.
The trick is to realize that there's no real contradiction here.
You want to be optimistic and skeptical about two different things.
You have to be optimistic about the possibility of solving the
problem, but skeptical about the value of whatever solution you've
got so far.
Фокус в том, чтобы осознать, что никакого реального противоречия здесь нет. Вы хотите быть оптимистом и скептиком в отношении двух разных вещей. Вы должны быть оптимистичны насчёт возможности решить задачу, но скептичны насчёт ценности того решения, что у вас есть на данный момент.
People who do good work often think that whatever they're working
on is no good. Others see what they've done and are full of wonder,
but the creator is full of worry. This pattern is no coincidence:
it is the worry that made the work good.
Люди, которые делают хорошую работу, часто считают, что то, над чем они работают, никуда не годится. Другие видят то, что они сделали, и полны восхищения, а творец полон тревоги. Этот паттерн не случаен: именно тревога сделала работу хорошей.
If you can keep hope and worry balanced, they will drive a project
forward the same way your two legs drive a bicycle forward. In the
first phase of the two-cycle innovation engine, you work furiously
on some problem, inspired by your confidence that you'll be able
to solve it. In the second phase, you look at what you've done in
the cold light of morning, and see all its flaws very clearly. But
as long as your critical spirit doesn't outweigh your hope, you'll
be able to look at your admittedly incomplete system, and think,
how hard can it be to get the rest of the way?, thereby continuing
the cycle.
Если вы можете удерживать надежду и тревогу в равновесии, они будут двигать проект вперёд так же, как две ваши ноги двигают вперёд велосипед. В первой фазе двухтактного двигателя инноваций вы яростно работаете над какой-то проблемой, вдохновлённые уверенностью, что сумеете её решить. Во второй фазе вы смотрите на то, что сделали, в холодном свете утра и очень ясно видите все недостатки. Но пока ваш критический дух не перевешивает вашу надежду, вы сможете взглянуть на свою, признаться, незавершённую систему и подумать: «да насколько сложно пройти оставшийся путь?» — тем самым продолжая цикл.
It's tricky to keep the two forces balanced. In young hackers,
optimism predominates. They produce something, are convinced it's
great, and never improve it. In old hackers, skepticism predominates,
and they won't even dare to take on ambitious projects.
Удерживать эти две силы в равновесии — дело хитрое. У юных хакеров преобладает оптимизм. Они что-то выпускают, убеждены, что это великолепно, и никогда это не улучшают. У старых хакеров преобладает скептицизм, и они даже не осмеливаются браться за амбициозные проекты.
Anything you can do to keep the redesign cycle going is good. Prose
can be rewritten over and over until you're happy with it. But
software, as a rule, doesn't get redesigned enough. Prose has
readers, but software has users. If a writer rewrites an essay,
people who read the old version are unlikely to complain that their
thoughts have been broken by some newly introduced incompatibility.
Всё, что вы можете сделать, чтобы поддерживать цикл перепроектирования, — хорошо. Прозу можно переписывать снова и снова, пока вы ею не довольны. Но софт, как правило, перепроектируют недостаточно. У прозы есть читатели, а у софта — пользователи. Если писатель переписывает эссе, люди, читавшие старую версию, вряд ли пожалуются, что их мысли сломала какая-то вновь введённая несовместимость.
Users are a double-edged sword. They can help you improve your
language, but they can also deter you from improving it. So choose
your users carefully, and be slow to grow their number. Having
users is like optimization: the wise course is to delay it. Also,
as a general rule, you can at any given time get away with changing
more than you think. Introducing change is like pulling off a
bandage: the pain is a memory almost as soon as you feel it.
Пользователи — обоюдоострый меч. Они могут помочь вам улучшить язык, но могут и отвадить вас от его улучшения. Так что выбирайте пользователей тщательно и не спешите наращивать их число. Иметь пользователей — это как оптимизация: мудрый путь в том, чтобы её откладывать. К тому же, как правило, в любой данный момент вам может сойти с рук больше изменений, чем вы думаете. Вводить изменения — это как срывать пластырь: боль становится воспоминанием почти в тот же миг, как вы её почувствуете.
Everyone knows that it's not a good idea to have a language designed
by a committee. Committees yield bad design. But I think the worst
danger of committees is that they interfere with redesign. It is
so much work to introduce changes that no one wants to bother.
Whatever a committee decides tends to stay that way, even if most
of the members don't like it.
Все знают, что плохая идея — поручать проектирование языка комитету. Комитеты дают плохой дизайн. Но я думаю, что худшая опасность комитетов в том, что они мешают перепроектированию. Внести изменения — столько труда, что никто не хочет с этим возиться. То, что решил комитет, как правило, таким и остаётся, даже если большинству членов это не нравится.
Even a committee of two gets in the way of redesign. This happens
particularly in the interfaces between pieces of software written
by two different people. To change the interface both have to agree
to change it at once. And so interfaces tend not to change at all,
which is a problem because they tend to be one of the most ad hoc
parts of any system.
Даже комитет из двух человек мешает перепроектированию. Это особенно происходит в интерфейсах между кусками софта, написанными двумя разными людьми. Чтобы изменить интерфейс, оба должны согласиться изменить его одновременно. И потому интерфейсы, как правило, вообще не меняются, что является проблемой, потому что они, как правило, — одна из самых ситуативных (ad hoc) частей любой системы.
One solution here might be to design systems so that interfaces
are horizontal instead of vertical — so that modules are always
vertically stacked strata of abstraction. Then the interface will
tend to be owned by one of them. The lower of two levels will either
be a language in which the upper is written, in which case the
lower level will own the interface, or it will be a slave, in which
case the interface can be dictated by the upper level.
Одно из решений здесь — проектировать системы так, чтобы интерфейсы были горизонтальными, а не вертикальными, — чтобы модули всегда были вертикально уложенными слоями абстракции. Тогда интерфейс, как правило, будет принадлежать одному из них. Нижний из двух уровней либо будет языком, на котором написан верхний, — в этом случае интерфейс будет принадлежать нижнему уровню, — либо будет рабом, и тогда интерфейс может диктоваться верхним уровнем.
11 Lisp
11 Lisp
What all this implies is that there is hope for a new Lisp. There
is hope for any language that gives hackers what they want, including
Lisp. I think we may have made a mistake in thinking that hackers
are turned off by Lisp's strangeness. This comforting illusion may
have prevented us from seeing the real problem with Lisp, or at
least Common Lisp, which is that it sucks for doing what hackers
want to do. A hacker's language needs powerful libraries and
something to hack. Common Lisp has neither. A hacker's language is
terse and hackable. Common Lisp is not.
Из всего этого следует, что есть надежда на новый Lisp. Есть надежда на любой язык, который даёт хакерам то, чего они хотят, — включая Lisp. Я думаю, мы, возможно, совершили ошибку, полагая, что хакеров отталкивает странность Lisp. Эта утешительная иллюзия, возможно, помешала нам увидеть реальную проблему Lisp — или, по крайней мере, Common Lisp — которая в том, что он отвратителен для того, что хакеры хотят делать. Хакерскому языку нужны мощные библиотеки и нечто, что можно хакать. У Common Lisp нет ни того, ни другого. Хакерский язык лаконичен и хакабелен. Common Lisp — нет.
The good news is, it's not Lisp that sucks, but Common Lisp. If we
can develop a new Lisp that is a real hacker's language, I think
hackers will use it. They will use whatever language does the job.
All we have to do is make sure this new Lisp does some important
job better than other languages.
Хорошая новость в том, что отвратителен не Lisp, а Common Lisp. Если мы сможем разработать новый Lisp, который будет настоящим хакерским языком, я думаю, хакеры будут им пользоваться. Они будут пользоваться любым языком, который делает работу. Всё, что нам нужно, — убедиться, что этот новый Lisp делает какую-то важную работу лучше, чем другие языки.
History offers some encouragement. Over time, successive new
programming languages have taken more and more features from Lisp.
There is no longer much left to copy before the language you've
made is Lisp. The latest hot language, Python, is a watered-down
Lisp with infix syntax and no macros. A new Lisp would be a natural
step in this progression.
История даёт некоторое ободрение. Со временем сменяющие друг друга новые языки программирования брали из Lisp всё больше и больше черт. Уже не так много осталось скопировать, прежде чем язык, который вы сделали, станет Lisp'ом. Новейший модный язык, Python, — это разбавленный Lisp с инфиксным синтаксисом и без макросов. Новый Lisp был бы естественным шагом в этой прогрессии.
I sometimes think that it would be a good marketing trick to call
it an improved version of Python. That sounds hipper than Lisp. To
many people, Lisp is a slow AI language with a lot of parentheses.
Fritz Kunze's official biography carefully avoids mentioning the
L-word. But my guess is that we shouldn't be afraid to call the
new Lisp Lisp. Lisp still has a lot of latent respect among the
very best hackers — the ones who took 6.001 and understood it, for
example. And those are the users you need to win.
Я иногда думаю, что было бы хорошим маркетинговым трюком назвать его улучшенной версией Python. Это звучит хиповее, чем Lisp. Для многих людей Lisp — это медленный язык для ИИ с кучей скобок. Официальная биография Fritz Kunze тщательно избегает упоминания слова на букву «L». Но я полагаю, что нам не стоит бояться назвать новый Lisp — Lisp'ом. Lisp по-прежнему пользуется немалым скрытым уважением среди самых лучших хакеров — например, тех, кто прослушал курс 6.001 и понял его. А это как раз те пользователи, которых вам нужно завоевать.
In "How to Become a Hacker," Eric Raymond describes Lisp as something
like Latin or Greek — a language you should learn as an intellectual
exercise, even though you won't actually use it:
В «How to Become a Hacker» Eric Raymond описывает Lisp как нечто вроде латыни или греческого — язык, который вам следует выучить как интеллектуальное упражнение, даже если вы на самом деле не будете им пользоваться:
Lisp is worth learning for the profound enlightenment experience
you will have when you finally get it; that experience will make
you a better programmer for the rest of your days, even if you
never actually use Lisp itself a lot.
Lisp стоит выучить ради того глубокого опыта просветления, который вы переживёте, когда наконец его постигнете; этот опыт сделает вас лучшим программистом на всю оставшуюся жизнь, даже если вы сами никогда не будете много пользоваться самим Lisp.
If I didn't know Lisp, reading this would set me asking questions.
A language that would make me a better programmer, if it means
anything at all, means a language that would be better for programming.
And that is in fact the implication of what Eric is saying.
Если бы я не знал Lisp, чтение этого побудило бы меня задавать вопросы. Язык, который сделал бы меня лучшим программистом, — если это вообще что-то значит — означает язык, который был бы лучше для программирования. И это и есть, по сути, подтекст того, что говорит Eric.
As long as that idea is still floating around, I think hackers will
be receptive enough to a new Lisp, even if it is called Lisp. But
this Lisp must be a hacker's language, like the classic Lisps of
the 1970s. It must be terse, simple, and hackable. And it must have
powerful libraries for doing what hackers want to do now.
Пока эта идея всё ещё носится в воздухе, я думаю, хакеры будут достаточно восприимчивы к новому Lisp, даже если он называется Lisp. Но этот Lisp должен быть хакерским языком, как классические Lisp'ы 1970-х. Он должен быть лаконичным, простым и хакабельным. И у него должны быть мощные библиотеки для того, что хакеры хотят делать сейчас.
In the matter of libraries I think there is room to beat languages
like Perl and Python at their own game. A lot of the new applications
that will need to be written in the coming years will be
server-based
applications. There's no reason a new Lisp shouldn't have string
libraries as good as Perl, and if this new Lisp also had powerful
libraries for server-based applications, it could be very popular.
Real hackers won't turn up their noses at a new tool that will let
them solve hard problems with a few library calls. Remember, hackers
are lazy.
В вопросе библиотек, я думаю, есть пространство обыграть такие языки, как Perl и Python, на их же поле. Многие из новых приложений, которые понадобится написать в грядущие годы, будут серверными приложениями. Нет причин, по которым у нового Lisp не могло бы быть строковых библиотек не хуже, чем у Perl, и если бы у этого нового Lisp были ещё и мощные библиотеки для серверных приложений, он мог бы стать очень популярным. Настоящие хакеры не станут воротить нос от нового инструмента, который позволит им решать трудные задачи парой библиотечных вызовов. Помните, хакеры ленивы.
It could be an even bigger win to have core language support for
server-based applications. For example, explicit support for programs
with multiple users, or data ownership at the level of type tags.
Ещё бóльшим выигрышем могла бы стать поддержка серверных приложений на уровне ядра языка. Например, явная поддержка программ с несколькими пользователями или владение данными на уровне тегов типов.
Server-based applications also give us the answer to the question
of what this new Lisp will be used to hack. It would not hurt to
make Lisp better as a scripting language for Unix. (It would be
hard to make it worse.) But I think there are areas where existing
languages would be easier to beat. I think it might be better to
follow the model of Tcl, and supply the Lisp together with a complete
system for supporting server-based applications. Lisp is a natural
fit for server-based applications. Lexical closures provide a way
to get the effect of subroutines when the ui is just a series of
web pages. S-expressions map nicely onto html, and macros are good
at generating it. There need to be better tools for writing
server-based applications, and there needs to be a new Lisp, and
the two would work very well together.
Серверные приложения дают нам и ответ на вопрос, что этот новый Lisp будет использоваться хакать. Не помешало бы сделать Lisp лучше как скриптовый язык для Unix. (Сделать его хуже было бы трудно.) Но я думаю, есть области, где существующие языки было бы легче обыграть. Я думаю, было бы лучше последовать модели Tcl и поставлять Lisp вместе с полной системой для поддержки серверных приложений. Lisp естественно подходит для серверных приложений. Лексические замыкания дают способ получить эффект подпрограмм, когда пользовательский интерфейс — это просто череда веб-страниц. S-выражения славно отображаются на HTML, а макросы хорошо его генерируют. Должны появиться лучшие инструменты для написания серверных приложений, и должен появиться новый Lisp, и они очень хорошо работали бы вместе.
12 The Dream Language
12 Язык мечты
By way of summary, let's try describing the hacker's dream language.
The dream language is
beautiful, clean, and terse. It has an
interactive toplevel that starts up fast. You can write programs
to solve common problems with very little code. Nearly all the
code in any program you write is code that's specific to your
application. Everything else has been done for you.
В качестве итога давайте попробуем описать язык мечты хакера. Язык мечты красив, чист и лаконичен. У него есть интерактивный верхний уровень (toplevel), который быстро запускается. Вы можете писать программы, решающие распространённые задачи, очень малым количеством кода. Почти весь код в любой программе, которую вы пишете, — это код, специфичный для вашего приложения. Всё остальное уже сделано за вас.
The syntax of the language is brief to a fault. You never have to
type an unnecessary character, or even to use the shift key much.
Синтаксис языка краток до предела. Вам никогда не приходится набирать лишний символ или даже часто пользоваться клавишей shift.
Using big abstractions you can write the first version of a program
very quickly. Later, when you want to optimize, there's a really
good profiler that tells you where to focus your attention. You
can make inner loops blindingly fast, even writing inline byte code
if you need to.
Используя крупные абстракции, вы можете очень быстро написать первую версию программы. Позже, когда вы захотите оптимизировать, есть по-настоящему хороший профайлер, который подсказывает, на чём сосредоточить внимание. Вы можете сделать внутренние циклы ослепительно быстрыми, при необходимости даже написав встроенный (inline) байт-код.
There are lots of good examples to learn from, and the language is
intuitive enough that you can learn how to use it from examples in
a couple minutes. You don't need to look in the manual much. The
manual is thin, and has few warnings and qualifications.
Есть множество хороших примеров, на которых можно учиться, и язык достаточно интуитивен, чтобы вы могли научиться им пользоваться по примерам за пару минут. Вам не нужно часто заглядывать в руководство. Руководство тонкое, и в нём мало предупреждений и оговорок.
The language has a small core, and powerful, highly orthogonal
libraries that are as carefully designed as the core language. The
libraries all work well together; everything in the language fits
together like the parts in a fine camera. Nothing is deprecated,
or retained for compatibility. The source code of all the libraries
is readily available. It's easy to talk to the operating system
and to applications written in other languages.
У языка небольшое ядро и мощные, в высшей степени ортогональные библиотеки, спроектированные так же тщательно, как и само ядро языка. Все библиотеки хорошо работают вместе; всё в языке подогнано друг к другу, как детали в хорошей фотокамере. Ничто не объявлено устаревшим (deprecated) и не сохранено ради совместимости. Исходный код всех библиотек легко доступен. Легко общаться с операционной системой и с приложениями, написанными на других языках.
The language is built in layers. The higher-level abstractions are
built in a very transparent way out of lower-level abstractions,
which you can get hold of if you want.
Язык построен слоями. Высокоуровневые абстракции построены очень прозрачным образом из низкоуровневых абстракций, до которых вы можете добраться, если захотите.
Nothing is hidden from you that doesn't absolutely have to be. The
language offers abstractions only as a way of saving you work,
rather than as a way of telling you what to do. In fact, the language
encourages you to be an equal participant in its design. You can
change everything about it, including even its syntax, and anything
you write has, as much as possible, the same status as what comes
predefined.
От вас не скрыто ничего, что не было бы абсолютно необходимо скрыть. Язык предлагает абстракции лишь как способ избавить вас от работы, а не как способ указывать вам, что делать. Более того, язык поощряет вас быть равноправным участником его проектирования. Вы можете изменить в нём всё, включая даже его синтаксис, и всё, что вы пишете, имеет, насколько это возможно, тот же статус, что и то, что идёт предопределённым.
Notes
Примечания
[1] Macros very close to the modern idea were proposed by Timothy
Hart in 1964, two years after Lisp 1.5 was released. What was
missing, initially, were ways to avoid variable capture and multiple
evaluation; Hart's examples are subject to both.
[1] Макросы, очень близкие к современной идее, были предложены Timothy Hart в 1964 году, через два года после выхода Lisp 1.5. Чего поначалу не хватало, так это способов избегать захвата переменных и многократного вычисления; примеры Hart подвержены и тому, и другому.
[2] In When the Air Hits Your Brain, neurosurgeon Frank Vertosick
recounts a conversation in which his chief resident, Gary, talks
about the difference between surgeons and internists ("fleas"):
[2] В книге When the Air Hits Your Brain нейрохирург Frank Vertosick пересказывает разговор, в котором его старший ординатор Gary рассуждает о разнице между хирургами и терапевтами («блохами»):
Gary and I ordered a large pizza and found an open booth. The
chief lit a cigarette. "Look at those goddamn fleas, jabbering
about some disease they'll see once in their lifetimes. That's
the trouble with fleas, they only like the bizarre stuff. They
hate their bread and butter cases. That's the difference between
us and the fucking fleas. See, we love big juicy lumbar disc
herniations, but they hate hypertension...."
Мы с Gary заказали большую пиццу и нашли свободную кабинку. Шеф закурил сигарету. «Посмотри на этих чёртовых блох, болтают о какой-то болезни, которую увидят раз в жизни. Вот в чём беда с блохами — им нравится только всё причудливое. Они терпеть не могут свои рутинные, хлеб-да-масло случаи. Вот в чём разница между нами и этими сраными блохами. Видишь ли, мы любим большие сочные грыжи поясничных дисков, а они ненавидят гипертонию...»
It's hard to think of a lumbar disc herniation as juicy (except
literally). And yet I think I know what they mean. I've often had
a juicy bug to track down. Someone who's not a programmer would
find it hard to imagine that there could be pleasure in a bug.
Surely it's better if everything just works. In one way, it is.
And yet there is undeniably a grim satisfaction in hunting down
certain sorts of bugs.
Трудно представить грыжу поясничного диска сочной (разве что буквально). И всё же, кажется, я понимаю, что они имеют в виду. У меня часто бывал сочный баг, который надо было выследить. Тому, кто не программист, было бы трудно вообразить, что в баге может быть удовольствие. Уж наверное лучше, когда всё просто работает. В одном смысле — да. И всё же есть неоспоримое мрачное удовлетворение в охоте за определёнными сортами багов.