Stream: ideas

Topic: tabs for indentation?


view this post on Zulip Richard Feldman (Nov 01 2023 at 16:56):

I recently realized that we inherited a particular design decision from Elm—namely, that tab characters are disallowed—and never really discussed it here, so while I'm not advocating for or against changing the status quo, I am advocating for exploring the question explicitly :big_smile:

there is a massive thread advocating for the ubiquitously-used JavaScript formatter Prettier to switch to using tab characters for indentation by default instead of spaces. I know go fmt has been doing this for years.

view this post on Zulip Richard Feldman (Nov 01 2023 at 16:56):

tab characters do have a straighftforward performance advantage when it comes to parsing; \t is 1 byte, and multiple spaces are multiple bytes, so there's just less to parse if using tab characters

view this post on Zulip Brendan Hansknecht (Nov 01 2023 at 17:02):

Whatever we do, I think we should pick 1 specific format and not be like python where both work, but not together.

view this post on Zulip Agus Zubiaga (Nov 01 2023 at 17:03):

Funny you mention that. It was one of the first things I tried when I started playing with Roc. Tabs always made more sense to me but years of Python and JS experience taught me to let that go :upside_down:

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:04):

something that's partially an upside and partially a downside is that tab widths are configurable in many editors (and GitHub, now).

an upside is that different people with different indentation size preferences can adjust their tab widths according to their own preferences, rather than perhaps being unsatisfied with the enforced number of spaces.

a downside is that different people working on the same code base may see the code differently, which can have consequences like:

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:07):

another consideration is that if we enforce "Tabs are only for indentation and can only be used at the beginning of a line (and maybe also in string literals, but that would be a separate discussion). Spaces are never allowed at the beginning of a line." - which is the design I would favor by default - I'm not sure how that rule would affect Roc code being embedded in other contexts, e.g. code snippets in .md files

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:07):

if someone has their editor set to convert tabs to spaces, is it weird if their .md files have code snippets that get converted to spaces, e.g. because someone looking at that code thinks "whoa this Roc code is really indented strangely compared to what I'm used to"

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:08):

(presumably it wouldn't be a compile error because there'd just be a syntax highlighter pass happening on code snippets in a .md file anyway)

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:09):

I'm curious if anyone has relevant experience working in code bases that used hard tabs for indentation, e.g. in (or in any language, really)

view this post on Zulip Agus Zubiaga (Nov 01 2023 at 17:09):

I think the formatter at least should parse both and always output one

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:10):

yeah I think the way to go would be to have the parser understand both but then report an error (or perhaps warning) if it gets the disallowed one

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:10):

in general I'd like to make the parser more permissive in ways like that, especially for editor integration

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:11):

e.g. if you have an outdented when branch, giving an error but still assuming you meant it to continue the current when branch (so the formatter can just fix it for you like it does in Rust)

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:57):

I guess another downside is that tabs may be harder to type in some contexts (e.g. browser textareas) because the tab key has some other meaning

view this post on Zulip Richard Feldman (Nov 01 2023 at 17:58):

some relevant points here: https://github.com/ziglang/zig/issues/544#issuecomment-558881335

view this post on Zulip Richard Feldman (Nov 01 2023 at 19:20):

some interesting points about humans and editors mixing up tabs and spaces by accident - https://github.com/ziglang/zig/issues/544#issuecomment-618072318 - anyone have any relevant experience with that happening?

view this post on Zulip Richard Feldman (Nov 01 2023 at 22:51):

related thoughts from @drathier https://twitter.com/rtfeldman/status/1719694899681870183

view this post on Zulip Brian Carroll (Nov 02 2023 at 00:19):

For some recent work I have been reading the Ruby codebase a lot. It's written in C. They mostly use tabs but there are also spaces in there. So it's hard to read unless you have the right setting in your editor... which defeats the main point of using tabs in the first place.
So I think if we allow tabs there should be some way of preventing them from being mixed, at least for start-of-line indentation.

