> It turns a fun 1-hour game into a much longer fun game.
First procgen game I ever played was Starflight 2. (Pre-Internet era, so I couldn't get hold of Starflight 1. SF 2 spoils you, hard, on the major spoiler in SF 1, so if you're playing them from GOG or other sources then you should definitely play 1 before 2).
My ten-year-old mind was boggled. Hundreds of star systems, each one with several planets (usually), and you could land on each one? And explore the whole planet (in a very limited top-down 2D view, because this was the 1980's), harvesting minerals, and the map was quite a bit larger than what would fit on one screen? And it all fit onto one 720K floppy disk?!??!?
Now, of course, I know how they did it. But there was an actual game there. There were half-a-dozen alien races you could interact with (talk or shoot, as required), and there was an actual story. With a twist at the end that 40-year-old me would see coming, but 10-year-old me was shocked and amazed by. (And the twist in SF 2 wasn't even as good as the one in SF 1). And you progressed that story by following the gameplay loop:
- Fly around looking for planets with valuable minerals
- Land, scoop up what you can carry, fly home to sell them
- Gradually increase your ship's capabilities
Then eventually you would be able to make your way to planets with plot on them, at which the loop changes to:
- Collect plot-important artifacts, fly home to get them researched
- Research tells you "go talk to these aliens".
- Do a fetch quest so they like you, then talk to them.
- They tell you where to go to kick off the next plot point.
After only a few runs through that loop, it's on to:
- Find out where the Big Bad's home base is
- Find out where the MacGuffin is that lets you access that location
- Take MacGuffin to right place, fight Big Bad, save the day.
Crucially, once you had gone to talk to those plot-important aliens, you probably had enough resources that you didn't need to do much mining anymore. You might land when you spotted a target of opportunity — "Oh look, scanners say big pile of platinum just sitting there on a nearby planet, let's make a small detour" — but that was just to keep the bank account topped off. You could afford enough fuel to fly all the way across the map and back, so you could focus on the story.
And they timed it well: the core harvest-resources-and-upgrade-the-ship loop didn't have time to get boring before you were off to collect plot coupons. And there weren't too many plot coupons before it was time to find the MacGuffin, use it to beat the Big Bad, and save the day.
Star Control 2 did it really, really well, with better graphics since it was released a few years later. BTW, if you haven't played SC 2, search for "The Ur-Quan Masters" to download and play a totally free, legitimate, open-source version of the game, with full original assets since the copyright reverted back to the original creators who released it into the public domain for the UQM project to port to modern machines. I wish that had happened to all the old classics, but Star Control 2 is truly a good game. Definitely seek out The Ur-Quan Masters.
But before you do that, I would strongly recommend to play Starflight 1 and Starflight 2, to get a feel for the origins of the procgen-with-good-story genre that Star Control 2 did so very well.
P.S. Edited the "core gameplay loop" paragraph to better make it clear there were two or three loops, and you progressed forward through them, rarely having to go backwards.
> Other than maritime navigation, I can't think of many tasks where Mercator would be more useful than an equal-area projection.
Precisely why, I suspect, the US voted against the change. (One of the reasons, at least) I mean, gee, I wonder why the country with the world's largest navy* would prefer maps where you can draw a line on the map between two points and it's the actual compass direction? (Give or take a bit of weirdness near the poles, where the difference between the Earth's rotational pole and its magnetic pole actually matters in a way it doesn't matter below the polar circles).
It's just a symbolic vote, of course, and nobody's navy is going to stop using the so-useful-for-maritime-navigation Mercator just because of this UN vote. But still, I would bet that factored into the reasoning. How much? Who knows, I certainly couldn't say. Except to suspect that it was a non-trivial factor.
* Largest by tonnage — China and Russia have more total ships, with the US in third place by ship count, but the US has nearly half the number of aircraft carriers in the entire world, 11 out of a total of 23, and aircraft carriers are some of the heaviest ships out there. Numbers are from https://worldpopulationreview.com/country-rankings/largest-n...
I doubt that was a factor at all. As you say, voting for this wouldn’t change the maps a navy uses anyway. Besides, navies aren’t normally using world maps, they use maps for specific regions.
The vote was because the US is an intransigent rogue state at this point, and it doesn’t want to accept any outside influence whatsoever.
> ... most of the new testament has him [Jesus] as a fully separate person with his own separate agenda ...
Just want to correct a couple errors of fact here, by quoting from the sources that you're misunderstanding.
"And he withdrew from them about a stone’s throw, and knelt down and prayed, saying, 'Father, if you are willing, remove this cup from me. Nevertheless, not my will, but yours, be done.'" - Luke 22:41-42 (copied from https://biblehub.com/esv/luke/22.htm)
He doesn't want to suffer and die on the cross. Yet he chooses to serve the Father's agenda, not his own.
And note that, if you read just a few more sentences, you discover that this statement caused the Jews listening to him to pick up stones to stone him (for anyone who doesn't know, stoning was a method of execution: they intended to kill him). He asks (verse 32) why they want to stone him, and they reply (verse 33) that it's for blasphemy — "because you, being a man, make yourself God."
Finally, I want to address one other point in what you said:
> Christianity, if you ask anyone besides a christian, is polytheistic.
It's true that if you ask most people who are not Christians, most (not all, but most) will tell you that Christians worship three gods. But consider this: if you want to find out about Buddhist teaching, who would be a better source for explaining it to you correctly, a Buddhist, or a non-Buddhist? If you want to find out about Jewish teaching, who would be more informed about it, a religious Jew, or a non-Jew? (The word "Jew" is ambiguous, referring to both a religion and an ethnicity — so I use the term "religious Jew" to distinguish people who follow the religion from people who are ethnically Jewish but don't follow the Jewish religion). If you want to be well-informed about Islam, who would explain it to you better, a Muslim, or a non-Muslim? And if you want to understand what Christianity actually teaches, who's more likely to be correct about it, a Christian or a non-Christian?
P.S. To explain just a little further, the teaching of the Trinity is indeed one of the most complex teachings of Christianity to fully grasp, and there have been countless arguments and debates about it over the centuries. The council at Nicaea in AD 325, which formalized the Nicene Creed, did not completely settle that — some people continued to argue over the doctrine later — but it pretty well cemented the official church position. That the Father, the Son, and the Holy Spirit ("Holy Ghost" in older English texts, but "Holy Spirit" in modern English) are both three and one. The modern English translation of the Nicene Creed is probably worth quoting here (at least the relevant bits) so people can see what the actual teaching is:
"I believe in one God, the Father almighty ... I believe in one Lord Jesus Christ, the Only Begotten Son of God, born of the Father before all ages. God from God, Light from Light, true God from true God, begotten, not made, consubstantial [which means "of one being, of one nature"] with the Father ... I believe in the Holy Spirit, the Lord, the giver of life, who proceeds from the Father and the Son, who with the Father and the Son is adored and glorified ..." (Source: https://www.usccb.org/prayers/nicene-creed, though there are multiple translations, e.g. the translation I'm most familiar with says "of one being with the Father" rather than "consubstantial with the Father").
And before I quit writing this P.S., I want to mention one kind of awesome story about the council of Nicaea. Which is the story about what St. Nicholas allegedly did there. (Yes, the St. Nicholas whose life inspired the story of Santa Claus). Sadly, the story is probably not true, since Nicholas's name does not appear in any of the lists of attendees that have survived... but it's an awesome story anyway. The story goes that Arius was standing in front of the council arguing his position, which was that Jesus had not existed eternally, but was created by God the Father at one point. (The famous phrase is "There was a time when he was not".) That part is certainly historically true. What is likely not historical is the rest of the story: that Nicholas got so mad at Arius's denial of the divinity of Jesus that he got up and slapped (some sources say "punched") Arius in the face.
Which leads to this historical-humor variation on a famous American Christmas carol:
He knows when you are sleeping,
He knows when you're awake,
He knows when you've denied the divinity of Christ,
So if you're an Arian, DUCK!
P.P.S. One last note. My intention here is not to argue, but to explain. I am happy to argue/debate with anyone who wants to discuss further, but HN is not the right place for literal religious debate. If you want to argue or debate about Christian teaching, feel free to contact me at (my HN username) at pobox dot com. (And if you just write a note here that you've done so, that will avoid the possibility of my missing your email: my pobox address gets a lot of email).
It's also a very physical play with a large number of onstage fights. Fight choreography is some of the most dangerous stuff to do onstage: a single mistake and someone can easily be hit by a sword that was supposed to just barely miss them. And although stage-fighting weapons are naturally blunted, they're still big heavy metal rods that can bruise or break bones if you get hit by them. (See my P.S. for a funny story about that, BTW — nobody was injured in that one, but it came close a couple times).
There are some scenes in Macbeth that can be turned into offstage fighting if the director wants to minimize risk to the actors; for example, the battle with Macdonwald (not a typo) in Act 1 Scene 2 is reported to King Duncan, but not seen onstage in most productions. (Though an ambitious director might choose to have a mass battle depicted during the transition from Scene 1 to Scene 2, then have the combatants leave when Duncan walks onstage to hear the report). But there are three scenes that explicitly call for an onstage fight:
Act 3, Scene 3: three hired killers attack Banquo and his son; Banquo is killed but the son manages to escape. This all happens onstage.
Act 5, Scene 7: Macbeth fights young Siward, and kills him.
Act 5, Scene 8: Macbeth fights Macduff, and it's a long fight. They fight once, pause to exchange some words while both are gasping for breath, then they fight again. The stage directions call for them to exit the stage still fighting, then come back onstage still fighting, just in time for the audience to see Macduff kill Macbeth.
With three swordfights that must happen onstage, the potential for accidents is a lot higher than for most of Shakespeare's plays.
On the other hand, Romeo and Juliet has a similar number of fights, as does Hamlet — yet neither of them has acquired the same reputation. So it's also possible that there's an element of self-fulfilling prophecy going on here: actors who are worried about getting hurt might not have their full attention on the fight choreography, making them more prone to make mistakes that do actually result in injury.
P.S. Now for the funny story I mentioned. If you haven't seen The Court Jester starring Danny Kaye as the protagonist and Basil Rathbone as the villain, go watch it; it's hilarious, and it deserves to be more widely-known than it is. In the final swordfight between Kaye's character and Rathbone's, the fight ranges all over the castle, and for plot reasons, Kaye's character is alternating between fighting expertly, and making wild, amateurish swings with no skill at all. Thing is, Rathbone was an expert fencer, and helped teach Kaye (who had no fencing experience) how to fight. Now, usually in a swordfight scene, they would substitute a stuntman to double for the actor when the actor's face isn't visible. But in the scenes where Kaye's face is visible and Rathbone's isn't, it's still Basil Rathbone doing the fighting — because Kaye was so inexperienced that he was likely to make mistakes, and Rathbone didn't want anyone less experienced than himself facing an inexperienced actor in a dangerous fight scene. (In fact, if you have a lot of experience with fight choreography, you can probably spot the times when Kaye came very close to actually hitting Rathbone for real, and if Rathbone had been less experienced he might very well have been injured).
P.S. Another reason why Macbeth might have more injuries than either Hamlet or Romeo and Juliet is the setting. In both Romeo and Juliet and in Hamlet they're fencing with rapiers, appropriately to the setting. But in Macbeth they're in the Scottish highlands, and a rapier just wouldn't look right. I don't believe Shakespeare ever explicitly specified what kinds of swords the characters in Macbeth are fighting with, but traditionally they've used either longswords (two-handed) or arming swords (one-handed swords, which are what you might think "longsword" means if you came to your knowledge of weaponry through D&D or other RPGs). Both of which are heavier (especially the longswords) than a rapier, and easier to accidentally injure your opponent with (broken bones, concussions, etc) than a blunted stage rapier.
So that fact alone might help explain why injuries tend to be higher in stage productions of Macbeth. It's just inherently more dangerous to perform than the rest of Shakespeare's plays.
2^27 is 128 megabytes. How much RAM do you want the decompressor to have to allocate for every file? Especially since you can't tell, by looking only at the file size of a compressed file, how many bytes it will decompress to. You could read the file header, but if it's a malicious "zip bomb" type of file, the header could be lying.
If the header says the file is smaller than it really is, you've already allocated a small widow by the time you realize it lied, so it doesn't harm you here.
If the header says the file is bigger than it really is, it can get you to allocate a pointlessly large window. But if a large allocation is the goal, they can make the file actually decompress that big without affecting the compressed size. So lying is pointless.
Or you just forbid mixing spaces and tabs in the same indentation sequence, the way most whitespace-sensitive languages seem to end up doing. Or you make a slightly more reasonable rule: spaces may follow tabs, but no tabs may follow a space. That's at least unambiguous.
Oh, that's really elegant! I've got a whitespace sensitive language of my own, and I think I'll change it to use that rule! Thanks!
(Until now, I went with the standard approach: Remember the leading whitespace of the previous line. Then compare with the new line's leading whitespace: If they are the same, then no change in indentation. If the old one is a prefix of the new one, it's an indent. If the new one is a prefix of the old one, it's a dedent. If neither, it's an error)
That seems like a decent way to handle the mixed-spaces-and-tabs scenario, even between lines: one line starts with `<tab><tab>`, the next line `<tab><tab><sp><sp><sp><sp>`, that's an indent. (Probably someone who likes 4-space indents and 8-space tab characters). Follow that up with `<sp>*12` and that looks like the same indent to someone who uses 4-space tabs, but not the same indent to someone who uses 8-space tabs.
So your proposed prefix-matching rule would correctly flag that scenario, forcing people stop and figure it out.
EDIT to add this P.S.: Actually, my "spaces may follow a tab but tabs may not follow a space" rule, while elegant, is incomplete. Your prefix-matching rule is actually necessary in order to deal with the "two tabs on one line, twelve spaces on the next line" situation. That would be legal under the "spaces may follow a tab but tabs may not follow a space" rule, but it's ambiguous whether that's an indent or a dedent. If tabs mean eight spaces then it's going from 16 to 12, a dedent; if tabs mean four spaces then it's going from 8 to 12, an indent.
But it also feels arbitrary and annoyingly restrictive. On top of that there are at least 25 whitespace codepoints in UTF. Should your language really be opinionated about when, where, and in what order (for example) the "mongolian vowel separator" appears?
I mean, obviously that one should only appear within Mongolian text and not within indentation.
To state explicitly what should be implicitly obvious, there is no valid reason (that I'm aware of, I welcome any non-facetious correction) to use any character except U+0009 and U+0020 within indentation. Horizontal Record Separator? Zero-width joiner? Language-specific whitespace characters like your example? All make sense within human text (well, maybe not HRS), but in programming, they should be eschewed in favor of the characters that can be typed in every single keyboard layout in the world. Even languages that don't put spaces between words, such as Thai, still put spaces between sentences (or comma phrases) and therefore keep the space bar in their keyboard layout.
And since mixing tabs and spaces (even between lines, where some lines are tab-indented and some are space-indented) creates problems for whitespace-sensitive language, there's a reason why every whitespace-sensitive language I'm aware of has tended to either outright forbid, or at least discourage, U+0009 and its ambiguous meaning (since its meaning isn't clear until you know people's editor configurations, which are usually not available to the validation code running in CI or on other people's machines).
> To state explicitly what should be implicitly obvious, there is no valid reason ...
There doesn't need to be an articulable reason. Or rather there's generally no expectation that a central authority will be able to reliably enumerate such. Everything should default to being permitted and only ever be restricted for good reason.
But since you asked. U+2003 for example carries formatting information. Maybe an editor could be written (or even already exists) that would find that useful. Who is any third party to dictate that?
U+00A0 similarly communicates information about the desired formatting and I can see no reason it would be unreasonable for someone to use it nor why its use should pose a technical challenge to a compiler.
> creates problems for whitespace-sensitive langauge
Does it? That seems like an invented problem to me. You have a running prefix composed of arbitrary whitespace characters. Any change in that prefix is a change in the level of indentation. You can add or remove arbitrary amounts from the end of the prefix. In the event you remove from it the result must exactly match the previous stack level. What's so complicated about this?
> outright forbid, or at least discourage, U+0009 and its ambiguous meaning (since its meaning isn't clear until you know people's editor configurations ...
Did you mix up your code points there? It's space that's ambiguous, not tab.
Regardless I think that a compiler worrying about the specifics of text editors or other tooling would be backward information flow and a massive abstraction violation. Semantic meaning is entirely dictated by the compiler, not the other way around. There's no convincing reason (IMO) to impose restrictions that aren't technically necessary or to otherwise needlessly employ solutions that would reduce generalization.
> Did you mix up your code points there? It's space that's ambiguous, not tab.
Space is always the same width, but tab means a variable number of spaces (usually either 4 or 8, but I've seen 3 before) depending on people's editor configuration.
What makes you say that the space character, U+0020, is ambiguous?
A single tab always indicates (AFAIK, in common usage) a single level of indentation. Whereas depending on editor configuration a single level of indentation could be represented by any number of spaces - commonly somewhere between 4 and 8, but who can say?
Tab never "means" any number of spaces. How it gets displayed varies but the meaning (of any character, not just tab) can only ever be determined by usage, not display choices (at least for any sane way of doing things). Otherwise what would you make of escape sequences or binary files? Or constructs such as a nonbreaking space?
What business does a compiler have worrying about display width? As I said earlier worrying about the specifics of the editor or other tooling would be backwards information flow and a massive abstraction violation. What if I choose to program in a variable width font? (For the record writing that left me feeling disgusted.)
Got it. You're looking at the problem from the other direction. Yes, tabs are unambiguous if they're the only thing used for indentation. It's when some people use tabs and others use spaces that ambiguity arises.
But there are other cases where the variable-width nature of tabs can create ambiguity all by itself. Take this example from R7RS small:
But to everyone else using a different editor, where the convention is "the tab character just advances to the next multiple of T" (where T is usually 4 or 8), then the second and third lines won't be correctly aligned. And then instead of being able to use the indentation as a visual reference and ignore the parentheses, those people will have to revert to counting parentheses in order to figure out what S-expression each form is part of. Granted, in this simple example that's not hard, but imagine that `cond` nested deep inside a larger expression including a `call/cc` and a `let` or two, rather than being at the top level where it's easy to read.
Here, the ambiguity is because the tab character needs to have a width of six characters in order to align with the text `(cond `. If that had been an `(if ` with just two forms (omitting the `(else 'equal)` case) then the tab would have needed to have a width of four characters. A smart editor that reads the Lisp code and can interpret `<tab>` as meaning "indent this form to align with the form on the line above", but any context that isn't syntax-aware, such as a git diff, will not align those tabs correctly.
Which is why I consider tabs to be ambiguous, because I'm looking at it from the perspective of "how many spaces does this correspond to", and spaces to be unambiguous.
> It's when some people use tabs and others use spaces that ambiguity arises.
I don't think so? Assuming we're talking about significant whitespace here and assuming we're maintaining a consistent prefix within a given block then AFAICT there is never any ambiguity. To argue otherwise it seems to me that one of two things must be true.
It could be that spaces are equally ambiguous because in theory you can use any number of either of them for a single level of indentation. While that isn't syntactically ambiguous I suppose it might bother some people.
Or it could be that the compiler is concerning itself with how different editors might choose to display a given line of text in different instances which is (IMO) fundamentally broken and a path down which only madness lies (and anyway suffers from the variable width font conundrum I pointed out earlier).
If you have any counterexamples I'd be interested to see them.
> But to everyone else using a different editor, where the convention is "the tab character just advances to the next multiple of T" (where T is usually 4 or 8), then the second and third lines won't be correctly aligned.
No, you've got a misconception here. An editor should never go out of its way to align that. That would be broken by design. Tabs are never for alignment. Never. Notice that syntactically no new scope has been introduced. So you are still at the same indentation level as the `cond` and you are aligning (thus you _must_ use spaces) a list of expressions that has been split one per line.
I think the entire controversy arises because people (incorrectly IMO) get the idea in their heads that a tab character has some fixed width. It does not. In the context of source code it communicates the concept of indentation, never anything more. It's entirely up to the editor how exactly to display indented code.
> Which is why I consider tabs to be ambiguous, because I'm looking at it from the perspective of "how many spaces does this correspond to", and spaces to be unambiguous.
Right, but that is in my view misguided and anyhow is not of any concern to the compiler. Recall that the original topic and my contention had to do with the possibility of syntactic ambiguity in a language with significant whitespace, not with formatting inconsistencies between different programmers.
The counterexample I've personally seen is multiple people editing the same file with different editors. The first person has his editor configured to indent with tab characters, and he writes Python code like this:
Now a second guy edits the file. His editor is configured to indent with spaces. He adds `do_something_else()`, and doesn't notice that the code block no longer has a consistent prefix:
Notice that because I've used five characters to type `<tab>`, it is already visually obvious that this is incorrectly indented. But that wasn't obvious to guy number two, because this is what he saw on his screen:
def example():
if True:
do_something()
do_something_else()
The compiler itself isn't per se concerning itself with how different editors have chosen to display tab characters. But in practice, it has to decide "is the do_something_else() line part of the `if True` block, or not?" And so it has to have some opinion on tab characters. Here, that opinion will be "Inconsistent mixing of tabs and spaces in same file, impossible to know programmer intent, refusing to guess; raise TabError exception here".
The use of .editorconfig files should, in theory, solve this. But just yesterday I had another file, thankfully one where whitespace was not significant. The .editorconfig file said "Indent with tab characters", so my editor, when I opened a new line, indented it with tab characters. But the file was actually indented with spaces, and nobody had fixed the .editorconfig file to say "indent with tab characters... except for this file which is indented with spaces".
Editor misconfiguration in both cases. Not strictly the couterexamples you were asking about. But the Python example, although made up, is reflective of actual situations I've seen. People with different editors editing a file, not paying attention to whitespace, and ending up with ambiguity where the width of a tab character would actually make a difference to whether a line visually appears lined up with its indentation block or a different one.
Tabs are great for indentation in theory. In practice, I've personally seen more pain than gain from files that used them.
Surely tabs are only ambiguous if one considers the point of indentation to be to align things visually in relation to each other, as opposed to just being, y'know, indented.
Besides, I'm sure many people would look at your Scheme snippet and argue that it's not really about indentation as much as alignment of the subforms, because in a Lisp those two things are basically equivalent, and that the distinction between indentation and alignment is mostly a thing for the curly-brace or otherwise ALGOL-esque languages like Pascal or in this case Python. And in those cases the use of "tabs for indentation, spaces for alignment" is fairly popular although I don't frankly know if many editors actually support that.
I do however think that this whole discussion of spaces Vs tabs is pretty asinine and mostly just stems from people just wanting to align code text visually across lines. It's the same way people insist on monospaced fonts even though one could easily make the argument that proportional fonts are easier to read. Oh well, even I'm not _that_ deprived.
> the use of "tabs for indentation, spaces for alignment" is fairly popular although I don't frankly know if many editors actually support that.
It all works swimmingly until you introduce a nested scope (indentation, tabs) in the middle of an aligned scope (spaces). At that point it still works in the sense that everything is correctly aligned however depending on the editor the tabs might not all have the same width if you aren't able to disable tabstop.
So it isn't generally recommended for lisps in practice (because most common editors will correctly align any given block but when considered in whole the formatting will be inconsistent) but poses near zero problems for most c like languages. (If you're determined you can manage to create problems in a c like by nesting an anonymous lambda within an aligned list of statements or similar such shenanigans. However pretending that python or c++ is a lisp is generally frowned upon so in practice all tabs can be expected to appear to the left of any spaces.)
The other problem I've personally seen with "tabs for indentation, spaces for alignment" is when your editor destroys your tab-space mix when it adjusts the indentation. I've personally seen an editor, I believe VS Code but I don't remember for certain (EDIT: on second thought it was probably Visual Studio, as my memory is placing me in an office I worked in around 2010 or 2011, before VS Code was created), turn a `<tab><tab><sp><sp>...<sp><sp>` line into `<tab><tab><tab><tab>...<tab>` when I intended or dedented it as part of a code block. I.e., I added or removed an `if:`, highlighted a section of code, and pressed the Tab or Shift-Tab shortcuts. And boom, that section of code was no longer in correct "tabs for indentation, spaces for alignment" syntax: the editor had converted a certain number of alignment spaces into tabs.
That was one of the moments that made me move away from tab characters in all circumstances. Because the only way to prevent that sort of thing from happening would be either to fix the editor bug (which I don't have time to do), or to turn on visible whitespace and pay close attention to whitespace every time I make an indentation change, knowing that the editor will sometimes do the wrong thing. I don't want to have to pay close attention to whitespace, and the only way I've found not to have to pay close attention is to either never align things at all, or never use tab characters. Tabs for indentation and spaces for alignment works great in theory, but in practice I have found I can't trust major editors to handle it right.
Truly, indentation is the moveable feast. Even on ancient typewriters, you could adjust your tabs depending on what you are doing. And people who have dissimilar tastes in tabbage will certainly write stuff that doesn't appear that great in each others' editors.
> What business does a compiler have worrying about display width?
The business of the compiler is to insure that code that it deems acceptable is not ambiguous to different users. Since people can set their own tab spacing, display of tabs is, in an indentation-sensitive language, inherently ambiguous.
> What if I choose to program in a variable width font?
As long as the spacing of any prepended whitespace doesn't arbitrarily change depending on the phase of the moon, the compiler shouldn't (and Python doesn't) give a rat's ass about your display preferences.
The only important thing here is that the location of the left margin on every line is meaningful, both to the compiler, and to any viewers of your code.
> people who have dissimilar tastes in tabbage will certainly write stuff that doesn't appear that great in each others' editors.
Not for code, no. People will do that for spaces. For tabs it's a 1:1 correspondence with indentation level with any visual adjustments done by the editor.
Reading between the lines I suspect you are operating with the flawed idea of using tabs for alignment. One must never use tabs for alignment purposes because they very explicitly do not have a fixed width. (They have a consistent width within a document at any given point in time but it is entirely arbitrary and can change at any time.)
> insure that code that it deems acceptable is not ambiguous to different users ... display of tabs
A compiler never has any control over display. It must ensure no _semantic_ ambiguity. And indeed there isn't any to be found here. Even in python where you can introduce an arbitrary amount of whitespace when going up a level of indentation there is never any semantic ambiguity.
In short you are confused about the division of labor within the stack of abstractions.
> The only important thing here is that the location of the left margin on every line is meaningful, both to the compiler, and to any viewers of your code.
I'd dispute that the compiler needs to care about where your editor places the left margin. However rather than argue about bizarre hypothetical text editors that do unhinged things when displaying whitespace for no apparent reason, I'll instead observe that it seems to follow from what you said that you actually agree with me. As long as the prefix remains consistent across a given level of indentation then there's no cause for concern.
> I'll instead observe that it seems to follow from what you said that you actually agree with me. As long as the prefix remains consistent across a given level of indentation then there's no cause for concern.
No, I vehemently disagree with most of what you wrote. We certainly agree on basic things that tabs do not have a fixed width, and that a "compiler never has any control over (source code) display." (What a bizarre idea; whoever said it did?)
> I'd dispute that the compiler needs to care about where your editor places the left margin.
This isn't just about editors. I well remember green-bar.
> As long as the prefix remains consistent across a given level of indentation then there's no cause for concern.
No, if someone uses 8 character tabs, and then wants to space over half a tab for visual reasons, things completely break. We probably agree that's wrong, and that the answer is some variant of the answer to "Doc, it hurts when I do this" and I maintain the answer is to dispense with tabs completely.
Look the tabs-vs-spaces war is as old as the big-endian/little-endian war, and I am probably older than you. We'll probably never convince each other of any of this. Have a good day.
I could not successfully search for green-bar; I was turning up a brand of rebar made from fiberglass and various vegan bars and restaurants in different cities... but nothing related to coding or text editing. Do you have a link handy that would explain what the green-bar you're referring to is? Or, failing that, could I ask you for a brief (one or two sentences) explanation/summary? Would be appreciated. (UPDATE: Figured it out, see P.S. below)
BTW, if you've been reading my responses you'll see that I've landed in the same "get rid of tab characters" camp, because while they're nice in theory, they cause pain in practice.
EDIT to add this P.S.: Figured it out. I eventually came across https://elpa.gnu.org/packages/greenbar.html which mentioned the alternating white and green bands of color on old printer paper. I remember those, but I never heard them called "green-bar" which is why I couldn't place the term.
Sorry, didn't mean to send anybody on a wild goose chase. Glad you found a reference, and also somewhat glad that the reference says that the the term was "often" used -- maybe I'm not quite ready for the dementia ward yet?
> BTW, if you've been reading my responses you'll see that I've landed in the same "get rid of tab characters" camp, because while they're nice in theory, they cause pain in practice.
I had to go back and look. You obviously have more patience than I do for this sort of debate. :-)
I don't think people who fall down on the tab side of the debate have thought things through. Tabs are about alignment, of course, but why did we transport the typewriter alignment to printers? (Many printers had escape sequences that let you set the tab spacing.) Arguably, it was to save computation time, storage space, data transmission time, and even (for faster printers) to make your print job come out faster. People forget how precious all those were.
Today, a tab key on a keyboard is a perfectly cromulent method to get to your next alignment boundary, but there's a reason that every single usable code editor lets you program the tab key to emit a certain number of spaces.
I'm sure it was often used, but I spent a lot of my childhood and early adolescence in the non-English-speaking country where my father worked for many years. So "green-bar paper" is not the only apparently-commonly-used English term that I had to learn later in life, since when I was growing up, I heard English mostly from my parents and coworkers, and that's not a term that they happened to use a lot. So although it's my native tongue, I'm constantly finding holes in my vocabulary — usually 80's or 90's slang terms that my (extensive) reading habit couldn't teach me because most of the English-language books I had access to in the 80's or 90's were published in the 1970's or earlier.
In other words, don't take my not knowing a term as evidence that it wasn't commonly used; my childhood was unusual by the standards of most Americans. :-)
How so? In what scenario would you ever need to use a sequence like <tab><space><tab> in indentation in your source code? Let alone using esoteric Unicode whitespace characters for indentation. I think it is perfectly reasonable for the language to make the restriction that indentation must be either all tabs, tabs followed by spaces, or all spaces.
> In what scenario would you ever need to use a sequence like <tab><space><tab> in indentation in your source code?
Writing a lisp in an editor that doesn't do boneheaded things with tabs? That's the only one I've personally run into but lack of imagination is hardly a good excuse to implement arbitrary restrictions.
> Let alone using esoteric Unicode whitespace characters for indentation.
How do you know what's esoteric in other countries? I certainly don't. I'm not an expert in linguistics but I'm sure that people everywhere in the world write computer programs at this point.
> I think it is perfectly reasonable ...
Without any concrete justification? Why would entirely artificial restrictions ever be seen as reasonable?
What "boneheaded things with tabs" are you referring to? The picture I'm piecing together from your comments suggests that you may use tab characters in a different way than most people seem to, so I'd quite like a further explanation of how you use tab characters and how you expect an editor to handle them.
> you may use tab characters in a different way than most people seem to
As far as I'm aware there are three primary and entirely independent uses for tabs. Indentation, field separation, and typesetting. When it comes to typesetting and also to display of fields with a narrow maximum width the concept of a tabstop is useful.
Boneheaded things with tabs was in reference to code editors (where tabs are more or less exclusively used for indentation) most often failing to provide the ability to disable tabstop. In practice this generally hasn't been a point of friction because until fairly recently the most popular languages (ie C & co) didn't support constructs that would lead to adding any indentation outside of the prefix of a line.
Agreed... but see my Lisp example in https://news.ycombinator.com/item?id=49593406 for a place where tabs end up unavoidably ambiguous. Because in that `cond` example the tabs look like they're used for indentation, but they're actually being used for alignment, something that falls more under typesetting than under indentation. A smart editor that has read the Lisp code (note that I'm using "read" in its Lisp meaning, i.e. "parsed into a syntax tree") can make those tab characters correctly align the forms the way you'd want them to be aligned for maximum understanding... but really, you would want space characters, not tab characters, in that context.
So even though in most cases those three uses for tabs are independent, in some languages they get muddled. F# is another language where you may want to align text on line two with the middle of line one, e.g. if you write
let person = { FirstName = "Bill"
LastName = "Gates" }
(Those two links point to different anchors in the same document, BTW: the HN link shortening is going to make them look identical until you hover over them).
The cond example commits a sin (see my other reply), in the F# example tabs (were they permitted) would introduce no ambiguity if used solely to communicate indentation, and the only change I would make to the F# example were I formatting it myself would be to also align the `=` characters. Actually that supposedly bad style is more or less exactly how I write nix expressions (as a matter of practicality I do not use tabs when writing those FWIW).
I agree that the cond example is committing the sin of trying to align with tabs. I wrote it because I had misunderstood something you were saying. But also, I've personally seen situations like this. I was working in a team whose indentation convention was "one tab character per indent level", and I had written some C# code like this:
var result = someObject.SomeMethod(param1, param2,
param3, param4);
And then to my horror I noticed that the editor (earlier I said it was VS Code, but thinking back I think it was actually Visual Studio) had produced this monstrosity:
var result = someObject.SomeMethod(param1, param2,
<tab><tab><tab><tab><tab><tab><tab>param3, param4);
(Actual number of tabs was different, of course, and I believe it was followed at the end by a space or two, whereas my example happened to line up without needing an extra space character).
I know not to do that. The editor did it anyway, and if I hadn't been paying close attention to whitespace I might not have caught it.
The editor could have been smart enough to parse the code into an AST, notice that param3 and param4 were part of a parameter group, and said "I will use tab characters equal to the indentation of `var result`, then spaces thereafter". It didn't. I had to edit the call to look like this:
var result = someObject.SomeMethod(
param1, param2, param3, param4
);
And then I was safe from the editor trying to align things with tab characters.
If my memory is right about which office I was working in when I saw the editor do that to my code, then it was more than a decade ago, probably around 2010 or 2011. It's possible that the modern version of that editor has improved its handling, and would have correctly aligned param3 with spaces. I haven't checked recently. Maybe at some point I will, and report my findings.
> And they still can’t count the R’s in strawberry!
Really? I do not have the time to survey the modern LLMs to see if your assertion is correct, but if it is then I'm surprised; I would have thought that that one would have shown up so often in their training data that they would be able to answer that question, even if they would then be unable to (for example) count the R's in raspberry, or in some other word where "count the R's in _____" was not widely found in recent online discussion.
You're running into a cultural difference. The book of Ecclesiastes was written in Hebrew, in a poetical style even though large chunks of it are prose. But if you read other parts of the Bible, such as the book of Psalms (which is entirely poetry, specifically songs, though in many cases we do not know the tune that they were set to), you'll see that Hebrew poetry relied on repetition. For example, here's the King James Version's translation of the famous "to every thing there is a season" passage from chapter 3 of Ecclesiastes, which most translations render as poetry:
> To every thing there is a season, and a time to every purpose under the heaven: a time to be born, and a time to die; a time to plant, and a time to pluck up that which is planted; a time to kill, and a time to heal; a time to break down, and a time to build up; a time to weep, and a time to laugh; a time to mourn, and a time to dance; a time to cast away stones, and a time to gather stones together; a time to embrace, and a time to refrain from embracing; a time to get, and a time to lose; a time to keep, and a time to cast away; a time to rend, and a time to sew; a time to keep silence, and a time to speak; a time to love, and a time to hate; a time of war, and a time of peace.
That could have been said in less than a quarter of the words the author expended on it. But something of the style would have been entirely lost. He wasn't trying to be succinct, he was trying to repeat the same concept over and over until it sinks in.
Repetition can make a good impact, but it's beyond excessive in this instance. Contrast with this poem:
Non est salvatori salvator,
neque defensori dominus,
nec pater nec mater,
nihil supernum.
Translated:
No rescuer hath the rescuer.
No Lord hath the champion,
no mother and no father,
only nothingness above.
- Eliezer Yudkowsky
I find this one profound, and it's given me a lot to think about over the years - in situations ranging from asking what our place in the universe is, to doing the "right thing" (and deciding what "the right thing" even means to yourself), or standing at the helm of some team or project, knowing that judgement call is yours alone and there's no authority or higher power coming to swoop in and give you the answer or authoritatively judge your decision can be simultaneously liberating and terrifying. The use of repetition works incredibly well in my opinion and it still gives me chills to read it.
I never had formal training in Latin, just what I've picked up. But grammatically, I would think the second line would translate to "No champion hath the lord", not "no lord hath the champion". Am I misunderstanding the grammatical suffixes here?
I'm admittedly no Latin expert, so I can't give an authoritative answer, but the translation was actually arrived at on a forum where the author asked for help, and I can see someone asked the same question: https://www.lesswrong.com/posts/qpp6ZdwHLNKj6PXRp/req-latin-...
> ... confused about why I would talk to the human that prompted the AI, rather than the AI that did the work.
One reason is because you can't talk to the AI that did the work, not unless the human who prompted it is able to hand you a file with the complete session and/or context data. (And I'm not at all certain whether Anthropic would allow users to obtain that kind of thing, since it would probably be extremely useful to people trying to distill their models. It's possible they might allow user A to say "Hey, allow user B" (or anyone with the link) "to access my session with GUID ba5eba11-1234-5678-abcd-0decafc0ffee", but I doubt they'd ever allow context data to be downloaded and passed around).
Without the context, you're talking to a different instance of the AI that doesn't have the memory of the instance that ported the code, so the answers you get won't be nearly as useful.
First procgen game I ever played was Starflight 2. (Pre-Internet era, so I couldn't get hold of Starflight 1. SF 2 spoils you, hard, on the major spoiler in SF 1, so if you're playing them from GOG or other sources then you should definitely play 1 before 2).
My ten-year-old mind was boggled. Hundreds of star systems, each one with several planets (usually), and you could land on each one? And explore the whole planet (in a very limited top-down 2D view, because this was the 1980's), harvesting minerals, and the map was quite a bit larger than what would fit on one screen? And it all fit onto one 720K floppy disk?!??!?
Now, of course, I know how they did it. But there was an actual game there. There were half-a-dozen alien races you could interact with (talk or shoot, as required), and there was an actual story. With a twist at the end that 40-year-old me would see coming, but 10-year-old me was shocked and amazed by. (And the twist in SF 2 wasn't even as good as the one in SF 1). And you progressed that story by following the gameplay loop:
Then eventually you would be able to make your way to planets with plot on them, at which the loop changes to: After only a few runs through that loop, it's on to: Crucially, once you had gone to talk to those plot-important aliens, you probably had enough resources that you didn't need to do much mining anymore. You might land when you spotted a target of opportunity — "Oh look, scanners say big pile of platinum just sitting there on a nearby planet, let's make a small detour" — but that was just to keep the bank account topped off. You could afford enough fuel to fly all the way across the map and back, so you could focus on the story.And they timed it well: the core harvest-resources-and-upgrade-the-ship loop didn't have time to get boring before you were off to collect plot coupons. And there weren't too many plot coupons before it was time to find the MacGuffin, use it to beat the Big Bad, and save the day.
Star Control 2 did it really, really well, with better graphics since it was released a few years later. BTW, if you haven't played SC 2, search for "The Ur-Quan Masters" to download and play a totally free, legitimate, open-source version of the game, with full original assets since the copyright reverted back to the original creators who released it into the public domain for the UQM project to port to modern machines. I wish that had happened to all the old classics, but Star Control 2 is truly a good game. Definitely seek out The Ur-Quan Masters.
But before you do that, I would strongly recommend to play Starflight 1 and Starflight 2, to get a feel for the origins of the procgen-with-good-story genre that Star Control 2 did so very well.
P.S. Edited the "core gameplay loop" paragraph to better make it clear there were two or three loops, and you progressed forward through them, rarely having to go backwards.
reply