You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tracking issue for File::with_options stabilisation #65439
From the name I'd associate it with a function that takes an OpenOptions parameter, just like Vec::with_capacity takes a capacity. Basically not a builder type. For consistency's sake, why not either add a File::with_options(options: &OpenOptions) or rename it to something like File::builder()?
Reacted by Ruslan Fadeev, tesuji, Stanislav Tkach, Alexander Kovalyov, Sivizius, Radio Guy, Lionel Flandrin, Michał and zohnannor
I guess File::options() makes more sense when you just look at that API but File::with_options() makes more sense in typical usage.
let options = File::options(); // Ok
let options = File::with_options(); // Weird
let file = File::with_options().read(true).create(true).open("foo.txt"); // Ok
let file = File::options().read(true).create(true).open("foo.txt"); // Bit weirder. Maybe it is better actually?
Not that this is a democracy, but let's have a poll: upvote one or more of the following options...
From the API discovery point of view it's not great to have the only actual verb be the last in chain.
From the point of view of making code nicer to read, it's not great that open is not in any way syntactically distinguished from the rest of the methods. The reader has to inspect the types to find out that all but the last one return the same OpenOptions type. (It doesn't help that other methods are verbs too, even though they refer to fields and would be nouns in most other builders.)
I think the argument about whether something sounds like a nullary function or not is valid, and is reasonable grounds to exclude File::with_options() from the running. But we already have OpenOptions as a very... interesting type name. So to me, I agree that nullary File::open_options() is quirky, but I also think it's "natural" to Rust, simultaneously, because of the existing legacy of OpenOptions. I believe it's reasonable to lean into the quirkiness. But of course, File::options() is also good to me.
So, I feel it is copacetic either way, and
open_options seems reasonable but I think all of the options (heh) are reasonable. Doesn't seem like it's enough better to bother changing the PR again.
I am happy to repaint the bikeshed if people can agree on a color!
On Fri, Jun 04, 2021 at 10:09:34AM -0700, Jubilee wrote:
I think the argument about whether something sounds like a nullary function or not is valid, and is reasonable grounds to exclude `File::with_options()` from the running. But we already have `OpenOptions` as a very... interesting type name. So to me, I agree that nullary `File::open_options()` is quirky, but I also think it's "natural" to Rust, simultaneously, because of the existing legacy of OpenOptions. I believe it's reasonable to lean into the quirkiness. But of course, `File::options()` is also good to me.
One difference is that `OpenOptions` is a type, not a function, so it's
more obvious that `OpenOptions` itself doesn't perform an open
operation. A function named `File::open_options`, living right next to
`File::open`, seems more ambiguous.
I'm not set on the function being called `File::options`; I just don't
think the function name should start with `open`.
I'd like to restate that IMO options() has the advantage of being a generic name that could be reused for other APIs which in turn could help discoverability. It could join new(), iter() and other well known method whose semantic you can guess without even having to look at the docs. You could have an option() method for an OpenGL context object, a database handle object, a cryptographic algorithm object etc...
open_options() is also fine, but that would make it semantically a little more "narrow" IMO. I suppose that for a DB handle the metaphor also works, but you don't typically "open" a SHA1 context for instance, you create it.
But I agree that this is a pure bikeshed at this point. If open_options is favoured, I'm absolutely fine with it.
m-ou-se suggests File::open_options() as an alternative, because it sorts directly next to File::open(Path) in the method overview, and proposes other shorthands like File::open_rw(), File::open_append(), or File::create_new().
Question: Is the function sorting algorithm for rustdoc stable or likely to change?
Question: Where does create_new() come in here? How exactly would it differ from create(Path) in usage?
Josh suggests OpenOptions is meaningfully distinct from File::open_options() because it's a type (a "noun") not a function (a "verb"), and thus dissociated from File.
Josh suggests fn open_options(arg) -> OpenOptions is what he would expect, on the basis of the "verb" being included and implying something similar to with_.
Question: If this is an expected pattern, maybe other examples of this already exist? What do programmers currently write, and thus, expect?
Jubilee (hi!) suggests the name is quirky regardless.
Question: How did we arrive at the original name anyways?
Josh suggests that fn open(Path) and fn open_options() are unnecessarily ambiguous next to each other.
Question: Isn't that the point, actually? That both are valid ways to start the same code string?
simias believes that fn options() will carry more weight over time (alongside fn option()) and become a common library pattern.
Question: If it seems like a commonly reusable pattern, maybe it has already arisen? What do programmers currently write, and thus, expect?
Other Ideas
If the problem is imports, why not just use an std::fs::prelude::* a la std::io::prelude::*?
Reflections
Rereading this reveals what now feels like a misstep in the early drafts of the File API, and I would like to offer these remarks to both m-ou-se's and Josh's comments regarding the relationship (or not) of OpenOptions, fn open_options, and fn open:
I don't think it's a problem that fn open_options is nullary whereas fn open is unary, or that one is a constructor for a Result<File> and the other is a constructor for an OpenOptions that will eventually yield a Result<File>.
I think the problem is that they are actually logically unrelated, or perhaps I should say that OpenOptions is the distant ancestor of File::open(Path), not the immediate parent. OpenOptions is far more ambiguous than what you can get from File::open(Path) because it can imply creating a file, appending to an existing file, reviewing and editing the contents of an existing file, or opening a file in read-only mode. File::open(Path) only supports the last. Thus File::open_options() would only bear a passing resemblance in use to File::open(Path), which would actually be something more like File::read(Path) if I had my druthers.
This difference itself would not be a huge issue, honestly, but we have a relatively strong norm of highly "patterned" names in other std APIs, and people would expect two names which use the same initial word to have similar meaning, when one is far different. But I don't believe that is a definitive argument against using fn open_options() per se, merely that it is an issue. I would probably want to research answers to some of the other questions more.
A quick skim of grep.app for open_options reveals that the dominant use of it is "a variable or struct field that is OpenOptions". In one or two cases it is in fact used as "open with this OpenOptions".
Searching for the regexp /fn open_.*\(/ yields quite a lot of examples of "open_something that takes an argument", it's true.
/fn options?(<.*>)?\(/ shows that fn option and fn options are both about equally often a "getter" and a nullary constructor, and sometimes it also takes an argument other than self.
Another possibility: First introduce additional File constructors such as File::(open_)?append, then re-evaluate how much the additional OpenOptions constructor is.
Activity
Kinrany commentedon Feb 23, 2020
Just a thought about an alternative API:
LPeter1997 commentedon Apr 12, 2020
From the name I'd associate it with a function that takes an
OpenOptionsparameter, just likeVec::with_capacitytakes a capacity. Basically not a builder type. For consistency's sake, why not either add aFile::with_options(options: &OpenOptions)or rename it to something likeFile::builder()?Timmmm commentedon Apr 14, 2020
LPeter1997, that was my original suggestion but people overwhelmingly preferred this API.
TheRadioGuy commentedon Jul 1, 2020
I agree with @LPeter1997. I think it'd be better to rename it to something like
File::options()Timmmm commentedon Jul 1, 2020
I guess
File::options()makes more sense when you just look at that API butFile::with_options()makes more sense in typical usage.Not that this is a democracy, but let's have a poll: upvote one or more of the following options...
Timmmm commentedon Jul 1, 2020
Timmmm commentedon Jul 1, 2020
Timmmm commentedon Jul 1, 2020
Kinrany commentedon Jul 2, 2020
From the API discovery point of view it's not great to have the only actual verb be the last in chain.
From the point of view of making code nicer to read, it's not great that
openis not in any way syntactically distinguished from the rest of the methods. The reader has to inspect the types to find out that all but the last one return the sameOpenOptionstype. (It doesn't help that other methods are verbs too, even though they refer to fields and would be nouns in most other builders.)tesuji commentedon Sep 15, 2020
22 remaining items
workingjubilee commentedon Jun 4, 2021
I think the argument about whether something sounds like a nullary function or not is valid, and is reasonable grounds to exclude
File::with_options()from the running. But we already haveOpenOptionsas a very... interesting type name. So to me, I agree that nullaryFile::open_options()is quirky, but I also think it's "natural" to Rust, simultaneously, because of the existing legacy of OpenOptions. I believe it's reasonable to lean into the quirkiness. But of course,File::options()is also good to me.So, I feel it is copacetic either way, and
I am happy to repaint the bikeshed if people can agree on a color!
joshtriplett commentedon Jun 4, 2021
m-ou-se commentedon Jun 4, 2021
Pink!
Timmmm commentedon Jun 5, 2021
Sorry, "you" was referring to m-ou-se.
simias commentedon Jun 10, 2021
I'd like to restate that IMO
options()has the advantage of being a generic name that could be reused for other APIs which in turn could help discoverability. It could joinnew(),iter()and other well known method whose semantic you can guess without even having to look at the docs. You could have anoption()method for an OpenGL context object, a database handle object, a cryptographic algorithm object etc...open_options()is also fine, but that would make it semantically a little more "narrow" IMO. I suppose that for a DB handle the metaphor also works, but you don't typically "open" a SHA1 context for instance, you create it.But I agree that this is a pure bikeshed at this point. If
open_optionsis favoured, I'm absolutely fine with it.workingjubilee commentedon Jul 5, 2021
Recap
File::open_options()as an alternative, because it sorts directly next toFile::open(Path)in the method overview, and proposes other shorthands likeFile::open_rw(),File::open_append(), orFile::create_new().create_new()come in here? How exactly would it differ fromcreate(Path)in usage?OpenOptionsis meaningfully distinct fromFile::open_options()because it's a type (a "noun") not a function (a "verb"), and thus dissociated fromFile.fn open_options(arg) -> OpenOptionsis what he would expect, on the basis of the "verb" being included and implying something similar towith_.fn open(Path)andfn open_options()are unnecessarily ambiguous next to each other.fn options()will carry more weight over time (alongsidefn option()) and become a common library pattern.Other Ideas
If the problem is imports, why not just use an
std::fs::prelude::*a lastd::io::prelude::*?Reflections
Rereading this reveals what now feels like a misstep in the early drafts of the
FileAPI, and I would like to offer these remarks to both m-ou-se's and Josh's comments regarding the relationship (or not) ofOpenOptions,fn open_options, andfn open:I don't think it's a problem that
fn open_optionsis nullary whereasfn openis unary, or that one is a constructor for aResult<File>and the other is a constructor for an OpenOptions that will eventually yield aResult<File>.I think the problem is that they are actually logically unrelated, or perhaps I should say that
OpenOptionsis the distant ancestor ofFile::open(Path), not the immediate parent.OpenOptionsis far more ambiguous than what you can get fromFile::open(Path)because it can imply creating a file, appending to an existing file, reviewing and editing the contents of an existing file, or opening a file in read-only mode.File::open(Path)only supports the last. ThusFile::open_options()would only bear a passing resemblance in use toFile::open(Path), which would actually be something more likeFile::read(Path)if I had my druthers.This difference itself would not be a huge issue, honestly, but we have a relatively strong norm of highly "patterned" names in other
stdAPIs, and people would expect two names which use the same initial word to have similar meaning, when one is far different. But I don't believe that is a definitive argument against usingfn open_options()per se, merely that it is an issue. I would probably want to research answers to some of the other questions more.workingjubilee commentedon Jul 5, 2021
A quick skim of grep.app for
open_optionsreveals that the dominant use of it is "a variable or struct field that is OpenOptions". In one or two cases it is in fact used as "open with this OpenOptions".Searching for the regexp /
fn open_.*\(/ yields quite a lot of examples of "open_somethingthat takes an argument", it's true./
fn options?(<.*>)?\(/ shows thatfn optionandfn optionsare both about equally often a "getter" and a nullary constructor, and sometimes it also takes an argument other thanself.So there's some data: clear as mud! 😃
jplatte commentedon Sep 22, 2021
Another possibility: First introduce additional
Fileconstructors such asFile::(open_)?append, then re-evaluate how much the additionalOpenOptionsconstructor is.yaahc commentedon Oct 14, 2021
This has been stalled for a while and so I'm nominating it for discussion in our next meeting to help it get unblocked.
yaahc commentedon Oct 20, 2021
The PR stabilizing this feature, #85766, has entered its final comment period with disposition merge.
Stabilize File::options()
Rollup merge of rust-lang#85766 - workingjubilee:file-options, r=yaahc