Open aconsroe-hpe opened 2 years ago
Another possibility is to simply drop them because they are a thin convenience over writing new date(2021, mydate.month, mydate.day). I see the utility of these methods as a toss-up and would err towards dropping them unless we had a consistent pattern that we wanted to adopt across all standard modules (or at the language level with a "record update" or "functional update" feature like in OCaml (date with year=2021)).
I think dropping them can reduce ease-of-use in the larger records, especially datetime
. If you want to just change the second
, you'd have to enumerate all the other fields of it as initializer arguments.
I would just rename/simplify them as set of replaceX
methods as you describe.
With a return type in the proc signature, I would personally find the documentation clear on the behavior (eg. proc date.replace(year=0, month=0, day=0): date {}) and wouldn't feel strongly about a different name.
I feel similarly to this, and the proposal in #19110 would also help with that confusion if we were to implement it. As noted there, I wouldn't choose a more complex name simply to try and telegraph this more clearly to the user.
Do we actually use different sentinels in the following two cases? That seems odd...
proc date.replace(year=0, month=0, day=0) { }
proc datetime.replace(year=-1, month=-1, day=-1,
splitting out the single method into multiple methods to handle each part.
Is there any reason not to have both? (the current single routine, and the per-component routines?). Specifically, the requirement to write things like this: myDate.replaceYear(2021).replaceMonth(10)
relative to myDate.replace(year=2021, month=10)
seems unfortunate to me.
Of course, if we were to do that, there's no rush to add the per-component routines now / for 2.0. We could wait until someone wanted them.
Of course, if we were to do that, there's no rush to add the per-component routines now / for 2.0. We could wait until someone wanted them.
This is where I'm leaning as well.
Do we actually use different sentinels in the following two cases?
I was overlooking that. In a 100% compat mindset, changing the 0
to -1
is a breaking change. I know we don't have to be absolutist on this front (esp. for the nature of the module), so perhaps it could be okay to make that change.
In a 100% compat mindset, changing the 0 to -1 is a breaking change. I know we don't have to be absolutist on this front (esp. for the nature of the module), so perhaps it could be okay to make that change.
I think it'd be fine to make the change. Am I right that the only way a user would notice it would if they were to explicitly pass the sentinel value in themselves? I don't think we need to worry about protecting against a case like that, particularly given how infrequently I suspect this routine is used today—and especially if the routine itself does bounds checks and would complain if someone were passing in a 0 going forward.
(This case, though, reminds me of a long-standing desire to have a param
"didUserOverwriteDefaultValue()" query implemented by the compiler, which would allow us to distinguish between our default value and the user passing in the same one; where I'd argue, the former should cause it not to be replaced and the latter should result in an OOB-style message).
In the Time module final review we decided to:
replace
Time
)replaceX
methods post-2.0.Noting this issue is only still open to allow discussing splitting into replaceX
methods
As part of the module reivew for
DateTime
, we identified the.replace
family of methods ondate
,time
, anddatetime
as a potential area of improvement.Currently, those signatures are below and the current behavior of each is to return a new record with the fields given
The name
replace
could be misleading because it might suggest an in-place update, but this is consistent with thestring.replace
method which also returns a new string. With a return type in theproc
signature, I would personally find the documentation clear on the behavior (eg.proc date.replace(year=0, month=0, day=0): date {}
) and wouldn't feel strongly about a different name.Another direction we discussed was splitting out the single method into multiple methods to handle each part. This is a similar direction to #16767, though the list begins to grow:
This is similar in spirit to java.time.LocalDate (and related classes) that have a
withMonth
,withYear
, andwithDayOfMonth
methods. Those also return new objects.One benefit here is that there is no potential confusion around the default args in the current methods. Besides
date.replace
using0
as a sentinel as opposed to-1
like its siblings, these are perhaps not as precise as we might like. One downside is that you have to use method chaining to replace multiple fields likemyDate.replaceYear(2021).replaceMonth(10)
.Another possibility is to simply drop them because they are a thin convenience over writing
new date(2021, mydate.month, mydate.day)
. I see the utility of these methods as a toss-up and would err towards dropping them unless we had a consistent pattern that we wanted to adopt across all standard modules (or at the language level with a "record update" or "functional update" feature like in OCaml(date with year=2021)
).