This seems like a good idea IMO, but:
- why make these methods private instead of public?
- precisely what methods do you want to see added?
Also, subclassing builtin classes is often not a good idea (see ).
-- Paul Brannan
You haven't explained the reason why you need mutable version of Time. Why do you need to implement the mutable time which also is subclass of Time? Is the reason important enough to change the standard class behavior? Remember immutable is often better than mutable, not to allow unexpected side effect.
--matz.
I don't understand why I should have to justify why I happen to want to write SubClassX that inherits from ClassX to justify adding hooks to ClassX that are generally useful for any subclassing of it. The change I'm proposing (in particular to the Time class, in general to various Builtins):
- Has zero impact on existing code
- Should have (near-)zero impact on performance
- /Should/ be rather easy to implement
- Provides functionality previously lacking from the Time class, necessary (IMO) for proper subclassing
But, while I don't believe my particular use needs to be justified, apparently you do :) So:
I like my MutableTime class for code like this:
def printWeek (day)
#...
end
aDate = MutableTime.now
(1..24).each{
printMonth(aDate)
aDate.month+=1
}
In general, I want the ability to directly set any value for seconds/minutes/hours/date/month/year. With the Time class as it currently exists, I can sort of easily 'change' the seconds/minutes/hours/date by using the + method and getting a new time class:
aDate = aDate + 7*DAY_IN_SECONDS
but this both requires annoying calculations, and does not work for months or years. I cannot do this using a custom date= method either, since the return value of such a method is the rvalue, so I can't even hack it using code like:
aDate = aDate.date+=7
which might return a new Time instance. (And doing something like aDate = aDate.call('date=',aDate.date+7) is an unacceptable hack, for me.)
The only way I can see to do it would be something like:
class Time
def setDate(newDate)
self+newDate*DAY_IN_SECONDS
end
end
which would still require me to call it via
aDate=aDate.setDate(aDate.date+7)
BUT: However flawed the above desire may or may not be in your eyes, what I'm asking for in general is simply a way to access the private instance variables which Time obviously has, but which does not expose even to subclassed methods because they are hidden behind C and not Ruby code. Whether or not you agree with the particular reason I want to extend the Time class in this instance, hopefully you agree that in general a Subclass should be have full access to the private instance variables of the class it inherits from, whether that class was written in Ruby or C.
--RabYak (aka Gavin Kistner)
Oh, and as for which methods in particular I want added, I listed them in the first sentence of the proposal. Really, that would do it :)
--RabYak
RabYak,
You have to understand the language design rationale cannot be "just because". You have to consider the impact of the desgin to the users. From what you mantioned, all you want is actually
aTime += 7
without allocating new Time object. But this is nearly impossible with Ruby's design of "+=", unless we make a huge change to the language.
Back to Time class, its internal state is actually a single integer that shows seconds since the Epoch (1970-01-01 0:00 GMT). The timeval struct is merely a cache. If you understand this, you might realize it is not that easy to implement methods like "setDate" or "setTimeZone" for Time class.
Ruby's Time class is a representation of C's time_t (note that it's not struct timeval) with fancy formatting methods, so I feel like your proposal is changing Time's role. I feel you are trying to change the Ruby Way (of course this is my personal feeling).
Why do you hate allocation so much, when even numbers are immutable objects?
--matz.
Matz
First, what are you doing spending time writing in-depth responses to newbie RCRs like mine this early? Get back to working on Ruby2 and let your underlings deal with my foolishness! :)
Anyhow...I thought that I had considered the impact to the language. I do personally want (and already have, through my implementation of MutableTime) the ability to do:
aTime.date+=5
aTime.month+=12
#...
...but since the Time object doesn't support this natively, I'm quite happy to say "OK, Time doesn't do what I want; rather than trying to change Time itself to do what I want, I'll just write my own class." Which is what I did, but had to do it without inheritance.
Discussing this more on IRC (which I should have done before bringing a formal RCR) I understand now that this change--providing hooks which allow subclasses to mutate a Time instance--essentially makes Time itself mutable, given the existance of 'instance_eval' and the simple ability for users to do:
class Time
def changeMe
# call the private methods described in this RCR
end
end
And while I don't personally see that as bad (it's added flexibility, not changing the core way the 'default' Ruby setup encourages you to program) I do understand that it causes more effect on the language than the near-zero-impact I was envisioning.
The killing blow is the information that the current internal implementation of Time is not mutable, as you say. I must have read the C-code wrong. Given your assertion that it's non-trivial to make this change, I am now voting against my own RCR and will withdraw it.
[And have been convinced by people on IRC that, however well-meaning I may be, I really need to have 1 to 1.5 years' experience with the language before I propose another RCR. I'll try hard to wait :)]
This seems like a good idea IMO, but:
Also, subclassing builtin classes is often not a good idea (see ).
-- Paul Brannan
You haven't explained the reason why you need mutable version of Time. Why do you need to implement the mutable time which also is subclass of Time? Is the reason important enough to change the standard class behavior? Remember immutable is often better than mutable, not to allow unexpected side effect.
--matz.
I don't understand why I should have to justify why I happen to want to write SubClassX that inherits from ClassX to justify adding hooks to ClassX that are generally useful for any subclassing of it. The change I'm proposing (in particular to the Time class, in general to various Builtins):
But, while I don't believe my particular use needs to be justified, apparently you do :) So:
I like my MutableTime class for code like this:
In general, I want the ability to directly set any value for seconds/minutes/hours/date/month/year. With the Time class as it currently exists, I can sort of easily 'change' the seconds/minutes/hours/date by using the + method and getting a new time class:
but this both requires annoying calculations, and does not work for months or years. I cannot do this using a custom date= method either, since the return value of such a method is the rvalue, so I can't even hack it using code like: which might return a new Time instance. (And doing something like aDate = aDate.call('date=',aDate.date+7) is an unacceptable hack, for me.)The only way I can see to do it would be something like:
which would still require me to call it viaBUT: However flawed the above desire may or may not be in your eyes, what I'm asking for in general is simply a way to access the private instance variables which Time obviously has, but which does not expose even to subclassed methods because they are hidden behind C and not Ruby code. Whether or not you agree with the particular reason I want to extend the Time class in this instance, hopefully you agree that in general a Subclass should be have full access to the private instance variables of the class it inherits from, whether that class was written in Ruby or C.
--RabYak (aka Gavin Kistner)
Oh, and as for which methods in particular I want added, I listed them in the first sentence of the proposal. Really, that would do it :)
--RabYak
RabYak,
You have to understand the language design rationale cannot be "just because". You have to consider the impact of the desgin to the users. From what you mantioned, all you want is actually
without allocating new Time object. But this is nearly impossible with Ruby's design of "+=", unless we make a huge change to the language.
Back to Time class, its internal state is actually a single integer that shows seconds since the Epoch (1970-01-01 0:00 GMT). The timeval struct is merely a cache. If you understand this, you might realize it is not that easy to implement methods like "setDate" or "setTimeZone" for Time class.
Ruby's Time class is a representation of C's time_t (note that it's not struct timeval) with fancy formatting methods, so I feel like your proposal is changing Time's role. I feel you are trying to change the Ruby Way (of course this is my personal feeling).
Why do you hate allocation so much, when even numbers are immutable objects?
--matz.
Matz
First, what are you doing spending time writing in-depth responses to newbie RCRs like mine this early? Get back to working on Ruby2 and let your underlings deal with my foolishness! :)
Anyhow...I thought that I had considered the impact to the language. I do personally want (and already have, through my implementation of MutableTime) the ability to do:
...but since the Time object doesn't support this natively, I'm quite happy to say "OK, Time doesn't do what I want; rather than trying to change Time itself to do what I want, I'll just write my own class." Which is what I did, but had to do it without inheritance.
Discussing this more on IRC (which I should have done before bringing a formal RCR) I understand now that this change--providing hooks which allow subclasses to mutate a Time instance--essentially makes Time itself mutable, given the existance of 'instance_eval' and the simple ability for users to do:
And while I don't personally see that as bad (it's added flexibility, not changing the core way the 'default' Ruby setup encourages you to program) I do understand that it causes more effect on the language than the near-zero-impact I was envisioning.
The killing blow is the information that the current internal implementation of Time is not mutable, as you say. I must have read the C-code wrong. Given your assertion that it's non-trivial to make this change, I am now voting against my own RCR and will withdraw it.
[And have been convinced by people on IRC that, however well-meaning I may be, I really need to have 1 to 1.5 years' experience with the language before I propose another RCR. I'll try hard to wait :)]