Hi all
I have been using Dolphin for over a year, but I still find myself stuck on quite simple points. Could some kind person give me a steer on my current hold-up? I am trying to tidy up the coding of a part of my app (which may be my first mistake - it works, so perhaps I should leave it alone!). I have modified the coding of the method View>>#onMouseWheeled:, and my code currently reads: test := self topView allSubViews select:[:view|{condition}]. selectedView := test notEmpty ifTrue: [test at: 1] ifFalse: [nil]. The logic of the selection {condition} specifies that the number of successful selects will be zero or one (usually one), so it seems inefficient to test all the remaining views once I have found the one that satisfies the condition. At first sight it looks as though SequenceableCollection>>#findFirst: should do what I want, but this returns the index of the matching view, not the view itself. I can get round this by writing something like: gotIt := (allViews := self topView allSubViews) findFirst:[:view|{condition}]. selectedView := gotIt > 0 ifTrue: [allViews at: gotIt] ifFalse:[nil]. but somehow this looks kludgy. What I would like is an equivalent of #findFirst: which returns the matching element, not its index, and presumably nil if no match. Since I can't find such a method, I tried to construct the equivalent using #do: or #keysAndValuesDo:, but I find I have no idea how to break out of the loop when I have found a matching element. If I could, I would write something like: selectedView := nil. self topView allSubViews do: [:view| {condition} ifTrue: [selectedView := view. break]]. which looks the neatest of all. Is there any way of breaking out of a loop like this? Is it worth worrying about making the code more efficient anyway? - I started programming when we had to think about efficiency, but maybe it doesn't matter now. Sorry to ask such trivial questions. Thanks in advance for any help. Peter Kenny |
Peter,
> test := self topView allSubViews select:[:view|{condition}]. > selectedView := test notEmpty ifTrue: [test at: 1] ifFalse: [nil]. It looks like you want #detect:ifNone: which will go through a collection and answer the first one that passes the test, or nil if none do. selectedView := self topView allSubViews detect: [:each | {condition}] ifNone: [] NB an empty block answers nil > Is there any way of breaking out of a loop like this? Is it worth worrying > about making the code more efficient anyway? - I started programming when we > had to think about efficiency, but maybe it doesn't matter now. The normal way (other than using #detect) would be to put the test in another method and return the found value or nil from there. Something like whateverOrNil := self findItFrom: aCollection and MyClass>>findItFrom: aCollection aCollection do: [:each | {condition} ifTrue: [^each]]. ^nil -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
"Ian Bartholomew" <[hidden email]> wrote in message
news:[hidden email]... > Peter, > > > test := self topView allSubViews select:[:view|{condition}]. > > selectedView := test notEmpty ifTrue: [test at: 1] ifFalse: [nil]. > > It looks like you want #detect:ifNone: which will go through a > collection and answer the first one that passes the test, or nil if none do. Ian Thanks a lot. What I was looking for is exactly what #detect:ifNone: does, so this solves my problem. I was considering another method to Collection by adapting the code of #findFirst:, but it already exists - however the difference of terminology between 'find' to 'detect' managed to hide that from me! Thanks again Peter |
In reply to this post by Ian Bartholomew-21
Peter,
>> test := self topView allSubViews select:[:view|{condition}]. >> selectedView := test notEmpty ifTrue: [test at: 1] ifFalse: [nil]. > > > It looks like you want #detect:ifNone: which will go through a > collection and answer the first one that passes the test, or nil if none > do. > > selectedView := self topView allSubViews > detect: [:each | {condition}] > ifNone: [] > > NB an empty block answers nil I think Ian pegged it. To his reply I will add that you might look at #detect:ifNone: compared to #detect:, which signals an error if no item is found. In GUI code (handling mouse events qualifies), you probably do not want errors being generated, but in many other situations, it is nice to have the code complain at the site of the problem (unable to find a suitable element) vs. fumbling along until a less obvious DNU error occurs later. Note that error handlers ( #on:do: etc.) have costs to establish and greater costs to trap an error. However, there are times when you might know what happened but not what to do about it - signalling an error to be trapped at higher levels is the cleanest (and most idiot proof<g>) way to handle it. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
"Bill Schwab" <[hidden email]> wrote in message
news:de2n1n$12he$[hidden email]... > Peter, > > I think Ian pegged it. To his reply I will add that you might look at > #detect:ifNone: compared to #detect:, which signals an error if no item > is found. In GUI code (handling mouse events qualifies), you probably > do not want errors being generated, but in many other situations, it is > nice to have the code complain at the site of the problem (unable to > find a suitable element) vs. fumbling along until a less obvious DNU > error occurs later. > > Note that error handlers ( #on:do: etc.) have costs to establish and > greater costs to trap an error. However, there are times when you might > know what happened but not what to do about it - signalling an error to > be trapped at higher levels is the cleanest (and most idiot proof<g>) > way to handle it. > > Have a good one, > > Bill > > > -- > Wilhelm K. Schwab, Ph.D. > [hidden email] Bill Thanks for the advice. I shall bear it in mind for future use. In the present context the ifNone: case is not an error, it just means 'do nothing'. What I am doing is modifying the handling of mouse wheel events so that the pane that scrolls is the one containing the cursor, not what Windows calls the 'active pane' (i.e. I want Dolphin to do what Squeak does in this respect). The ifNone: case arises if the cursor is pointing at a non-scrollable part of the window (or outside the window). Thanks again Peter |
Free forum by Nabble | Edit this page |