Hacker News new | past | comments | ask | show | jobs | submit login

I think the problem is not private-by-default, but the repetition of "pub". We tried public-by-default and it led to a situation where it was very hard to make a stable API for your modules (which we need to avoid breakage of existing code). It could be solved with a "pub { ... }" block (which I'm pretty sure you could write today with a macro if you wanted to). Personally, I prefer repetition of "pub", as it forces me to think about what API I want to present to consumers of my library, but I can see how it can be annoying, especially if your modules are purely for internal use and you aren't concerned about API stability as much.

Regarding safety annotations, there is a WIP effort to eliminate 80%-90% of the lifetime annotations used in practice. There are also a couple of proposals to change the syntax of lifetime annotations to be less noisy.




I certainly welcome the attempts to reduce annotations and will look again at the language in a while.

It is interesting that the design priorities are so library-centric. I agree that library quality is important, but think about this: For every library that someone writes, N people are going to use that library in leaf programs, where if the library is useful N is much much greater than 1. So by definition the vast majority of code is not library code.

In video games we write programs that are between 200k and 2M lines, say. That is big enough that you do want to think about what API you are presenting from part of that program to another, but stability of that (internal) API is almost never a concern, and in fact this is one of the big boons of statically-typed languages: you can change a function and you instantly get errors at all the calling sites, allowing you to be sure you updated them (except in some bad ambiguous situations).

This fluid ability to change how parts of your program talk to each other is very important in large programs. It is one of the major ways you avoid code rot. The more friction is introduced into this process, the lower the ceiling on how large and complex a program you can build.

The other thing about games is that the problems are inherently very interconnected. Yes, we kind of partition things into different modules, but these modules all want to talk to each other very heavily (partly for inherent problem space reasons, partly for performance reasons). So again, friction introduced here hurts us more than it hurts most people.

I understand that private-by-default seems like the right idea because it supports a certain paradigm of programming that is generally considered the right thing (encapsulate your implementation details, modularize as much as possible, etc). But what I have found, in my field at least, is that this is less true than many people think. Yes, it's important to keep things clean, but fluid ability to change code is very important, and overmodularization hurts this. I think that some day this will become more widely understood, the same way that today most good programmers understand that OOP is not some kind of One True Panacea the way folks in the 90s seemed to think.

Good ideas can be carried too far and I think for my field private-by-default is way too far. Having to put 'pub' on every member of every struct and on well more than half my functions is kind of bananas.

(As someone who does not buy into the paradigm of OOP, I want to write functions that operate on data. In C++ sometimes I encapsulate these functions as struct members but this is just an aid to understanding when it is convenient; most functions are declared at file scope. In order to have a functions-operating-on-data mentality in Rust, I guess I need to put a pub in front of every member of every struct, which feels very distasteful; it feels like the language is pushing me toward paradigms that many in my field have tried and subsequently rejected after decades of pain.)

Well, this certainly went a few places, but that is where I am on these issues.


Great, that's really helpful feedback.

I guess the way I see it is that there's a difference between a namespace and a module. A namespace is what you're describing: you want a way to isolate the symbols of different components from one another, but you don't really want ironclad abstraction barriers. A module, on the other hand, is the unit where you really care about presenting a well-defined API. Sometimes projects call for one or the other, or a mix of both. You can always technically model namespaces as modules, but you end up repeating "pub", "public", or "export", or whatever your language calls it a lot. So it may well be good to have both features in the language.




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

Search: