-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Keyword-Only Arguments; leads to more readable code and fwd-compatible changes in API's #8306
Comments
The argument about making it easier to deprecate/add named parameters is really important IMO. It's currently unclear when it's "safe" to use named parameters when calling third-party code, since renaming a parameter is typically not treated as a breaking change. If the parameter can only be used as a named parameter however, it's obvious that any change to the name is a breaking change. This also opens up the possibility of having a deprecation path when a named parameter is renamed. The case where a named parameter had to be added to the beginning of the parameter list has already happened in |
Not a bad idea, but my favourite style is to reify the options: type GlobOptions = object
relative, expandDirs, includeHidden, includeDirs: bool
walkGlobKinds("*.*", root = "", options=GlobOptions(relative: true)) |
problem with that is defaults become an all or nothing: proc fun(pattern: string, options=GlobOptions(root:"/", relative: true, includeDirs: true)) = ...
fun("*.*") # uses all the defaults, ie GlobOptions(root:"/", relative: true, includeDirs: true)
# but if we want to override just 1 field (say, `relative: false`) and keep other defaults, it's not DRY:
fun("*.*", options=GlobOptions(root:"/", relative: false, includeDirs: true)) that reified style is actually what prompted me to write proc initGlobOptions():auto=GlobOptions(root:"/", relative: true, includeDirs: true)
proc fun(pattern: string, options=initGlobOptions()) = ...
fun("*.*", options=initGlobOptions().updateObj(relative = false))
# instead of, without reified style:
fun("*.*", relative = false) @andreaferretti Curious whether you have some good ideas on this... That being said, this RFC is useful independently of that point |
You know what sucks much more? A language that never stabilizes. -1 from me on yet another language feature. walkGlobKinds("*.*", root = "", relative = true, expandDirs = true, includeHidden = false; includeDirs = false) Should make use of Nim's walkGlobKinds("*.*", root = "", {Glob.relative, Glob.expandDirs}) |
unfortunately Here's another typical example to that effect, from osproc.startProcess, where not all args fit in a proc startProcess(command: string; workingDir: string = "";
args: openArray[string] = []; env: StringTableRef = nil;
options: set[ProcessOption] = {poStdErrToStdOut}): Process {..}
# this is obvious without reading docs
startProcess("bar", workingDir = "foo", env = ["FOO" : "BAR"], options = {poStdErrToStdOut})
# this is not so obvious:
startProcess("bar", "foo", nil, ["FOO" : "BAR"], {poStdErrToStdOut}) |
@timotheecour a little more verbose, but one can do var opt = defaultOptions()
opt.relative = true
walkGlobKinds("*.*", root = "", opt) |
Also, if the proposal for default values for object fields gets accepted, the problem af all or nothing goes automatically away |
Yes, I know, named arguments are awesome. Use them. You don't need enforcement in order to use something. |
Yep the So while I wouldn't be opposed to this feature I'm in agreement with @Araq, this is kind of unnecessary. |
I agree with everything @Araq said. I didn't even know Python had this feature. As such I think the consensus is to reject this and therefore close this issue (sorry). |
let's start with a quizz: which one of these is easier to understand ? (taken from @citycide's excellent
glob
library)Clearly, the 2nd one. The 1st one pretty much forces you to read the docs at every single such function call even if you're familiar with that API.
Yet, the 2nd one is not enforced by the compiler and relying on convention sucks.
The use case is to force callers to use keyword calling as opposed to positional calling for these arguments, with benefits:
NOTE: keyword-only arguments would make such API evolution and parameter deprecation much easier and less error prone (see [RFC] API simplification haltcase/glob#11 [RFC] API simplification for example)
python's approach
here's python's syntax + example from https://stackoverflow.com/questions/2965271/forced-naming-of-parameters-in-python to illustrate:
NOTE: relevant snippet from [PEP3102](https://www.python.org/dev/peps/pep-3102/ introduced keyword only arguments :
suggested syntax up for discussion:
we could use same syntax as python, nice and simple, but which particular syntax doesn't matter much
[1]
The text was updated successfully, but these errors were encountered: