7 ms·
The hardest program I've ever written (2015)
- sema4hacker 11mo ago> That handful of code took me almost a year to write. Formatting can be tough. See Knuth's extensive bug list for TEX from 1987 at https://yurichev.com/mirrors/knuth1989.pdf https://yurichev.com/mirrors/knuth1989.pdf to see the kind of tarpit one can get trapped in.
- cjfd 11mo agoOne can talk about about the technical side of writing a code formatter, but what about the ethical side? Automatically formatted code looks kind of okay but never great. Uniformity for the sake of uniformity. It is not a very humanistic.
- chaps 11mo agoThis might just be the most HN comment I've ever read.
- noir_lord 11mo agoIt's certainly an interesting take.
- deleted 11mo ago[deleted]
- 7thpower 11mo agoThere seem to be a lot of posts that attempt to cast seemingly mundane things through an “ethical” lens and I often wonder what the authors of them must be like in real life.
- kjs3 11mo agoYou do not want to get cornered by them at a party talking about their pet peeve.
- deleted 11mo ago[deleted]
- o11c 11mo agoThere are 3 major problems with automated code formatters: * Handling of multiple newlines to break sections, or none to group related functions (e.g. a getter with a setter). Sometimes it's even best to move functions around for better grouping. * They don't factor out an expression into a separate variable. * They destroy `git blame`. This one is avoided if the tooling has always enforced formatting.
- layer8 11mo agoRegarding the second one, a formatter shouldn’t be changing the AST. At most inserting parentheses/braces/semicolons for clarity, which doesn’t change the AST structurally (or, depending on one‘s definition of “AST”, doesn’t change it at all).
- o11c 11mo agoPerhaps, but it is absolutely relevant. Most of the horrible formatting results are due to the formatter trying really hard when the user really should introduce a variable.
- layer8 11mo agoTrue, formatters can only do so much. The purpose formatters is not to guarantee readable code, but to guarantee uniform code. Use of a formatter doesn’t relieve a programmer from taking care that the code is readable. But it ensures that everyone is using the same formatting conventions.
- dragonwriter 11mo ago> * They don't factor out an expression into a separate variable. That's...not formatting, and there's probably no good deterministic rule for when to do that, anyhow.
- zahlman 11mo ago> * They don't factor out an expression into a separate variable. * They implicitly enable people to write deeply nested code that lacks such factoring, without feeling like anything has gone wrong.
- mjsir911 11mo agoyeah, I've come to terms that I mostly do programming-as-an-art and that includes how my code is structured, and I'm on exactly the same page. In pragmatic business environments it's not worth the fuss but I never feel great about anything I make in those kinds of environments anyways, and I always appreciate being able to shine when there's no enforced code formatting.
- bartekpacia 11mo agoweirdest take on code formatting I've ever read imho uniformity of what the code looks like > some single person's opinion it's so satisfying to me when I just run "gofmt" and know the thing is formatted well.
- andrewflnr 11mo ago"Ethics" is overdramatizing it. The goal of a code formatter is not greatness, but adequacy, in a context where the code is a means to an end. They're particularly used in contexts where you may be sharing the project with people who don't care about formatting at all. Forcing me to work in or clean up the messes of my lazy co-workers is also, I would suggest, not very humanistic. Feel free to not use one in your art projects.
- wiseowise 11mo agoHumanistic is bikeshedding for weeks over new lines and “I feel like this is more readable”.
- cjfd 11mo agoThe bike shedding is optional once one accepts that code written by someone else might look a bit different from ones own. _Some_ conventions are beneficial, and one might discuss those, but one does not have to have complete uniformity. Bike shedding for weeks might happen and is not helpful. On the other side of this argument there are not-so-very-pleasant things as well. A: We follow this-and-this coding convention and we do not like wasting time on discussing it so we follow it to the letter. B: I don't like this small thing that I would like to write differently. A: We follow this-and-this coding convention and we do not like wasting time on discussing it so we follow it to the letter. B: You actually don't follow this-and-this coding convention because you are not following this-and-that rule. A: Yes, that is a change that I liked. One can easily end up with a very old coding convention that only the oldest developer likes so the oldest developer can now be dictator over everybody else.
- nkrisc 11mo agoWhat is the ethical dilemma presented?
- vbezhenar 11mo agoThe human might use a carefully selected mix of tabs and spaces to output a picture. And formatter will destroy it, thus destroying artist expression. Compare: #define/**/Q(x,y)r;char*q/* */=y#x","#y")",*p,x=*p%67;} /*-IOCCC2020-*/#include/* */<stdio.h>/*-BBQlock--*/ int(y),x,i,k,Q(s[9<<9/* 12 */];float(f)[3];void(Z) (){*f=r<0?r:-r;f[1]/* 11 1 */=42.5;f[2]=22.5;for (k=0;++k<39;*f/=(k/* 10 2 */%2?k:-k)*6875.5/i) y=f[1+k%2]+=*f;k=/* */f[2];p=s+k/2*86+y ;}int(main)(){p=/* 9 o-------> 3 */s;for(;i<1978;*q >32?k=i++/86-11/* / */,y=(750>r*r+k*k *4)*4+y/2,*p++=/* 8 L 4 */r<44?y?"+0X+0X" "+!"[y]-1:*q++/* 7 5 */:10:*q++)r=-41 +i%86;r=20;for/* 6 */(x=13;(i=3600* --x);*p++="XR"/* */"MOQSUWAY"[x%+ 10]-9,*p+=x/10/* */*41)Z();sscanf (__TIME__,"%d"/* \ / -------+ */":%d:%d",&k,&x ,&i);r=10;for(i/* \ / ------ | */+=(k*60+x)*60;r +18;*p=k%2?*p%2/* \ / ------ | */?59:44:*p>39?59 :39,i=r--?i:i%(+/* \ / ------ | */3600)*12)Z();for (p=s;*p;putchar(k/* X ------ | */%2&&k<14?q="End", printf("%c%c",224|/* __/ \__ | | */(21554>>k&3),"gCS" "gGMX"[k/2]+65),"E"/* / \ / \ | | */"Gh_BrG"[k/2]+64:*p ),++p)k,"#define/**/"/* \__/ \__/ +--+ */"Q(x,y)r;cha""r*q=y#" "x\",\"#y\")\",*p,x=*p"/* */"%67;}/*-IOCCC2020-*/#" "include<stdio.h>/*-BBQl"/* */"ock--*/int(y),x,i,k,Q(") and clang-formatted version: #define /**/ Q(x, y) \ r; \ char *q /* */ = y #x "," #y ")", *p, x = *p % 67; \ } /*-IOCCC2020-*/ #include /* */<stdio.h> /*-BBQlock--*/ int(y),x,i,k,Q(s[9<<9/* 12 */];float(f)[3];void(Z) (){ *f = r < 0 ? r : -r; f[1] /* 11 1 */ = 42.5; f[2] = 22.5; for (k = 0; ++k < 39; *f /= (k /* 10 2 */ % 2 ? k : -k) * 6875.5 / i) y = f[1 + k % 2] += *f; k = /* */ f[2]; p = s + k / 2 * 86 + y;}int(main)(){ p = /* 9 o-------> 3 */ s; for (; i < 1978; *q > 32 ? k = i++ / 86 - 11 /* / */, y = (750 > r * r + k * k * 4) * 4 + y / 2, *p++ = /* 8 L 4 */ r < 44 ? y ? "+0X+0X" "+!"[y] - 1 : *q++ /* 7 5 */ : 10 : *q++) r = -41 + i % 86; r = 20;for/* 6 */(x=13;(i=3600* --x);*p++="XR"/* */"MOQSUWAY"[x%+ 10]-9,*p+=x/10/* */*41) Z(); sscanf(__TIME__, "%d" /* \ / -------+ */ ":%d:%d", &k, &x, &i); r = 10; for (i /* \ / ------ | */ += (k * 60 + x) * 60; r + 18; *p = k % 2 ? *p % 2 /* \ / ------ | */ ? 59 : 44 : *p > 39 ? 59 : 39, i = r-- ? i : i % (+/* \ / ------ | */ 3600) * 12) Z(); for (p = s; *p; putchar(k /* X ------ | */ % 2 &&k < 14 ? q = "End", printf("%c%c", 224 | /* __/ \__ | | */ (21554 >> k & 3), "gCS" "gGMX"[k / 2] + 65), "E" /* / \ / \ | | */ "Gh_BrG"[k / 2] + 64 : *p), ++p)k,"#define/**/"/* \__/ \__/ +--+ */"Q(x,y)r;cha""r*q=y#" "x\",\"#y\")\",*p,x=*p"/* */"%67;}/*-IOCCC2020-*/#" "include<stdio.h>/*-BBQl"/* */"ock--*/int(y),x,i,k,Q(") The beauty is gone!
- jibal 11mo agoYou surely forgot the "/s". The uniformity is not merely for the sake of uniformity.
- mackeye 11mo agosemantic code style varies plenty between people; i can often tell who wrote which code, among the members of my research group, even though we format our code. i'd prefer to be recognized by my preference for short lambdas (vs. defs) and partial functions, than my preference to put if statements on one line.
- zero_shift 11mo agoI agree, actually. Humans are visual creatures and they take cues from the visual design of program code: alignment, grouping, density. All these things are used to signify meaning in product design, including digital design. But we are not allowed to "design" source code.
- dredmorbius 11mo agoEthical, or aesthetic? Both are branches of philosophy, but rather distinct from one another.
- tom_ 11mo agoInteresting comment. I always saw the formatting aspect as the sort of drudgery the computer could do for me. (As a bonus, it will always do it completely consistently.)
- b4ckup 11mo agoI once wrote a formatter for powerquery that's still in use today. It's a much simpler language and I took a simpler approach. It was a really fun problem to solve.
- PaulKeeble 11mo agoAbout the worst job on any enterprise software project is the PDF output, they always end up doing it for emails or something else and its a never ending list of bugs. Text formatting is a never ending list of problems since its so got a lot of vague inputs and a relatively strict output. Far too many little details go wrong.
- vbezhenar 11mo agoWith PDF, my best approach was to go very low level. I've used PDFKit and PDFBox libraries and both provide a way to output vector operations. It allows to implement extremely performant code. The resulting PDF is tiny and looks gorgeous (because it's vector). And you can implement anything. Code will be verbose, but it's worth it. I even think that it's viable to output PDF without any libraries. I've investigated that format a bit and it doesn't seem too complicated, at least for relatively dumb output.
- huflungdung 11mo ago[dead]
- kbbgl87 11mo agoThinking about phantomjs and rasterize brings back nightmares
- mikeday 11mo agoWe've spent twenty years working on HTML to PDF conversion and I expect we could easily spend another twenty years, so feel free to give Prince a try if you would rather avoid the headache :)
- twotwotwo 11mo agoAwesome. From curiosity: is Prince's core still written in Mercury? (Looked at old comments.)
- mikeday 11mo agoAbsolutely! The CSS support, layout engine, PDF output, and JavaScript interpreter are all written in Mercury, while the font support that was originally a mix of Mercury and C has now been rewritten as a standalone Rust project, Allsorts.
- mmaunder 11mo ago[flagged]
- jibal 11mo agoNo.
- mmaunder 11mo ago[flagged]
- Maxatar 11mo agoI'll just speak for myself, but I use Copilot with Visual Studio and C++ and Copilot does an excellent job of interpreting the instructions given to it and ensuring that the code I write is consistent with the coding style and standards specified in the instructions. I have it set to check my code live, as I write it, and it will reformat my code on the fly to break lines up, fix typos, insert code snippets, autocomplete documentation, etc... I will admit it was very awkward using it at first and I actually kind of hated it because it felt so intrusive, like having it modify code as I write it felt really distracting at first, but after maybe 2-3 days of doing it I got used to it and now I feel a lot more productive having it there. Especially for a language like C++ where sometimes the most menial syntax issue can have significant and hard to track down consequences, it's nice to have an LLM that can focus on these menial details while I focus on the higher level task.
- kjs3 11mo agoNo...it's that "can an LLM do it better" with no other commentary is perhaps the absolute lowest effort, lowest value comment possible on HN these days and mercifully gets an appropriate downvote. The condescending response to downvote is also par for the course from a particular sort of reader.
- andrewflnr 11mo agoSomeone complaining about lack of detailed response, when their own contribution was basically just "but what if LLM?", is very rich
- rafabulsing 11mo agoIn my brief experiments with Flutter, I must admit I didn't enjoy the experience of using the autoformatting. Not knocking the author of the tool at all, I can definitely see how absurdly hard it is to create something that does what it is trying to do. And I'm not against autoformatting in general either. I think gofmt works much better, and that's in large part because it tries to do less. With dart, I felt that very often, when time I saved a file after editing (which activated the formatter), the code would jump around a lot, even for very small edits sometimes. I actually found myself saving less often, as I found the sudden reorganizing kind of jarring and disorienting. Most of this, I felt like came from this wish of making the formatter keep lines inside a given width. While that's a goal I appreciate, I've come to think is one of those things that's better done manually. The same goes for the use of whitespace in general, other than trivial stuff like consistent indentation. There's actual, important meaning that can be conveyed in how you arrange things which I think is more important than having it always be exactly mathematically consistent. It's one of the reasons I still prefer ESLint over Prettier in JS land, also, even for stylistic rules. The fact that Prettier always rewrites the entire file from scratch with the parsed AST often ends up mangling some deliberate way that I'd arrange the code.
- fn-mote 11mo agoOne of the lessons I took from the formatters (Python, Go, Rust) is that enforcing the same style ends all of the drama - indeed, all of the thinking - about how to format code. I like that. I run my formatters manually, so I can’t comment on the jumps in code. That does seem jarring.
- rafabulsing 11mo agoAgain, I don't entirely disagree. Some choices are entirely stylistic: single vs double quotes for strings. Tabs vs spaces. Indentation width. Trailing commas. Those (and others) encode literally 0 meaning, and any time discussing those is time wasted, so they should be auto formatted away. But some things are not like that. Two statements being right against each other, or having an empty line between them, encodes information. In a big function call with many arguments, where do you add line breaks between arguments? That can convey information as well. As the posted link says, those are some of the most difficult scenarios for a formatter to try to deal with, and my point is that I think it's not worth the effort.
- georgeburdell 11mo agoMine was an automated file transfer system that had to be 100% reliable on an insanely unreliable network (~95% uptime). Took about 9 months of bug squashing after development was done. So many edge cases. I would probably never mention this in a job interview because I doubt most people would understand why it was so hard.
- bjoli 11mo agoI once wrote an inliner. When you have not done it, it seems simple. When you are doing it it is like trying to restrain a large rabid dog with a slippery leash. Now, I am not a programmer by trade, but I have a hard time thinking anyone would find it nice to write an inliner. At least not if you want the inliner to always make things faster.
- greazy 11mo agoI'm working on this exact same thing. Was your code ever published or did you blog about it?
- georgeburdell 11mo agoNope, just some internal facing code. The challenges boiled down to tracking what parts of the data got successfully sent to which recipients and how to get proof the data were transmitted correctly I wish I would have found a 3rd party tool to do all this, but I never did
- adammarples 11mo agoIs this not basically just torrenting?
- georgeburdell 11mo agoI guess, but some of the recipients are just 3rd party automated systems with a standard set of instructions, so I have no control over the protocol used
- Panzerschrek 11mo agoFor some time I tried to write a formatting tool for my programming language. After achieving first results I gave up. I have found that writing a formatter is surprisingly hard task. Operating on token-level can't provide good enough result, so a proper parser is necessary. Reusing existing parser isn't possible, since it ignores whitespaces and comments. Even more problems creates the necessity to preserve user-defined formatting in ambiguous cases. So I thought, that there is no reason trying to solve all these problems, since it requires too much time investments. But without solving all this a semi-working formatter isn't good enough to be useful and not annoying.
- skopje 11mo agoIts funny when you have programmed long enough to see the same language/app names recycled. Two examples that come to mind: Dart, which was an RTL validation scripting language in the 80's/90's used by CPU designers, and Elm, which was a mail program in Unix/Aix/SunOS in the 80's/90's. Even weirder, when googling for the "old" Dart, it referred to RTL as right-to-left, and not register transfer level.
- kccqzy 11mo ago> Note that “best” is a property of the entire statement being formatted. A line break changes the indentation of the remainder of the statement, which in turn affects which other line breaks are needed. I really don't like formatters where changing one small part of a large expression results in the entire expression formatted very differently. It's simply not version control friendly. Especially if the language encourages large statements like the pro example. I would rather accept a little bit of code ugliness in this case. Sure this then means that the way the code is formatted is path dependent (depends on the history of the code), but I think it's a reasonable compromise.
- kccqzy 11mo agoMost of the hardness of this program comes from a user-adjustable line length limit. The author on multiple occasions used a "blog-friendly 40-char line limit" which is of course insanely hard. The program can be made much much simpler if the line length is unlimited. And if that's not an option, the program can be made somewhat simpler by only allowing line limits that are reasonably large, such as 100 characters.
- juangacovas 11mo agoIMAP email parser for a ticket-like program. Even with abstractions and libraries, email can be such a pita...