I've written the following method:
Date>>to: anObject do: aBlock "For each date in the interval from the receiver up to the argument, incrementing by 1 day, evaluate aBlock. Date today to: (Date today addDays: 4) do: [:date | Transcript cr; show: date displayString] " ^self asDays to: anObject asDate asDays do: [:days | aBlock cull: (self class fromDays: days)] But it raises an exception and I cannot debug it. I suspect it's because Number>>to:do: is inlined, or some other compiler optimization. But why should compiler tricks for Number>>to:do: interfere with Date>>to:do:? -- [hidden email] _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Dave,
Throw a breakpoint here when you compile your Date>>to:do: and you'll notice that the node satisfies the requirement for optimization, transformToDo ^(self testLiteralBlock: 1 at: 2) ifTrue: [arguments last arithmeticLoopFrom: receiver by: (LiteralNode new value: 1) to: arguments first from: self] ifFalse: [nil] -Boris -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Dave Sent: Monday, February 11, 2013 1:57 PM To: VWNC Subject: [vwnc] compiler optimizations get in the way? I've written the following method: Date>>to: anObject do: aBlock "For each date in the interval from the receiver up to the argument, incrementing by 1 day, evaluate aBlock. Date today to: (Date today addDays: 4) do: [:date | Transcript cr; show: date displayString] " ^self asDays to: anObject asDate asDays do: [:days | aBlock cull: (self class fromDays: days)] But it raises an exception and I cannot debug it. I suspect it's because Number>>to:do: is inlined, or some other compiler optimization. But why should compiler tricks for Number>>to:do: interfere with Date>>to:do:? -- [hidden email] _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Dave & Vicki Stevenson
On 02/11/2013 10:56 AM, Dave wrote:
> But why > should compiler tricks for Number>>to:do: interfere with Date>>to:do:? > It's not just compiler tricks, #to:do: and the like are actually reserved selectors in most Smalltalk implementations and any method implemented with a reserved selector will never be invoked (except, typically, through #perform:). This practice dates back to Smalltalk-80 (if not before) but is somewhat unfortunate in that it introduces inconsistencies into the language that lead to unexpected results like those you encountered. Regards, -Martin _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Dave & Vicki Stevenson
Alternatively, you could write your own DateInterval and do;
(Date today to: (Date today addDays: 4)) do: [:date | ... ]. Do (1 to: 4) inspect. This will create an interval. An interval understands #do: You could create a similar Date interval. Terry =========================================================== Terry Raymond Crafted Smalltalk 80 Lazywood Ln. Tiverton, RI 02878 (401) 624-4517 [hidden email] =========================================================== > -----Original Message----- > From: [hidden email] [mailto:[hidden email]] On > Behalf Of Dave > Sent: Monday, February 11, 2013 1:57 PM > To: VWNC > Subject: [vwnc] compiler optimizations get in the way? > > I've written the following method: > > Date>>to: anObject do: aBlock > "For each date in the interval from the receiver up to the argument, > incrementing by 1 day, evaluate aBlock. > > Date today to: (Date today addDays: 4) do: [:date | Transcript cr; > show: date displayString] > " > > ^self asDays > to: anObject asDate asDays > do: [:days | aBlock cull: (self class fromDays: days)] > > But it raises an exception and I cannot debug it. I suspect it's because > Number>>to:do: is inlined, or some other compiler optimization. But why > should compiler tricks for Number>>to:do: interfere with Date>>to:do:? > > -- > [hidden email] > > _______________________________________________ > vwnc mailing list > [hidden email] > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Thanks to all who replied.
So the problem is not that my implementation of Date>>to:do: is optimized, but that any code trying to call Date>>to:do: (like the usage example in the method comment) gets optimized by #arithmeticLoopFrom:by:to:from:, based solely on the fact that the do: block has one argument. Too bad the optimization cannot take into account the type of the receiver, but that's not always known at compile time. I've looked at: MessageNode class>>initialize ImplementationLimits7x.pdf - "Open-coded Blocks" and "Non-verridable Methods" and inspecting the optimized client code shows that it gets implemented as a #whileTrue: loop. I could override #transformToDo to do nothing if a special characteristic is found for the do block. I don't think method pragmas can be used in blocks. A test as to whether '*date*' matches the name of the block parameter would break blocks with parameters named 'dateIndex', or some such, and any client code that did not remember to spell the block argument properly would break. So the only reliable way that comes to mind is to give the block an extra unused argument, which does not seem desirable at all. I cannot see a good way to reuse the api (#to:do:), which is unfortunate since it is so easy to remember. I think I'd be more likely to remember a different api (Date>>through:do:, or something) than remember the extra parentheses required by the use of a DateInterval. Still, it would be nice if there were a way to selectively avoid optimization. Maybe #toDate:do: would be a good alternative. It should be easy to remember that any alternate implementations of #to:do: requires the expected type as part of the first keyword. Dave [hidden email] On 2/11/2013 12:00 PM, Terry Raymond wrote: > Alternatively, you could write your own DateInterval and do; > (Date today to: (Date today addDays: 4)) do: [:date | ... ]. > > Do (1 to: 4) inspect. This will create an interval. An interval understands > #do: > You could create a similar Date interval. > > Terry > > =========================================================== > Terry Raymond > Crafted Smalltalk > 80 Lazywood Ln. > Tiverton, RI 02878 > (401) 624-4517 [hidden email] > =========================================================== > >> -----Original Message----- >> From: [hidden email] [mailto:[hidden email]] On >> Behalf Of Dave >> Sent: Monday, February 11, 2013 1:57 PM >> To: VWNC >> Subject: [vwnc] compiler optimizations get in the way? >> >> I've written the following method: >> >> Date>>to: anObject do: aBlock >> "For each date in the interval from the receiver up to the argument, >> incrementing by 1 day, evaluate aBlock. >> >> Date today to: (Date today addDays: 4) do: [:date | Transcript cr; >> show: date displayString] >> " >> >> ^self asDays >> to: anObject asDate asDays >> do: [:days | aBlock cull: (self class fromDays: days)] >> >> But it raises an exception and I cannot debug it. I suspect it's because >> Number>>to:do: is inlined, or some other compiler optimization. But why >> should compiler tricks for Number>>to:do: interfere with Date>>to:do:? >> >> -- >> [hidden email] >> >> _______________________________________________ >> vwnc mailing list >> [hidden email] >> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc > > > _______________________________________________ > vwnc mailing list > [hidden email] > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc > _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Dave Stevenson <dave.stevenson <at> pacbell.net> writes:
> > Thanks to all who replied. > > So the problem is not that my implementation of Date>>to:do: is > optimized, but that any code trying to call Date>>to:do: (like the usage > example in the method comment) gets optimized by > #arithmeticLoopFrom:by:to:from:, based solely on the fact that the do: > block has one argument. Too bad the optimization cannot take into > account the type of the receiver, but that's not always known at compile > time. > > I've looked at: > MessageNode class>>initialize > ImplementationLimits7x.pdf - "Open-coded Blocks" and > "Non-verridable Methods" > > and inspecting the optimized client code shows that it gets implemented > as a #whileTrue: loop. > > I could override #transformToDo to do nothing if a special > characteristic is found for the do block. I don't think method pragmas > can be used in blocks. A test as to whether '*date*' matches the name of > the block parameter would break blocks with parameters named > 'dateIndex', or some such, and any client code that did not remember to > spell the block argument properly would break. So the only reliable way > that comes to mind is to give the block an extra unused argument, which > does not seem desirable at all. > > I cannot see a good way to reuse the api (#to:do:), which is unfortunate > since it is so easy to remember. I think I'd be more likely to remember > a different api (Date>>through:do:, or something) than remember the > extra parentheses required by the use of a DateInterval. Still, it would > be nice if there were a way to selectively avoid optimization. > > Maybe #toDate:do: would be a good alternative. It should be easy to > remember that any alternate implementations of #to:do: requires the > expected type as part of the first keyword. > > Dave > > dave.stevenson <at> pacbell.net > Note that you can also send a message to the block argument, for example 1 to: 4 do: [:i | i inspect] yourself. will generate a compile-time warning in VW, but then compile a simple un-optimized #to:do: send. Instead of #yourself, we could as well define a [ ] unoptimized, which is IMO not worse than a method annotation (pragma). I don't especially recommend using this hack, it's far from ideal, but it's always good to know. Note that the hack works in Squeak too (and probably Pharo). Nicolas _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
In reply to this post by Dave Stevenson-3
---------- Forwarded message ---------- From: Eliot Miranda <[hidden email]> Date: Mon, Feb 11, 2013 at 1:44 PM Subject: Re: [vwnc] compiler optimizations get in the way? To: Dave Stevenson <[hidden email]> Hi Dave, you to:do: loop to: anObject asDate asDays do: [:days | aBlock cull: (self class fromDays: days)]
is being compiled to something equivalent to days := tmpresult := self asDays. tmplimit := anObject asDate asDays. [days <= tmplimit] whileTrue:
[aBlock cull: (self class fromDays: days). days := days + 1]. ^ tmpresult where tmplimit and tmpresult are compiler-introduced temporaries.
If you make your asDays object polymorphic with Integer for arithmetic (i.e. that aDay + anInteger is equivalent to aDay addDays: anInteger) then your loop may work. Anyway, worth a try. You might also find that the problem is actualy your returning the result of the loop. What happens if you write self asDays to: anObject asDate asDays do: [:days | aBlock cull: (self class fromDays: days)].
^self asDays? On Mon, Feb 11, 2013 at 12:47 PM, Dave Stevenson <[hidden email]> wrote: Thanks to all who replied. best, Eliot
best, Eliot
_______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
OK, it's kind of flaky silently coercing Integers and Duartions. wouldn't it be better to use Chronos? But, the below code does the trick. -- Mike === workspace Date today to: (Date today addDays: 2) do: [ :date | Transcript print: date; cr]. ===
Core.Integer methods for 'converting' asDuration ^Duration fromDays: self === Core.Date methods for 'arithmetic'
+ aDuration ^self sumFromDuration: aDuration asDuration _______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
---------- Forwarded message ---------- From: Eliot Miranda <[hidden email]> Date: Mon, Feb 11, 2013 at 1:55 PM Subject: Re: [vwnc] Fwd: compiler optimizations get in the way? To: Michael Klein <[hidden email]> On Mon, Feb 11, 2013 at 1:52 PM, Michael Klein <[hidden email]> wrote:
Yes, if self asDays class = self asYears class
because then + 1 is meaningless. But if self asDays is a thing that knows its units are days and self asYears (etc) answers a thing that knows its units are years then no, I don't think its flakey, I think its convenient.
But I'm not advocating. I'm just trying to help Dave understand what's going on.
best, Eliot
best, Eliot
_______________________________________________ vwnc mailing list [hidden email] http://lists.cs.uiuc.edu/mailman/listinfo/vwnc |
Free forum by Nabble | Edit this page |