Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

At Facebook, we are now using prettier[1] on all our JavaScript files, a growing number of Hack files are formatted with Hackfmt[2] and now black is being rolled out for Python. It's a really exciting time :)

[1] https://prettier.io/ [2] https://github.com/facebook/hhvm/blob/master/hphp/hack/src/h...



Hey Vjeux. What does black mean for the prettier python plugin[1]? I had high hopes to move over all projects to prettier (for JS/Python). Is there going to be any merging between prettier python and black? Do you recommend one over the other?

Thanks

[1] https://github.com/prettier/plugin-python


I don't know :)

I worked on prettier myself because I wanted to solve formatting for the language I was involved in. It turned out that the prettier infrastructure was actually really good for other languages so we used it for CSS, Markdown, GraphQL... and added support for a plugin system for other people to build printers for their own language. patrick91 (not working at Facebook) is working on a python formatter using the prettier infrastructure.

Independently, ambv (working at Facebook) started black which is written in Python. He's part of the Python core team and the Python infrastructure team at Facebook so it made sense for him to drive adoption of black within Facebook.

One interesting thing I realized is that communities are built around programming languages and it's really hard to influence another community from the outside. So my bet would be that black has the most chance of succeeding within the Python community.


> One interesting thing I realized is that communities are built around programming languages and it's really hard to influence another community from the outside.

IMO, that point is worthy of a detailed blog post or conference talk, if you would be so inclined. Would love to hear more.


That's true, I'll consider it, in the meantime here are some thoughts.

When I started working on React Native, I thought that the most difficult thing would be to design a good set of APIs to make it easy to write mobile apps using React that felt good. This turned out to be the "easy part", we started the project wanting to solve this and having lots of good ideas on how to do it.

What turned out to be a lot harder was the fact that we were trying to use JavaScript from within iOS and Android ecosystems.

1) Those at the time were in different repos, how do you synchronize code between them?

2) The three ecosystems use a different set of tools for everything: IDE (xcode, intellij, sublime/atom/code/emacs), package manager (cocoapods, maven, npm), linters (eslint), build (how do you hook up with the play button in xcode?), profilers (can you display stack traces with the two languages calling each other?)...

