[HN Gopher] Programming Bottom-Up (1993)
       ___________________________________________________________________
        
       Programming Bottom-Up (1993)
        
       Author : tzury
       Score  : 32 points
       Date   : 2023-12-07 07:03 UTC (2 days ago)
        
 (HTM) web link (www.paulgraham.com)
 (TXT) w3m dump (www.paulgraham.com)
        
       | dang wrote:
       | Related:
       | 
       |  _Programming Bottom-Up (1993)_ -
       | https://news.ycombinator.com/item?id=16933030 - April 2018 (64
       | comments)
        
       | smlavine wrote:
       | I've heard this about Lisp, but I don't really get how this
       | doesn't apply to other languages. How is writing special
       | operators in Lisp different from writing special functions in any
       | other language?
        
         | marcosdumay wrote:
         | PG has other essays where he claims it's because the lisp
         | version of operators can just do more things.
         | 
         | And that's true, lisp macros are way more powerful than what
         | most languages support. The newer ones (and some "progressive"
         | old ones) got template systems that are almost as powerful, but
         | the most used languages simply don't have anything comparable.
         | 
         | That said, nowadays using a lot of that kind of feature is
         | normally frowned upon.
        
           | leetrout wrote:
           | I have a theory it is frowned upon because there are not a
           | lot of small shops left. Everyone wants be a cog at a big
           | tech co where its leetcode interviews and code that large
           | groups can (somewhat) easily maintain.
           | 
           | In these cases the languages used are generally uniform so
           | your skills easily transfer and you aren't suffering as many
           | 200% problems by learning both the language and the authors
           | peculiar add-ons.
           | 
           | Of course it still happens just not as easy with rigid
           | languages such as Go.
           | 
           | It's all tradeoffs.
        
         | jksmith wrote:
         | Extreme reinforcement of your point: Read Leo Brodie's classics
         | "Starting Forth" and "Thinking Forth."
        
         | Jtsummers wrote:
         | > I've heard this about Lisp, but I don't really get how this
         | doesn't apply to other languages.
         | 
         | It can be, and he even says as much:
         | 
         | >> Bottom-up design is possible to a certain degree in
         | languages other than Lisp. Whenever you see library functions,
         | bottom-up design is happening.
         | 
         | I'll also point to kazinator's quote of Ken Thompson in the
         | previous discussion linked by dang:
         | 
         | >> It is the way I think. I am a very bottom-up thinker. If you
         | give me the right kind of Tinker Toys, I can imagine the
         | building. I can sit there and see primitives and recognize
         | their power to build structures a half mile high, if only I had
         | just one more to make it functionally complete. I can see those
         | kinds of things. The converse is true, too, I think. I can't--
         | from the building--imagine the Tinker Toys. When I see a top-
         | down description of a system or language that has infinite
         | libraries described by layers and layers, all I just see is a
         | morass. I can't get a feel for it. I can't understand how the
         | pieces fit; I can't understand something presented to me that's
         | very complex. Maybe I do what I do because if I built anything
         | more complicated, I couldn't understand it. I really must break
         | it down into little pieces. - Ken Thompson, Unix and Beyond: An
         | Interview with Ken Thompson, 1999
         | 
         | And if you use a TDD style of development (in particular, but
         | test-heavy in general with frequent use of unit and integration
         | tests below the full end-to-end-test level) you'll also likely
         | stumble onto a similar bottom-up style of development.
         | 
         | I think, circa 1993, his emphasis on Lisp and bottom-up
         | development made a lot more sense than it does today with the
         | increasing availability of interactive development environments
         | (essentially every dynamically typed language, pretty much; but
         | even many others like Java and C#) and increased emphasis on
         | test-heavy development methodologies.
        
         | norir wrote:
         | A function call has runtime overhead that a macro may not.
         | There are also things that can be difficult to express as a
         | function in the language type system but that are
         | straightforward to implement as a macro. Lisp isn't the only
         | language with a strong macro system but it disproportionately
         | attracts programmers who value the power and expressivity that
         | a strong macro system provides.
         | 
         | There are a number of reasons that bottom up programming in the
         | style PG seems to be advocating for is not popular in industry.
         | Industrial programming favors the median developer while bottom
         | up is a technique that works best with small teams of skilled
         | programmers. Big cos obviously prefer "safe" languages, but
         | even startups are generally conservative due to the vc induced
         | pressure towards hypergrowth, which also favors the median
         | developer since hypergrowth requires hiring.
         | 
         | Writing good programs from the bottom up requires more
         | skill[1], but can lead to substantially better programs by
         | certain criteria. But it may also be considered inscrutable by
         | the median developer. The median developer can also misuse the
         | power afforded by the bottom up language and write something
         | much worse than they would have been able to in a more
         | conservative language. This isn't a knock on the median
         | developer, btw, just my perspective on why this style is rarely
         | found in industry.
         | 
         | [1] neither LLMs nor stack overflow are of much help when you
         | have essentially written a new language to solve your problem.
        
       | liampulles wrote:
       | For me the key thing is that if you are doing "bottom-up"
       | programming, then those macros/functions/etc. should be abstract
       | and not related to business rules. Else you are doing premature
       | abstraction, and you'll end up creating big rocks you have to
       | carry on your back when you want to make a change.
       | 
       | As a consequence, I personally practice bottom-up very sparsely
       | and carefully.
        
       | sillysaurusx wrote:
       | If you want to see this principle in action, I've been updating
       | Arc for the last five years. If you clone
       | https://github.com/shawwn/sparc, you should be able to run
       | bin/arc news.arc and see a clone of hacker news running on
       | http://localhost:8080. No need to install anything if you're on
       | Linux or Mac; it downloads a minimal racket locally. Windows
       | users just need to install racket normally.
       | 
       | I use it as a bookmark aggregator, since I can submit things and
       | leave myself notes. The first account you create will become an
       | admin, and any future accounts are regular users. Passwords are
       | bcrypted rather than sha1'd. Windows works too, but for some
       | reason the repl seems to block all other threads from making
       | progress, so Microsoft users will have to run it with DEV=0 to
       | disable the news.arc repl on startup.
       | 
       | It's not ready to show yet in general, but there are a lot of
       | advances. My design goal is that if pg ever sees it, he'd want to
       | use it himself.
       | 
       | It incorporates some ideas from Bel, too. I'll be doing a big
       | write up of all the changes.
       | 
       | The biggest advance from a language standpoint is probably
       | keyword arguments. If there's any interest, I'll go into more
       | detail.
       | 
       | The biggest advance from a usability standpoint is that arc is
       | now a thin wrapper over racket. There's no FFI and no need to
       | translate anything. Arc lists are racket lists. Ditto for hash
       | tables and everything else. You can write racket code in arc by
       | prefixing code #'(like this), which the arc compiler turns into a
       | racket expression (like this). So #'(require (rename-in
       | racket/system [system racket-system])) will do what you'd expect
       | it to do in racket. You can mix racket code and arc in two ways:
       | (#'foo bar baz) will compile bar and baz as arc expressions, but
       | will call foo in functional position. So (#'begin0 (+ "x" 'y) 'z)
       | will give "xy", because begin0 is a racket special form that
       | returns its leftmost expression.
       | 
       | The other way is an equivalent of quasiquoting: #`(let ((x #,(obj
       | a: 1))) x) will return a hash table with 'a set to 1.
       | 
       | The unit tests in test.arc are probably the best way to see all
       | the language features, but it's hard to read at times. (The
       | writeup will introduce each concept in a bel-like fashion, but
       | it's not ready yet.)
       | 
       | news.arc is where most of the power is on display. Making a new
       | endpoint is extremely easy. And prompt.arc shows how you can
       | write a dynamic application without using databases or needing to
       | store any state. The state is in the closures.
        
         | sillysaurusx wrote:
         | Speaking of closures, remember how HN used to run out of RAM
         | because each page refresh would create new ones? That doesn't
         | happen here, because no new closure is created if both the
         | lexical environment and the compiled code are identical. The
         | number of fns are displayed at the bottom when you're logged in
         | as an admin, so you can verify nothing new is created when you
         | refresh.
         | 
         | Dan has a good writeup about why HN got rid of them, but
         | unfortunately I can't seem to find it. There are still reasons
         | to avoid them (e.g. if you need a stable url), but I'm happy
         | that performance is no longer one of them.
        
       | briantakita wrote:
       | > Whenever you see library functions, bottom-up design is
       | happening.
       | 
       | I'm glad he acknowledged that library functions is the majority
       | implementation of "bottom up design". In that case extracting
       | primitive api functions & layers composed of these functions is
       | effective at reusing logic & creating appropriate levels of
       | abstraction.
       | 
       | That being said, many frameworks do not offer these layers of
       | abstraction so create a sort of "complexity lock in"...where one
       | has to use the entire framework in order to use a few useful
       | parts of the framework. I find this complexity lock in to be
       | unfortunate as it not only couples the programmer to the entire
       | framework, even if the majority of the framework is not useful.
       | It also creates noise in the conversation, making it more
       | difficult to search for the appropriate solutions at the
       | appropriate level of abstraction.
       | 
       | There is a cost to integrating other libraries into the
       | framework.
       | 
       | Frameworks also tend to become an institution in search of
       | increasing market share. This means there are changes done to the
       | framework. Some of these changes are breaking changes that don't
       | necessarily improve the core development experience in meaningful
       | ways.
        
       ___________________________________________________________________
       (page generated 2023-12-09 23:00 UTC)