HNHacker News
TopNewBestAskShowJobs

todd8

6,363 karma · joined August 30, 2013

submissionscomments
todd8··on Emacs 29.1
Emacs is daunting, I've used it since grad school in the 80's, and I'm still familiar with only a couple of hundred packages/extensions available out of thousands that are available. Likewise, I use maybe a couple of hundred commands and key bindings (out of thousands available--Emacs interactive help with finding the commands makes this possible).

I can imagine how hard it must be to learn the basics buried within a mountain of functionality. The way I learned to use Emacs originally was by learning to use a stripped down Emacs-like editor that ran on my home PC running MS-DOS. This editor used the same basic key bindings and supported the fundamental operations one uses to edit files: navigation, directory browsing, reading and saving files and so forth, all with the same keys that full blown Emacs uses.

Instead of installing Emacs, try installing micro-Emacs (its actual name is mg). This should run on Linux, MacOS, or Windows. On the Mac, you can install mg using homebrew. This is a perfectly good editor, and it uses the keys and commands that make up most of the ones I use every day. It just has fewer features, no Org mode, no image browsing, no support for git, no Email clients, no GPG support, no Voice output, no games, etc. It's just a solid text editor that will run in text mode.

Within a few days of using mg, you will be able to navigate around a document, open and save files, browse directories, and know how to get basic help within the editor. Then try Emacs and only add extensions as you need or want them.

todd8··on Writing prettier Haskell with Unicode syntax and Vim
Another problem with using unicode in code is the handling of Unicode equivalence, compatibility, and normalization[1]. The same glyph can be produced in multiple ways. How is the reader, vim or emacs, and the compiler supposed to handle these cases?

[1] https://en.wikipedia.org/wiki/Unicode_equivalence

todd8··on Writing prettier Haskell with Unicode syntax and Vim
Perhaps this is true for some texts, but take a look at math journals where mathematicians are writing for other mathematicians within their own field. They reuse symbols, sometime an integral symbol is for Riemann integration and sometimes it's for Lebesgue integration. The subject of the paper will make it clear which is which.

Even in our own field, Computer Science, there are too many confusing cases: Knuth uses |S| to mean the cardinality of set S, |f| to be the number of solutions when f is a boolean, |x| to be the absolute value of x, |z| to be the absolute value of a complex number, and |a| to be the length of a. All within the same book, TAOCP vol 4A Part 1.

todd8··on Writing prettier Haskell with Unicode syntax and Vim
Using the equals sign (=) for assignment is unfortunate. Mathematically, a=a+5 is confusing. Algol 60 (and its grandchild Pascal) are a bit better and represent this as a:=a+5, but this is an odd notation too. A left pointing arrow would be a better notation for the common assignment statement, at least to me.

Does this mean I'm ready to embrace the use of mathematical notation via unicode glyphs in programming? No. I have a math degree and after dozens of university courses on math I've seen a lot of math notation. This notation uses a dizzying number of symbols across various mathematical disciples. LaTeX allows one to use any of 75 distinct kinds of arrows alone! Left, right, doubled, up, down, diagonal to the upper right, looped, long, bidirectional, harpooned, wiggly, maps-to, and so forth. That's just the arrows. Why does LaTeX allow typesetting with so many distinct arrows? Because mathematicians use them as distinct concepts.

I count 160 relational symbols available for use with standard LaTeX: less-than, equal, equivalent, congruent, subset, parallel, similar, approximate, the list goes on and on. See [1].

Mathematicians don't even use these symbols consistently. Consider the ubiquitous lambda, appearing all over in functional programming. Surely, the use of a lower-case greek lambda is prettier than spelling out the word 'lambda', but it may in many contexts not stand for an anonymous function. It's use as a symbol can also mean: wavelength of any wave, number of offspring, radioactive decay constant, occurrence density within a time interval, eigenvalues, charge density, Lagrange multiplier, empty string, and so forth. Wikipedia lists 24 distinct uses for lambda, [2].

Why do mathematicians, engineers, and scientists use so many different symbols? Because they are doing something fundamentally different with them than programmers. They use the symbols as abbreviations that will be understood by their audience, which might be students watching a lecture, readers of a technical article, or even themselves at some time in the future. The context in all of these uses is very different than the context of a program. The program must be precise and unambiguous, and the program may be one hundred times longer than a published math paper. For this reason, spelled out identifiers and keywords using standard ASCII glyphs are wordier and less "pretty" but are far more practical.