3) Mixing and matching languages inside of a single project is hard because there are a lot of subtle different semantics (eg: javascript doesn't have int32 or int64). If you have type systems, they are incompatible (flow vs obj-c). So in practice you end up with a lot of boilerplate to talk between the two languages and it's a performance overhead.

There's also a social aspect where you invested so much learning an ecosystem that it becomes part of your identity. So you see someone wanting to bring another language as trying to attack you directly.

My mission since then has been trying to "break down the silos" and trying to build tools that can work with all those languages. It's not been easy :)


Wow, that website is hard to use! You can’t touch scroll down on iOS unless you click towards the bottom of the page as scrolls in the animation zone are ignored.


Why black over yapf?


Black is a simple tool. It tries to implement a single code style well. It's not configurable.

We tried YAPF before and could never roll it out for everybody. I even contributed the "facebook" style to the tool. There were a few reasons why YAPF didn't work out for us but the most important were:

- YAPF would at times not produce deterministic formatting (formatting the same file the second time with no changes in between would create a different formatting); Black treats this as a bug;

- YAPF would not format all files that use the latest Python 3.6 features (we have a lot of f-strings, there's cases of async generators, complex unpacking in collections and function calls, and so on); Black solves that;

- YAPF is based on a sophisticated algorithm that unwinds the line and applies "penalty points" for things that the user configured they don't like to see. With a bit of dynamic programming magic it arrives at a formatting with the minimal penalty value. This works fine most of the time. When it doesn't, and surprised people ask you to explain, you don't really know why. You might be able to suggest changing the penalty point value of a particular decision from, say, 47 to 48. It might help with this particular situation... but break five others in different places of the codebase.


Another issue is that yapf uses an algorithm that is quadratic, so you end up with code you actually see in practice take seconds to minutes to format.

The authors have been adding specific workarounds for some cases but it's a general issue with the approach:

- https://github.com/google/yapf/issues/264

- https://github.com/google/yapf/issues/39

Black algorithm doesn't explode in such way. It's also a lot faster overall which makes it possible and reasonable to enable a good format on save experience.


I do like Black's line wrapping rules of keeping things on separate lines to minimize diffs. I really hate auto formatting tools that tries to compress lines vertically through binpacking techniques that produce unaligned code.


RE: non-deterministic formatting: I'm not familiar with YAPF, but what kind of behaviour does it have? Like if you run it on two copies of the same file you might get different results, or that it's not idempotent (i.e. sometimes YAPF(YAPF(source)) != YAPF(source))?


> It's not configurable.

Except for the line length:

> if you're paid by the line of code you write, you can pass --line-length with a lower number.


Yeah, I wasn't willing to die on that hill, especially that I'm introducing a new default value that wasn't popular before.


Ah but there's the irony.

Everyone would like to stick to the standard formatting rules. Well... except for that one little idiosyncratic thing that they just won't sacrifice.

Then black comes storming in to enforce conformity. Well... except for that one little idiosyncratic thing the author of black just can't bring himself to adhere to.

Don't get me wrong. I'm a big fan of the approach in general. I use things like paredit-mode and aggressive-indent-mode and whitespace-mode and I've just set up emacs to use black together with blacken-mode, but with blacken-line-length set to 80.


Time for a fork!

Let's call it "black-ish"


It was a good call. Some code bases use long identifiers and an 80 column limit gets to be a mess.

And for the 80 column fetishists, you'd have to pry their VT-100 terminals from their cold, dead hands. Disposing of the body is enough of a pain, but worse, you have to find a recycler who can deal with the lead glass in the CRT.


The modern argument for lower-line-lengths is the ability for more screens+fonts+UIs to display two blocks of code side-by-side. Somewhere between 80 and 120, you start to force many UIs to wrap. Adding to the subjectivity, approx nobody cares about one line of long code out of 100,000 -- so what percent of code-that-wraps is too much?

To avoid dying on that hill, many eng leads just throw up their hands and give into the 80-column folks, even if it's less productive for everybody else.

The beauty of gofmt and black is that formatting can become a commit hook, so no human wastes time cutting lines manually like some early 20th century typesetter.


I've got to say, I'm quite happy with the default line length in Black.

The reason I always fight with people who want to increase line length is that they generally want to increase it to 100. Which is just a bit too big to fit two columns comfortably side by side at a reasonable size on a laptop screen, or three columns side by side on a wide desktop screen, which is how I generally set up my editors.

I'm always frustrated with codebases that use a 100 character standard, since I'm always running into lines that wrap, but when I use type annotations, 80 characters causes too many function signatures to have to wrap.


When I read that line in the documentation, it hurt a little. I'm going to be honest here. I did not feel good with someone saying that an 80-column limit is just there to pad my paycheck, rather than an informed decision I made. I realize that it was tongue in cheek, but it still felt bad.


If that hurt you, you need bigger problems in life.


I like a line length rule because I use an editor that can show me multiple files side-by-side, and keeping things to a certain length ensures that I can productively do that.

And my terminal happens to be around 240 characters wide for the font size I use and the size of my laptop's screen, which means if I limit to 80 characters or less I can snugly fit three files, or if I set to 100 I can get two with some breathing room.

Plus, if a line really is going over those lengths, then it's often a code smell: maybe I've got code that's too complex and ending up deeply-nested, or maybe I've got functions or methods taking way too many arguments, and hitting a line-length rule will warn me about that.


Why are you being so dismissive? It seems like you are making this into some kind of contest to see who has bigger problems.

I am just being honest, and I think I am being helpful because other people will also react negatively to the way the documentation is written. I support the project and want it to be successful, providing feedback like this achieves progress towards that goal, in my estimation.


yapf is not consistent, you can rerun it on source and it will reformat it multiple times. The rules for how it formats are also hard to understand


Prettier is what I miss more everytime I switch from JS to Python. I hope Black fixes that.


I feel the same way. Prettier is a dream--instant speed, great output and 100% reliability for over a year.

So far black seems great. I just ran it on some existing Python packages and it was fast and the output was correct. Still need to try the editor plugins but very excited so far.

Now, if only someone would lead a similar project for R. :)


That's been my experience. I'm using the VSCode plugin and have for the first time ever enabled format-on-save for Python. I have yet to have any reason to see that as anything other than a positive.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: