280 karma · joined December 16, 2020
Last time I tried I got as far as the first substantive program (https://github.com/norvig/paip-lisp/blob/main/lisp/gps.lisp), was generally confused by the code, and was then not surprised when the following sections pointed out all the faults (i.e. bugs) with the initial approach and suggested various improvements. I've come to trust my own "how can this possibly work?" confusion as a strong signal that a design is probably buggy or fragile, so it was nice to see it confirmed here.
Which is not to say that what this book teaches is not useful, but I wouldn't go to it looking for best practice and robust software engineering techniques. Much of what I saw in this book wouldn't pass code review in many situations ("too fragile" or "too clever"). Most of what he's talking about are techniques that "allow a programmer to delay making decisions". This is a different kind of programming than very the very concrete kind of programming that can dominate day to day professional work. I suspect that these kinds of "delayed decisions" are best applied sparingly, but applied correctly they can be powerful.
To get a flavor of the "Norvig approach" to things, his Advent of Code solutions in IPython notebooks are fun: https://github.com/norvig/pytudes
I do think this moves the problem of possible argument confusion to the construction of the new type. At some point the association must be expressed in code, and if the association is between two things of the same type the type system can't flag mistakes as errors. A simple data class still helps, even if it doesn't eliminate the problem, because people can more easily remember one Point(x, y) constructor than where "x" and "y" appear in dozens of different functions.
I first ran into this issue trying to learn Haskell, where some beginner websites used fonts like Fira Code in their listing. The "weird" operators I saw in the listings were unclear to me. In some cases I simply wasn't sure how to even reproduce the code in my editor. I think it is something I could grow used to and someday perhaps even enjoy, but as a beginner it was a barrier.
Respectfully, this definition of "open-source" does not match common use, even with a loose colloquial interpretation in mind. As commonly understood, an "open-source" license requires the ability to acquire the source, and to modify it, and to redistribute it.
Your definition, quoted above, would call open-source a license that allowed for personal modifications to source but forbade redistribution of those modifications. Your definition would also call open-source a license that required all modifications of the source to be made through a single point of central control. I think both of these cases fail even loose understandings of what "Open Source/open-source" is. I do think they both describe "source available".
You draw a distinction between "open-source" as a colloquial term and "Open Source" as defined by the OSI, but I don't think this isn't very compelling or useful. Sure, language evolves and people use terms incorrectly all the time, but that doesn't make erroneous use correct. In particular, "Open Source" is used as a legal criteria for a set of software licenses, so precision in its definition is important. Also, I have not personally come across any cases where there was any material difference between colloquial use of the term open-source and precise definition of Open Source as defined by the OSI. Do you have anything to cite that justifies a distinction here?
So I beg you to reconsider the idea that the OSI is "some organization who just decided to name themselves after the term" and the idea that "Open Source" is a term "defined loosely by how people use it." In point of historical fact, the term was first used by the people behind the organization, who formed it to popularize it as a new concept, and an alternative to "Free Software": https://web.archive.org/web/20021001164015/http://www.openso.... The OSI is not some organization formed to co-opt and redefine the term for their own purposes after it was already in common use.
I do agree with you that often times people think of specific project management structures when talking about open-source development. I.e. the debates about what makes for a successful open-source project, cultivating a community, making it easy for community members to contribute, etc. There can be non-open-source projects using open-source development methodologies, sure, but it doesn't make them "open-source" even in a colloquial sense. The sole criteria is always the license granted to users of the software.
I once worked on an early era "smart" phone whose apps were written in a visual basic-like clone. We were silicon valley cool kids and thought people would love too write apps in a high level language rather than C or C++. This was pre-web, pre-javascript, pre-Android, pre-iOS. The large Japanese tech company putting the phone out was staffed by a bunch of electrical engineers whose idea of programming was a table driven state machine, so they used Excel to model the UI for the entire phone as one huge state machine, then wrote Excel basic that took that spreadsheet and generated the proprietary basic code for the device's UI. We thought they'd want to write basic code, but they wanted to code up a spreadsheet instead.
I code in an established language if I want to I'm more interesting in solving a specific technical problem.
As for "what if this becomes a serious project?" question, remember that a rewrite always goes faster than the original.
It is a much more difficult to maintain a different kernel than it is a different desktop environment. So there is a huge incentive to cooperate on one kernel, even among companies with wildly different concerns (e.g. embedded IoT devices vs. cloud servers).
The kernel is also developed with an entirely different support culture than, say, Gnome. Backward compatibility for all supported use cases is taken extremely seriously by kernel developers. If it works on today's Linux kernel you can be almost assured it will work in 5 or 10 years. So, kernel users (i.e. developers, distro maintainers, etc.) stay happy because their stuff doesn't break.
Contrast this with the more "opinionated" DEs and you see features yanked and changed at a comparably dizzying rate. So, DE users experience a rate of change and support dynamic that is actually much "worse" than kernel users do.
I also don't see it as necessarily a zero sum game. The choice is not always "do thing A or contribute to a similar incumbent project B" but "do my own thing A or nothing at all, because B doesn't want my idea."
At work, I've found I work best with fast moving get-it-done types. They push me to accept imperfect work, and I've learned to see the value in that. I polish the imperfect stuff, and signal to the team when a "boring" quality improvement really could reap benefits.
Clearly, the sentence you quote is making an unqualified absolute statement, which are usually easy to pick apart and tear down. After reading the whole philosophy, I'm not really sure what they mean by "guarantee" and "pointless" here. I doubt they're saying that all programming in "unsafe" languages is "pointless."
I suspect they could just reword that sentence to say something more clear. E.g. what kinds of correctness they weigh most heavily. Does Pony protect me from all classes of all possible bugs? No? Because that is impossible? Agreed. Then which kinds of bugs?
Just before, it also says: "The Pony philosophy is neither “the-right-thing” nor “worse-is-better”. It is “get-stuff-done”." This is admitting some sort of balance is being struck here...
Yes, and envelopes make it easier for many people to figure out if they have the cash for it. They let you "spend" the money the instant you get it, in a virtual way, even if you don't really need to spend it until later. This way you know that when it comes time to pay rent/mortgage, property tax, etc., you're good.
I think you are right though: I think the envelope idea is primarily targeted at people on a tight budget, where you really are trading off pros and cons of spending relatively small sums of money, and where the usual question is what gets sacrificed if this or that is purchased.
You suggest that in such a situation you'd look at the root cause of such behavior (e.g. compulsive spending). Often, the "root cause" is simply unawareness of spending patterns, and envelope spending is a useful technique for a lot of people. It isn't a crutch to cover up some sort of underlying personality flaw that has a deeper "root cause" -- It is just a way of tracking earmarked spending.
I don't think I agree with its basic conclusion that language flexibility leads to a kind of social problem akin to a "curse."
From what I've seen over my career, both C and C++, which the essay claims are not cursed, have many libraries that don't interoperate well, re-invent wheels, are under documented, solve only part of a problem, and are basically solo/hobby efforts. In every job, the first thing I have to learn is how I'm allowed to write C or C++ at the company, since each provides such a huge surface.
The difference between C/C++ and Lisp/D is, I think, not language flexibility. They are all incredibly complex and flexible languages in their own way. The difference is funding and critical mass. C and C++ persist because companies pay people to use them and to improve them. Or, in terms of the curse essay, companies pay people to cooperate. The result is an enduring dominance. Those languages work better because more people use and improve them, so they stay relevant. Neither Lisp nor D seem to benefit significantly from that, so you have what is left: people without the time or interest in producing truly polished solutions.
In many ways this is just growing pains. For years people willingly handed their name/password to third party apps and sites, and this granted those sites full auth. This was too permissive, but extremely easy for people to understand, even for non-techies.
With things like OAuth, OS level capabilities in iOS and Android, etc., we've now got to break down these "scopes" into slices that are flexible enough to write useful software against without being too broad, too revealing of the underling software architecture (brittle), and too confusing for the user. I think this is actually a really hard problem.