[1] https://www.cmor-faculty.rice.edu/~heinken/latex/symbols.pdf

[2] https://en.wikipedia.org/wiki/Lambda#:~:text=Lambda%20indica....

todd8··on Limits of Programmer Productivity: A lesson from Fred Brooks
Cards were often numbered for finished programs, but during development any change or refactoring would invalidate the numbers and the diagonal lines drawn on the side of a deck of cards. Some of the larger comp centers had data processing equipment that would number a stack of cards by punching the card number in the reserved columns 73-80. Card sorters could then sort a mixed up deck using a radix sort in a few passes. See my nearby comments.
todd8··on Limits of Programmer Productivity: A lesson from Fred Brooks
Punching the cards was a pain. The machines could jam and a single mistake would ruin the card and you have to pull it out and start over on a fresh card. So it wasn’t practical to number the cards while initially punching them. There was a designated field for numbering though, FORTRAN ignored columns 73 through 80 for this reason. The ubiquitous cards were 80 columns wide. This is why our programs today must never have lines wider than 72 columns—this honors those that came before us. Oh, and start your code in column 7, Fortran programs used the first 5 columns for numeric labels.

IF statements looked like this:

       IF (Y+Z) 100,200,205
This evaluates X+Y and jumps to the line labeled (in columns 1-5) 100 if X+Y is negative and to the source line labeled 205 if the sum is positive. Note that the IF always has three destinations, making it perfect for programs doing binary search.

My first programs were punched with the IBM 026 keypunch machine. This was a machine not really intended to punch program decks. It was for the earlier use of the cards to hold data that would be tabulated, sorted, or collated by IBM tabulation machinery. The later 029 model keypunch was a huge improvement for programming, it even had keys that would punch a parenthesis!

There were special file cabinets to store long stacks of cards in tray like drawers. You could pull out a drawer holding maybe 1000 cards and carry/drag it over to be submitted for a run. Smaller programs or data sets were carried around in shallow boxes.

I don’t ever remember having a dropped card box disaster, but I would mark my card decks with thick diagonal lines so that out of place cards could be easily spotted.

Even a simple, hundred line program might take 30 minutes from the time you handed it over to the computer operators to the time you saw any output (which came out on fan fold wide paper print outs). The operators lived in a big bright room with a glass wall housing the big computer with blinking lights and wore sweaters and could only receive your submitted programs through a small window. The operators literally looked down on us lowly programmers. (The computation centers had elevated flooring about a foot high to hide all the power and cooling lines.)

Unless you were special, you weren’t allowed in the secured room where the corporate computer resided. The corporations were very proud of their giant electronic brain—that’s why they put it in the big, bright, cold room behind glass so we could contemplate its power. The corporation might have a second computer, but it would be in a different city (in case of an earthquake or a Soviet nuclear bomb).

Because of the slow turn around time, a syntax error would require 30 minutes to discover. Then fixing it would require fumbling with cards to find the error and finding a free keypunch, more blank cards and then punching and fumbling around some more to refactor the code. Thirty minutes later . . . And you find your second syntax error.

Turn around time varied greatly, some times I was allowed only one overnight run every couple of days so I wouldn’t see my output until morning. This gave me lots of time to desk check my program. Sometimes I would even find my syntax error before the computer did.

Back in the bronze age, programmers didn’t have text editors, Github, or even a file system to store our source on, we just had drawers to hold our cards.

This link has pictures of the IBM 026 keypunch (used by the Vikings).

http://www.columbia.edu/cu/computinghistory/026.html

todd8··on Overview of C++ language support in Apple Clang
As far back as 2007 it was called clang. I'm not sure if it was called clang internally before that. See the seventh slide in the linked presentation.

https://web.archive.org/web/20190403123249/http://llvm.org/d...