view this post on Zulip Brian Carroll (Nov 02 2023 at 00:21):

By the way, the best setting for the Ruby codebase is 6 spaces per tab, because of course it is.

view this post on Zulip Richard Feldman (Nov 02 2023 at 00:24):

yeah I think a reasonable design would be:

view this post on Zulip Richard Feldman (Nov 02 2023 at 00:30):

I'm kinda surprised not to see more advocacy for spaces haha

view this post on Zulip Hannes (Nov 02 2023 at 00:39):

When I started using Roc I assumed the decision to use spaces had already been made and was a little disappointed because Roc seemed very modern in other ways.

I sometimes use a non-monospaced font for code, and one of the annoying things about it is the space character is very narrow, so using tabs would let me adjust the indentation in my editor.

view this post on Zulip Elias Mulhall (Nov 02 2023 at 02:39):

My best arguments for spaces, in order of most to least important

The first point is pretty compelling to me personally. Otherwise I don't really care, either is fine.

view this post on Zulip Luke Boswell (Nov 02 2023 at 03:36):

I've never been exposed to the tab vs spaces argument before, so probably not super qualified to drop my 2cents in here. But from a quick read through some of the reddit threads and blogs link in the content above, I'm pretty convinced tabs seems like the right way to go. The biggest benefit I think is the accessibility argument, followed by the consistency between tooling.

view this post on Zulip drathier (Nov 02 2023 at 06:45):

If you want to really push for full tab support, and make sure the formatter rules are flexible (which I strongly suggest you do!), this editor setup should work fine:

I used this as my everyday setup when writing go and go fmt handles this wonderfully. I know it sounds crazy but it works really really well :)

view this post on Zulip Declan Joseph Maguire (Nov 02 2023 at 07:36):

If we go for a hard constraint where one thing is right and the other wrong, I wouldn't mind. But I can also totally imagine myself as a novice trying to pick up their first or second language and not understanding whitespace rules, spending way too long writing my first precious script, only to get a error because I used the wrong convention and not knowing that it's easy to fix with an automated tool. If we decide on something that can error, we'd want to pair it with immediately actionable advice on how to fix it and keep it fixed.

view this post on Zulip Jacob (Nov 02 2023 at 08:45):

