Page 1 of 1
dif between counting up vs counting down
Posted: Wed May 15, 2013 3:03 pm
by Coffee1633
I was going through the sheep herder tutorials and in lecture 4 there is a sheepClear handler that counts the buttons from (the number of btns down to 1)
see code below. It works and I don't have a problem with that. However... and here is the problem
if you replace
"repeat with i = the number of btns of this stack down to 1" with
"repeat with i = 1 to the number of btns of this stack" it crashes.
Any ideas why this would be the case?
I ran some experiments using this logic on several test stacks and I was getting the same result. i.e. works with "the number of buttons down to 1" but not the other way around. hmmm...
(line 3 works the way it is written but not if you use: "...with i = 1 to the number of buttons of this stack" - why not?)
on clearSheep
lock screen
repeat with i = the number of btns of this stack down to 1
if the short name of btn i of this stack begins with "sheep" then
delete btn i of this stack
end if
end repeat
unlock screen
end clearSheep
coffee16
Re: dif between counting up vs counting down
Posted: Wed May 15, 2013 3:37 pm
by Klaus
Hi Coffe,
well, objects like buttons, fields, graphics, images etc. are counted relative to the CARD and not the stack.
So this is just invalid syntax, but should not crash in any case!
If you do:
...
put the num of buttons of this stack
..
You will only get the number of buttons on the CURRENT card!
So you need to loop through all cards and all buttons on every card:
Code: Select all
on clearSheep
lock screen
## Loop through all cards...
repeat with tCardNumber = 1 to the num of cds
## ... and then through all buttons on that card:
repeat with i = the number of btns of cd tCardNumber down to 1
if the short name of btn i of cd tCardNumber begins with "sheep" then
delete btn i of cd tCardNumber
end if
## END of button loop
end repeat
## END of card loop
end repeat
unlock screen
end clearSheep
Best
Klaus
Re: dif between counting up vs counting down
Posted: Wed May 15, 2013 4:26 pm
by dunbarx
The difference between counting up and counting down is usually only pertinent if you are deleting elements along the way. This comes simply from the way stuff is ordered, and you can see this easily with a few tests.
So if you have a list of five lines in field 1:
abc
abc
def
def
abc
and write something like:
on mouseUp
repeat with y = the number of lines of fld 1 down to 1
if line y of fld 1 = "def" then delete line y of fld 1
end repeat
end mouseUp
on mouseUp
repeat with y = 1 to the number of lines of fld 1
if line y of fld 1 = "def" then delete line y of fld 1
end repeat
end mouseUp
Watch what happens in each case. Do you see how the way we (and LC) counts makes only the first one work reliably?
Craig Newman
Re: dif between counting up vs counting down
Posted: Sat May 18, 2013 3:53 am
by Coffee1633
Yes, I see.
After setting a breakpoint in the repeat loop I see why it counting up from 1 doesn't work and only counting backwards does.
thanks, that cleared up a nagging issue for me.
coffee16
Re: dif between counting up vs counting down
Posted: Sat May 18, 2013 5:49 am
by Dixie
coffeecone...
Craig nailed the problem for you... It would be worth your while to read up on repeat in the dictionary as there are faster ways to iterate through long lists, using 'repeat for each' rather than 'repeat with'...
Using Craigs' example :-
Code: Select all
on mouseUp
put the number of lines of fld 1 into count
repeat for each line thisLine in fld 1
if line count of fld 1 = "def" then
delete line count of fld 1
end if
subtract 1 from count
end repeat
end mouseUp
would perform much faster if you used the 'repeat for each' method, though this will not show itself to be so using just five lines...
Dixie
Re: dif between counting up vs counting down
Posted: Sat May 18, 2013 4:09 pm
by sturgis
Dixie wrote:coffeecone...
Craig nailed the problem for you... It would be worth your while to read up on repeat in the dictionary as there are faster ways to iterate through long lists, using 'repeat for each' rather than 'repeat with'...
Using Craigs' example :-
Code: Select all
on mouseUp
put the number of lines of fld 1 into count
repeat for each line thisLine in fld 1
if line count of fld 1 = "def" then
delete line count of fld 1
end if
subtract 1 from count
end repeat
end mouseUp
would perform much faster if you used the 'repeat for each' method, though this will not show itself to be so using just five lines...
Dixie
I'm not sure, but I think the problem with the i = type of loop is due to how lc accesses the lines, so even with the "for each" method here, doesn't "delete line count..." still have to cycle through line 1 to line count each loop? In this case, getting faster as the list gets shorter of course since it would go from count down to 1.
If I recall correctly (never a sure thing), to get the benefit of the for each you need to work with the data in "thisline" and rebuild the list, then place the completed list back into the field. Since for each grabs each line sequentially and feeds it to the loop it should be much much faster on datasets as apposed to having to seek the line number each time. (in this loop, twice, once for the if, once for the delete.
Code: Select all
on mouseUp
put field 1 into tData
repeat for each line thisLine in tData
if thisLine is "def" then put this line & cr after tNewData
end repeat
delete the last char of tNewData
put tNewData into field 1
end mouseUp
EDIT: Did the check backwards. Would want to check if not (this line is "def") to get the correct result. DOH!
Re: dif between counting up vs counting down
Posted: Sat May 18, 2013 4:23 pm
by sturgis
Ok, now i'm curious about something.
When addressing lines using -1 (or "last line" ) does it have to index till it finds the last one or does it just start at the end and work backwards till it locates where the line is?
So a different type of loop might be (just quicky code)
Code: Select all
repeat (the number of lines in container) times
if not (the last line of container is "def") then put the last line of container & cr after tNewData
delete the last line of container
end repeat
delete the last char of tNewData
Will append speed comparisons if I get time to try this.
With a million lines, the for each loop takes about 1.5 seconds to complete. I don't have the patience to wait for the various other methods I tried with the exception of 1.
Code: Select all
replace ("def" & cr) in tData -- BLINDINGLY fast.
if the last line of tData is "def" then delete the last line of tData
APPEND:
Placing the resulting lines back into the field takes about 1 sec with my sample data (just the part putting the final data back into a field) This is of course the same for every method.
The speed results - the 1 second for replacing the contents of the for each method, and the replace method are 473 milliseconds with for each, and 73 milliseconds with the replace method. Working directly with the field of course slows all methods down, even the for each method (though in this case the difference is slight, for each line of field "field" works very well, but still no comparison to shoving the data into a variable and using replace)
Append 2:
Filter rocks.
filter field "whateverfield" without "def"
takes 98 millisec on my machine (1 mil lines) when working with a variable. When working directly with a field, still tack on the extra second to the time, which seems to indicate that the data is worked on in a holding variable, then placed back into the container when filter completes. Working directly in a variable yields the sub 98 mill times.
Re: dif between counting up vs counting down
Posted: Mon May 20, 2013 9:58 am
by Coffee1633
Thank you all for your replies. All the suggestions really help me sink my teeth into different design patterns.
Thank you Dixie for the "repeat for each" suggestion
--------------------
>>Craig nailed the problem for you... It would be worth your while to read up on repeat in the dictionary as there are faster ways to iterate through long lists, using 'repeat for each' rather than 'repeat with'...
--------------------(my quote and code buttons don't seem to be working)
What I really want to do is iterate over all the button objects. And I don't believe the "repeat for each" structure will allow me to do that. It only allows
* for each chunkType labelVariable in container
* for each element labelVariable in array
* for each key labelVariable in array
Craig was using some text in a fld just to illustrate a point.
On a sort of related note with iterators
**WishList items: more data structures like hash maps or dictionaries and the ability to iterate through them. Or does LC have these functions?
coffee16
Re: dif between counting up vs counting down
Posted: Mon May 20, 2013 2:35 pm
by sturgis
Oh yep. With buttons i = 1 to.. works fine. Could do a for each and run your own counter but for deleting buttons wouldn't be much point.