todd8··on Why Lisp Syntax Works
When I learned APL, the expression evaluation order at first seemed odd (strictly right to left with no operator presence, 5*5+4 evals to 45 not 29). After working with it a couple of hours I came to appreciate its simplicity, kind of like the thread operator in your last example.
todd8··on Caltech's Space Solar Power Demonstrator Wirelessly Transmits Power in Space
A recent report written for the UK government[1] estimates that the per megawatt of energy could get down to 62.50 USD, assuming that the system would run for 100 years--according to Sabine Hossenfelder[2] this would make it cheaper than Nuclear and more expensive than ground based Solar.

[1] https://www.fnc.co.uk/discover-frazer-nash/news/frazer-nash-... https://news.ycombinator.com/item?id=36177739

[2] https://www.youtube.com/watch?v=3ZPrIE5ZMZA https://news.ycombinator.com/item?id=36177739

todd8··on Rocket Carrying North Korean Spy Satellite Crashes into Sea
In grad school I took a class from Robert Boyer and J Strother Moore (famous for Boyer-Moore string searching and the 2005 ACM Software System Award for the Boyer-Moore Theorem Prover). It was a long time ago, but I remember an anecdote that Boyer explained happened while working at NASA on the Apollo project. It is a good example of the simple things that can go wrong in space. (I hope I can explain it clearly and correctly, I took that class decades ago.)

At one point, to return to earth the command module must separate from the landing module (after it has been on the surface of the moon and back) and fire the thrusters that will return the astronauts and some moon rocks to earth. The astronauts flip some switches to start this sequence.

Shortly before the whole Apollo moon mission, programmers discovered a bug. The thruster doesn't know where the center of gravity of the orbiter is located, but it must adjust its gimbals so that the thrust is in line with the craft's center of gravity to prevent tumbling the spaceship. This is automatically done, rapidly at the startup of the thrusters, by firing and then wiggling the nozzle a bit to figure out the correct direction vector in line with the center of gravity by readings from gyros. It seems like this should work.

The bug is that there would be a delay between flipping the switch to fire the thrusters and the actual firing because, in zero-gravity, the fuel is just a big floating ball of liquid in the fuel tanks and consequently there is a delay of a few seconds while little maneuvering gas jets start accelerating the craft causing the fuel to move to the back of the tank (where the fuel lines are) and finally making its way into the nozzle of the trusters where it ignites automatically. Unfortunately, the software assumed that the thruster would ignite right away, and would wiggle the nozzle and get a completely wrong answer for the calculated center of gravity because the engine wasn't ignited yet. Then, with the nozzle pointed in the totally wrong direction, ignition would cause the craft to be pitched into a dangerous tumble while trying to leave lunar orbit. This bug wouldn't be obvious during testing on earth because the fuel would be at the bottom of the tank and ready to fire without the delay.

It was too late to patch the software so some instructions were taped next to the switches instructing the astronauts to put in the necessary delay manually.

todd8··on Whistleblower drops 100 GB of Tesla secrets to German news site
Tesla seems to be making progress on full self driving, but real self driving (cars without steering wheels) still seems quite distant. How will such a car respond to road workers redirecting traffic? How many times have you had to talk to someone outside of your car to obtain instructions on how to get around some obstacle, like a moving truck. I don't do such things every day or even every month, but there are occasions where it is necessary to take unmarked detours.

How would a self driving car get through heavy fog or snow covered roads when there are only very difficult to decipher hints to the road edges?

How will self-driving cars deal with humans that can perfectly predict their actions? I believe that bad drivers will take advantage of self-driving cars by cutting them off and failing to yield when they should.

Because human drivers have a sense of self preservation we can break the rules when we are about to be car-jacked or see an impending collision coming. Imagine how easy it is to obstruct a self-driving car for nefarious reasons.

I'm confident that, eventually, self-driving cars will address all of these issues to some degree, and that will mark a turning point where it is better to leave driving to the cars than average drivers. However, this doesn't mean I'm going to put my $100K car into a taxi pool to be used by (sometimes drunk) strangers; I don't buy the argument that the cost of buying such a car will pay for itself.

todd8··on Neanderthal Flute
A friend's wrote a book on prehistoric flutes. Her Ph.D. dissertation was on the subject, [1]. Unfortunately, I believe that it is out of print.

[1] Lana Neal, The Earliest Instrument: Ritual Power and Fertility Magic of the Flute in Upper Paleolithic Culture, https://www.amazon.com/Earliest-Instrument-Fertility-Paleoli...