Yeah, accessibility argument wins. I'm sure most people don't actually care that much(even if it's fun to argue 1 way or the other), but for the people it does affect, it's probably way nicer to deal with.

view this post on Zulip Hannes (Nov 02 2023 at 09:07):

I remember my first time writing a makefile having configured my editor to always convert tabs to spaces and spending waaay too long trying to fix it

view this post on Zulip Hannes (Nov 02 2023 at 09:13):

I know Roc always tries to have helpful error messages, so I don't expect that to be a problem. :+1:

view this post on Zulip Declan Joseph Maguire (Nov 02 2023 at 09:24):

I think that ties into a broader conversation about first time user experience for various audiences. It's way way too early to lock anything down regarding that, but it's obviously worth keeping in mind early. Maybe it was my weird programming education in a physics degree, but I remember needing to learn C and C++ as someone who'd only done a little python, and the number of steps to get that working was very intimidating. The problem wasn't language syntax or deeper language concepts, it was all the weird stuff you needed to do to get it working on windows, the magic boilerplate code, etc.

view this post on Zulip Declan Joseph Maguire (Nov 02 2023 at 09:28):

So yeah, point being that accessibility is a lot more than the language features themselves; a lot of the coding infrastructure out there is pretty damn hostile to learn unless you've just picked it up or had a very conventional programming education. Roc is far ahead in most ways though, and I love how actively it's been prioritised.

view this post on Zulip Richard Feldman (Nov 02 2023 at 13:34):

Declan Joseph Maguire said:

If we go for a hard constraint where one thing is right and the other wrong, I wouldn't mind. But I can also totally imagine myself as a novice trying to pick up their first or second language and not understanding whitespace rules, spending way too long writing my first precious script, only to get a error because I used the wrong convention and not knowing that it's easy to fix with an automated tool. If we decide on something that can error, we'd want to pair it with immediately actionable advice on how to fix it and keep it fixed.

this is a great point - if someone new to the language has their editor configured to convert tabs to spaces by default, e.g.

Elias Mulhall said:

My editor is configured to convert all tabs to spaces

(and that's also the case with my editor personally)

I can imagine a beginner trying Hello World in the tutorial and getting this:

── SPACES USED FOR INDENTATION ──────────────────── hello.roc ─

This line is using spaces for indentation instead of tabs:

7│  main =
8│      Stdout.line "Hello, World!"
    ^^^^

Indentation is significant in Roc, and only tabs can be
used to indent. Make sure each indented line begins only
with tabs, and not spaces!

Tip: If your editor automatically converts tabs to spaces,
make sure it's configured not to do this for .roc files.

───────────────────────────────────────────────────────────────

is that an ok beginner experience? :thinking:

view this post on Zulip drew (Nov 02 2023 at 13:42):

count me as a strong advocate for spaces over tabs. the only language i use with tabs is go. the theoretical benefits of user configurable visual spacing is far outweighed by the strangeness budget spent by being different from basically every other modern language.

view this post on Zulip drew (Nov 02 2023 at 13:44):

also perhaps ironically i'm begging you all for 2 spaces, not 4

view this post on Zulip drew (Nov 02 2023 at 13:46):

i'm also in the "tabs become spaces in vim" camp, so i special case go

view this post on Zulip Hannes (Nov 02 2023 at 13:48):

I think as well as a compiler error, the editor extension/plugin should be able to give specific advice on how to configure Roc files to use tabs.

view this post on Zulip Martin Stewart (Nov 02 2023 at 13:49):

Maybe my knowledge about this is out of date, but if Roc is going to have its own editor that we want people to use instead of VSCode/Vim/Intellij/etc then the pros/cons of tabs vs spaces only matters when the code is being viewed elsewhere like github? Within the editor we could display the code with however much spacing the user wants regardless of if the actual saved file is using tabs or spaces?

view this post on Zulip Richard Feldman (Nov 02 2023 at 13:55):

Jacob said:

Yeah, accessibility argument wins. I'm sure most people don't actually care that much(even if it's fun to argue 1 way or the other), but for the people it does affect, it's probably way nicer to deal with.

accessibility is a big deal to me, but I've had a really hard time trying to figure out what the impact would be in practice here.

I've seen it said in many places that "configurable tabs is important for people with certain visual impairments" but then when I try to understand more deeply which visual impairments it would help with, how it would help them, etc. - it seems to come down to:

not knowing what the actual impact would be makes it hard to weigh the accessibility benefit here. Like screen readers are obviously a huge benefit to people who can't read text, so making things work well with screen readers is a huge deal. Specifically how big of a benefit are we talking about with tab widths? It's surprisingly hard to determine!

view this post on Zulip Richard Feldman (Nov 02 2023 at 14:17):

drew said:

count me as a strong advocate for spaces over tabs. the only language i use with tabs is go. the theoretical benefits of user configurable visual spacing is far outweighed by the strangeness budget spent by being different from basically every other modern language.

this is a fair point, although the same argument can be made for the status quo; Zig bans hard tabs (like Roc does today), and if you search for "zig tabs" you'll find a number of discussions where beginners were vocally unpleasantly surprised to discover the hard way that Zig doesn't allow hard tabs. To them, disallowing tabs is taking things out of the strangeness budget.

view this post on Zulip Richard Feldman (Nov 02 2023 at 14:21):

here's some food for thought:

has any language having the parser accept either tabs or spaces for indentation, but only on a per-file basis? e.g. if a file uses all spaces for indentation, that's fine, but if one line uses tabs that line is an error. (The parser could count how many lines had been indented one way vs the other, and give an error at the end of the file for any lines that were not the majority indentation character used. This might sound complicated but actually sounds very easy to implement to me.)

view this post on Zulip Richard Feldman (Nov 02 2023 at 14:21):

then of course the formatter would always choose one or the other (let's assume tabs) - but this design would mean that beginners are never tripped up by this in hello world, even if they haven't set up the formatter yet

view this post on Zulip Richard Feldman (Nov 02 2023 at 14:22):

also would mean if markdown files use spaces instead of tabs for code snippets, it's not a problem - but might be a problem if people copy/paste from those into their code base that uses tabs (although the formatter would fix that, and if they aren't using the formatter, they'd get an error anyway for mixing tabs and spaces for indentation in the same file)

view this post on Zulip Brendan Hansknecht (Nov 02 2023 at 15:45):

has any language having the parser accept either tabs or spaces for indentation, but only on a per-file basis?

I don't think per file is the issue. It is just the inconsistency in general. My editor generates spaces for python. I can't visually see the difference between spaces and tabs. I edit a file with tabs and totally break it.

view this post on Zulip Brendan Hansknecht (Nov 02 2023 at 15:47):

Imagine if a library you use does tabs, but your own project does space. Anytime you go to definition for a file in the library and edit it, you will break things due to tabs and spaces. Like your editor would have to be configured to detect the correct indent character per file. That sounds painful. Like you can add local overrides, but that is just worse than forcing only one.

view this post on Zulip Richard Feldman (Nov 02 2023 at 15:48):

Brendan Hansknecht said:

has any language having the parser accept either tabs or spaces for indentation, but only on a per-file basis?

I don't think per file is the issue. It is just the inconsistency in general. My editor generates spaces for python. I can't visually see the difference between spaces and tabs. I edit a file with tabs and totally break it.

ah interesting, so if everyone culturally used a code formatter, there wouldn't be a problem?

view this post on Zulip Richard Feldman (Nov 02 2023 at 15:49):

(a code formatter with no configuration options, like roc format)

view this post on Zulip Brendan Hansknecht (Nov 02 2023 at 15:50):

I have one anecdote about astigmatism

Astigmatism can happen at any angle. For me, I essentially have the diagonal text shadow effect on all the time. Someone could have astigamatism that goes directly horizontal. This would make tab/space width harder to verify perfectly. That said, it would also lead to overlapping characters if it was quite bad. That would be totally unreadable. I would assume that most likely readability of words and requirement for glasses will come much before tab width being a problem.

view this post on Zulip Richard Feldman (Nov 02 2023 at 15:52):

interesting! Do you know of anyone who has a horizontal astigmatism who customizes tab width because of it? (And if so in which direction - making it higher or lower?)

view this post on Zulip Brendan Hansknecht (Nov 02 2023 at 15:52):

I don't know of anyone.

view this post on Zulip Brendan Hansknecht (Nov 02 2023 at 15:52):

Just thinking of how it could theoretically happen.

view this post on Zulip Richard Feldman (Nov 02 2023 at 15:52):

like one reason I care about the specifics here is that it might be the case that 4-space indent (for example) is already sufficient that in practice that's about what anyone who had that issue would choose to set the tab width at anyway, and being able to set it higher or lower wouldn't make a significant difference for them anyway

view this post on Zulip Richard Feldman (Nov 02 2023 at 15:53):

as with any user research, talking to people who are directly affected tends to reveal things that are different from what we predict their experience would be in theory :big_smile:

view this post on Zulip Brendan Hansknecht (Nov 02 2023 at 15:54):

If 4 space indents are hard to see due to astigmatism, I am pretty sure that would mean all characters are stretching to be about 2 characters wide. So the text would be totally unreadable anyway. Though maybe I am missing something in how the duplication and stretch effect works for some people.

view this post on Zulip Richard Feldman (Nov 02 2023 at 15:56):

yeah that's exactly the type of thing that makes me crave specifics - e.g. in general if something is sufficiently serious, no amount of tweaks will make it legible and the answer is some other way of accessing the text (e.g. screen reader, refreshable braille display, etc.) - at which point tab width is not actually a benefit to that person because they aren't using a screen display at all

view this post on Zulip Richard Feldman (Nov 02 2023 at 15:57):

as an aside, I've read that modern screen readers in editors will generally condense repeated space characters (e.g. instead of saying "space space space space" they'll say "4 spaces" or "8 spaces" etc.) so I don't think there's a big difference between spaces and tabs in terms of verbosity

view this post on Zulip Brendan Hansknecht (Nov 02 2023 at 16:00):

Oh, one extra note for:

ah interesting, so if everyone culturally used a code formatter, there wouldn't be a problem?

A code formatter would fix the issue if it is smart enough to deal with tabs and spaces on the same line while figuring out correct indentation levels. Cause I may edit someone else code by adding a new conditional. As such, I would be tabbing in their code father which could lead to mixed spaces and tabs depending on the editor config. Though I would just set my editor to match the formatter in practice, so this hopefully wouldn't come up as a real issue.

view this post on Zulip Richard Feldman (Nov 02 2023 at 16:01):

yeah I think that situation is similar to "I'm consistently using the same character for indentation, but I pasted some code in at the wrong indentation level" - can the code formatter guess what you meant and correct it?

view this post on Zulip Richard Feldman (Nov 02 2023 at 16:01):

and I think the answer is that often it can but of course not always

view this post on Zulip Richard Feldman (Nov 02 2023 at 16:02):

for example, if it encounters a when branch that would make sense here (e.g. there's an open when in progress) but it's at the wrong indentation level, we can safely assume it should just be indented properly and move on

view this post on Zulip Richard Feldman (Nov 02 2023 at 16:07):

I suspect the same is true of nested defs, e.g.

foo =
    x + 1

    bar = y + 1

baz = z + 1

this is technically a syntax error of bar doesn't have a closing expression, but from context clues we can guess that it's probably an indentation mistake and bar = should be at the same indentation level as foo =

view this post on Zulip Sky Rose (Nov 02 2023 at 19:58):

Throwing in my vote: I'd lean towards tabs because tabs are semantic. Using spaces for vertical alignment (aside from indentation) is a bad practice in general (aside from special cases like hard coding a big list of tabular data). At least at the beginning of a line, Roc code should be indented exactly one tab-width more than the line above, which tabs are better at than spaces. I do personally prefer spaces but only cuz I'm used to them, and switching to a new language is the right time to change that.

I also think that the compiler should be as forgiving as possible. Maybe a compiler error if bad indenting means the compiler can't figure out the semantics, a warning if there's mixed whitespace within one file but the compiler can figure it out, and silently succeeding if a file is consistently spaces. This is a formatting concern, so only the formatter should be the enforcer. That way people could try the language with spaces, and only run into this issue once they call roc format and show they want to conform to the standard.

view this post on Zulip Declan Joseph Maguire (Nov 02 2023 at 22:02):

Richard Feldman said:

ah interesting, so if everyone culturally used a code formatter, there wouldn't be a problem?

We wouldn't be able to rely on that for the new user Hello World experience

view this post on Zulip Jacob (Nov 05 2023 at 10:27):

I was more thinking that tab being 1 character rather than space for braille displays (maybe screen readers too?) might be easier. I wasn't really thinking about the adjustable tab width part.

view this post on Zulip Richard Feldman (Nov 05 2023 at 11:44):

yeah I'd love to learn more about braille displays, but so far the most detail I've been able to find is "they exist, and it's conceivable that some programmers might use them for programming instead of screen readers, but also maybe not" which is not much to go on :sweat_smile:

view this post on Zulip Jacob (Nov 06 2023 at 05:53):

Yeah, I remember seeing a blind programmer in college, but pretty sure he just used a screenreader and a normal keyboard.

view this post on Zulip Declan Joseph Maguire (Nov 06 2023 at 07:18):

I live with a blind programmer, and he uses screenreaders as they're functionally mandatory for navigating computers. Then again, he was blinded as an adult.

view this post on Zulip Richard Feldman (Nov 06 2023 at 11:51):

@Declan Joseph Maguire do you know if he happens to know anyone who uses a braille reader?

view this post on Zulip Richard Feldman (Nov 06 2023 at 11:51):

I'd love to learn more!

view this post on Zulip Fabian Schmalzried (Nov 07 2023 at 12:59):

If it does not conflict with the indentation rules of roc, I would vote for the parser allowing any mix of tabs and spaces. This will solve any problem with

The formatter of cause has to choose one. Since the purpose of tabs is to do indention, they are more configurable, and are only 1 byte, I would vote for tabs. But having a formatter doing it for me is more important than the actual indentation style.

view this post on Zulip Fabian Schmalzried (Nov 07 2023 at 12:59):

Also interesting, but I'm not sure how relevant: elastic tabstops (VS code extension)

view this post on Zulip Brendan Hansknecht (Nov 07 2023 at 15:08):

Accepting any mix does not magically fix the issue. I have had plenty of python code where it worked upon copy but would break whenever I edited the file. Really painful and annoying to work with.

view this post on Zulip Brendan Hansknecht (Nov 07 2023 at 15:09):

Especially painful because tabs and spaces look the same. So I would have no visual way to even see where or why the code is broken

view this post on Zulip Brendan Hansknecht (Nov 07 2023 at 15:09):

I honestly much prefer only accepting one and erroring out on the other.

view this post on Zulip Brendan Hansknecht (Nov 07 2023 at 15:10):

I am fine with the formatter accepting both, but I don't thing roc run or roc bulld should accept both.

view this post on Zulip Brendan Hansknecht (Nov 07 2023 at 15:11):

They should just error and say that the user can try running roc fmt or manually converting all tabs to spaces (or spaces to tabs, whichever we pick)

view this post on Zulip Brendan Hansknecht (Nov 07 2023 at 15:16):

Fabian Schmalzried said:

Also interesting, but I'm not sure how relevant: elastic tabstops (VS code extension)

I don't think that would work on a whitespace significant language like roc or Python.

view this post on Zulip Brendan Hansknecht (Nov 07 2023 at 15:16):

Though really interesting idea

view this post on Zulip Eli Dowling (Nov 14 2023 at 20:34):

My little suggestion, pick one and make everyone follow because consistency trumps all.
Have the compiler work but emit a warning. I totally agree with @Sky Rose, it's a formatting concern, formatting is worth taking an official stance on, but if you want to do something visually yuck or you are writing your first 10 lines of rust in vi then it should still just work.
Make your formatter fix it if it's wrong.
If you are worried about the beginner experience, have a warning that both explains that you should change the setting that either inserts tabs or spaces, tells you to run "roc fmt" to fix it right now and links to a page explaining why it is this way and a little explanation for how to fix this in each major editor.
As an editor extension, in many cases you can set settings like whether to use tabs or spaces in your language, so assuming a beginner is on the "golden path " it should just work.

Lasty i think you should choose tabs, because we shouldn't live in a world of fixed indentation. When I'm on my best game and i want to absorb as much code as possible I'm generally in a 2 space indentation mood, but when it's 2am and I'm staring at my tiny laptop with blurry eyes 4+ spaces of indentation is the only hope i have of discerning one indentation level from another. The option to change your indention whenever the mood strikes is an ultimate freedom we all deserve and feel the loss of, even those too oppressed by space tyranny to realize that. ;)

view this post on Zulip Brendan Hansknecht (Nov 14 2023 at 23:35):

The option to change your indention whenever the mood strikes is an ultimate freedom we all deserve and feel the loss of, even those too oppressed by space tyranny to realize that

The funny part is that many editor now can render spaces at any width. So they have a way to get what you are talking about despite using an exact number of spaces. It's an interesting work around that has been implemented many times.


Last updated: Jun 16 2026 at 16:19 UTC