todd8··on Who wants to be tracked?
Yes
todd8··on The Case for Bash (2021)
I'm a computer scientist/software engineer that has used primarily Unix or Linux systems since the 80's. I write shell scripts occasionally, but I just find them error prone enough that I'd rather use python than sh for complex scripts. Python has some packages that make working with files, directories, and processes tolerable and at least I can understand the string quoting rules in python.

Generally my order of preference for shell scripting tasks is: python > bash > pearl > tcl > sh > anything > AppleTalk.

todd8··on Who wants to be tracked?
Thanks...I'm think I'm too sensitive about it since this comes up every f'ing time.
todd8··on Who wants to be tracked?
Really? I didn't invent it for browsers, I invented it for distributed file systems before the "World Wide Web" had even been invented. You might as well have a talk with William Shockley or Vint Cerf.
todd8··on Who wants to be tracked?
I'm sure that many can make the same claim. In the 1980's, I was an operating systems architect working at IBM. I thought up many interesting (to me) innovations while working on the first couple of releases of the AIX on the IBM POWER hardware. It was a great job and I learned a lot doing it. I got to work with some really brilliant developers and computer scientists (a number from IBM Research).

One project I was responsible for was the development of a distributed file system for AIX. The goal was a distributed file system that addressed some of the weaknesses found in other distributed file systems at the time. Our chief competitor was Sun's NFS distributed file system. NFS was a really nice design. It was well integrated into the operating system and quite reliable because it utilized a (mostly) stateless server. This had a number of performance and security implications along with some file system semantics over NFS that didn't match local file system semantics. We wanted to introduce state for the server to address these issues and thought of a number of complex protocols to manage it in the presence of unreliable clients. That's when I thought up the idea of making the clients keep their own state to be restored when they reconnected to the server. I protected this state from manipulation by the client by encrypting it. I didn't call them cookies, I called them tokens.

This design was patented by IBM and I was one of the two inventors on the patent. This patent was owned by IBM and years later they gave a special award for this patent because it decided that it was one of IBM's most important patents. (They wouldn't have done this unless the patent had held up to scrutiny or legal challenges). Unfortunately, by that time I had already left IBM to start my own company--I was at the top of my game and had confidence that I could create a software product of some kind that would be successful--so I missed out on the financial award for the patent. By then, I was at my new company and already in competition with IBM.

By now, the patent should be long expired. Interestingly, IBM ended up buying my company around seven years after I and a partner started it.

I was very aware of the academic literature and industrial practice during this time so I do believe that my invention does reflect original work that ended up with a very significant impact.

From a more personal perspective, the invention didn't financially benefit me. The work that I did at my company own was more creative, inventive, technically impactful, and financially important to me. For example, Austin Ventures has indicated that my company was the start of Austin becoming an important high-tech location, but none of that was related to the cookie.

todd8··on Who wants to be tracked?
My spouse will sometimes mention in conversation with others that I invented the cookie. This always puts me on the spot, and I have to enter into a long explanation of the what and the why of cookies least they believe that I some sort of evil software hacker. (Now for a short explanation so that HN readers don’t think that I’m an evil hacker: I invented them, with the help of a colleague, while at IBM where we were designing a distributed file system. This was before the advent of the World Wide Web.)
todd8··on The RedMonk Programming Language Rankings: January 2023
I enjoy looking over the 2D chart of programming language popularity, but the chart raises some questions:

-- How are there more Roff projects on GitHub than there are projects in Julia or Haskell or Perl? I haven't thought about Roff for decades.

-- Why are Zig and Nim so far apart on the chart?

-- What circumstances are putting some languages above the diagonal while others are below it? Go and Rust are below the diagonal while R, Processing, Matlab, Scheme and Racket are above the diagonal?

todd8··on macOS Apps in Rust
This is off topic, but thinking about portable desktop apps, why didn’t JavaFx become more popular? What is JetBrains using for its sophisticated GUIs? Is it just Swing? It would be great if Rust could be used to write portable high quality desktop apps.
todd8··on I’m in Wyoming to celebrate the next nuclear breakthrough
Today I posted this https://news.ycombinator.com/item?id=35840591 to HN. It is a YouTube video with some straightforward statistics that, in my opinion, imply a very rough road ahead for Solar and Wind.

The basic problem confronting us is the need for so many mined materials to build future solar, wind, and storage facilities. It's really quite daunting.

todd8··on Waymo One doubles service area in Phoenix, continues growing in SF
In these cases, bus vs cruise vehicles, the bus is often helpless to fix the problem, and a stalemate ensues. As I understand it, bus drivers in SF are not allowed to backup without the presence of a supervisor (it makes sense that you'd want someone watching the back of the bus) so it is up to the cruise vehicle to backtrack if they somehow meet up head-to-head. Of course the cruise vehicle is like an Uber driven by Spock--perfectly logical and without emotion--and will just is sit waiting until the path ahead is clear.
todd8··on Why split lexing and parsing into two separate phases?
Yes absolutely, I was just pointing out that there were in those days people still committed to bottom up parsing despite the advantages of top down approaches. The bottom up parsing with LR parsers that I was familiar with always used a table driven approach for the language grammar and assumed a separate lexer, sometimes hand written and sometimes generated by a program like lex. To me, the effort saved by using lex and yacc was completely lost by having to incorporate extra work to get good error messages for users out of LR parsers.

Recursive descent over a character stream might have a negative performance impact, but I’m not sure of this considering the simple grammar involved in the lexical portion of the overall grammar and the ability of today’s tools to optimize function calls via inclining etc. If I was writing a compiler today for modern hardware, I would like to try using recursive descent on a single grammar that went all the down to the characters.

todd8··on Why split lexing and parsing into two separate phases?
Compilers used to be my favorite subject in CS (circa 1975) and back then I never saw a single case where lexing was handled in the parser. A few factors back then may have been responsible for this.

First memory was very limited by todays standards, say 30 to 60kb. By making lexing a separate pass, the source could be discarded before the parser started and the tokenized intermediate file written by the lexer could be read during the parsing pass. Typically, the compiler might keep the name table of all identifiers in memory between these passes.

Around the mid 70s, languages that could be compiled in a single pass were investigated. Pascal was one of these. Pascal didn’t support separate compilation either so the linking step was eliminated. Nevertheless, the early Pascal compilers still did lexing separate from parsing; I learned Pascal by studying the source for Wirth’s compiler (it had crazy inconsistent indenting).

The second reason lexing was done separately was performance. Touching every character of the input source file was a major bottleneck for compilers back then, so optimizing the lexer was perceived to be very important. By doing the lexing in a tight loop rather than being called once for ever token lots of overhead associated with these calls was eliminated.

Also, there was a questionable attraction to bottom up parsing. Knuth had shown how LR (left to right) shift-reduce parsers could parse a very large family of grammars efficiently around 1965. Everyone was enamored with them. I even wrote a set of FORTRAN programs that would construct the SLR tables suitable for a subset of LR parsable grammars. When lex and yacc applications came along, everyone thought that every compiler should be built this way (to be fair, Wirth and Per Brinch Hansen were both designing languages that could easily be parsed by recursive descent because their grammars were LL(1) a smaller family of grammars than LR(n)). I’ve never seen anyone try to use only a LR parser at the lexical level combined with the normal grammar parsing.

I went back to University for another graduate degree in 1984, and I was surprised to hear the professor that taught the compiler class say that everyone should be using lex and yacc for any compiler development. By then, in the real world, people had discovered that much more meaningful error messages were possible with LL or recursive descent (i.e. top down) parsing.

Now, performance and memory considerations are different. It’s practical for compilers to read an entire source file in a single read (or memory map the entire source file), saving all the round trips to the OS for reading input. Top down parsing provides better error messages and it fits well with parsing all the way down to the lexiems.

todd8··on The seven programming ur-languages (2021)
The comments here are interesting, lots of possibilities for other ur-languages. My suggestion is macro based languages. Macro based programming predates all programming languages other than ASM[1]. The simple macro systems, like early assemblers provided, aren't ur-languages, but once macros can expand other macros and generate definitions of new macros, the macro systems can become general purpose programming systems.

The two earliest macro systems that were clearly designed to be general purpose languages that I know of are Christopher Strachey's GPM[2] and Calvin Mooers TRAC[3] programming language. These languages appeared at roughly the same time, the mid 1960s. I prefer the syntax of TRAC, but otherwise they are almost isomorphic. TRAC was featured in Computer Lib/Dream Machines[4] by Ted Nelson where the author said it was one of the three important languages for programmers to learn. A good introduction to TRAC and it's implementation can be found in Études for Programmers[5].

Other more contemporary examples of macro programming languages are m4, and TeX. LaTeX is programmed in the TeX macro system.

[1] Daniel Weise and Roger Crew, "Programable Syntax Macros", ACM SIGPLAN, 1993, https://dl.acm.org/doi/pdf/10.1145/173262.155105

[2] Christopher Strachey, “A general purpose macrogenerator,” Computer Journal, 8(3), pp. 225-241, 1965

[3] Calvin Mooers, "TRAC, a procedure-describing language for the reactive typewriter", CACM, Vol 9(3), March 1966, pp. 215-219, https://dl.acm.org/doi/10.1145/365230.365270

[4] Ted Nelson, "Computer Lib/Dream Machines", 1974, Self-published. (There is a 2nd edition from Microsoft Press, but I'm only familiar with the 1st edition).

[5] Charles Wetherell, "Études for Programmers", 1978, Prentice Hall. (It's out of print and available from Amazon for $427. I'm going to have to start locking up my old books.)

todd8··on How to Design Programs 2nd Edition
There's a lot of speculation about the approach used by this book to teach programming. It's the book that my own daughter used as a freshman in college. It was her first programming class, and she ended up deciding to major in CS.

The programming language taught in this book is Scheme. Students are introduced to programming concepts and language features gradually and the assignments are intended to be implemented using a growing subset of Scheme features as the students learn the language. By the end of the semester my daughter was familiar with much of Scheme and was comfortable with subjects like recursion, lambda functions, list handling, map functions, and closures. I'm not sure but I don't believe that she learned about continuations or macros.

Some comments mention the "toy" languages used in the book, but these aren't really toys, just subsets of Scheme that provide guard rails to keep the students from wandering into parts of Scheme that they haven't yet learned.

Another notable feature of the How to Design Programs 2nd Edition is its introduction of a defined sequence of steps for breaking a problem down into parts that are implemented as collection of functions that make up the solution.

todd8··on Long before trees overtook the land, Earth was covered by prototaxites (2013)
I was thinking Zangarmarsh from World of Warcraft.
todd8··on Schools bought millions of Chromebooks and 3 years later they’re breaking down
You’re right!

I start thinking about my collection of laptops and amended my comment above.

todd8··on Schools bought millions of Chromebooks and 3 years later they’re breaking down
I do this all the time. Out of a dozen laptops around here (Apple, Dell, Lenovo) none have broken over the years. I usually just outgrow them, or the batteries lose their ability to hold a charge.

Thinking about this, I realize that all of my laptops fall into four categories: (1) MacBooks ——these are made of metal and are quite rigid and strong, (2) large screened Dells, too heavy to pick up comfortably with one hand, (3) Lenovo Thinkpads that are thin but very lightweight, and (4) a couple of Chromebooks that sit permanently on a desk for web use only and don’t get picked up. In all of these cases, there is little danger that I will injure them by handling them as you’ve described.

todd8··on Amazon investigates after high-value orders were switched for cheaper products
This has happened to me twice at brick at mortar stores. Now, I open packages before I check out where practical (like over the counter at a camera store) or as soon as I exit the store otherwise.

In one case, at Best Buy, I purchased a camera and at home I discovered a less expensive camera in the box than the one I paid for. Best Buy took care of it even though I brought it back around an hour after I purchased it.

My other experience was much worse. A local computer parts store sold me a tape drive and the box contained a cheaper model. They simply wouldn’t let me return or exchange it.

In general, my experience has been that the big box stores like Home Depot or Best Buy will take returns for something that doesn’t function properly without question while a small local store will sometime refuse. I’ve lived in the same city for decades and there is a ceiling fan store that I will not shop at because of an experience I had there twenty five years ago —- maybe I should drop the grudge at this point.

← PreviousPage 2 of 34Next →