Page 1 of 1
ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 1:59 am
by Savapo
Hello,
Please, could you add this functionality to simplify writing programs ?
Thank you.
Code: Select all
NewList List()
AddElement(List())
List()=1
AddElement(List())
List()=2
AddElement(List())
List()=3
; ------
ForEachReverse List() ; <- *** Here, new instruction ***
Debug List() ; -> 3
; -> 2
; -> 1
Next
; ------
ForEach List()
Debug List() ; -> 1
; -> 2
; -> 3
Next
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 2:25 am
by 136
Or just allow "Step" to be used with "ForEach", so we can use "Step -1" to iterate backwards.
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 6:09 am
by Bisonte
not necessary ....
Code: Select all
NewList LinkList()
AddElement(LinkList()) : LinkList() = 1
AddElement(LinkList()) : LinkList() = 2
AddElement(LinkList()) : LinkList() = 3
ForEach LinkList()
Debug LinkList()
Next
Debug "-----"
; This ....
MaxIndex = ListSize(LinkList()) - 1
LastElement(LinkList())
While MaxIndex > -1
Debug LinkList()
PreviousElement(LinkList())
MaxIndex - 1
Wend
Debug "-----"
; Or this...
LastElement(LinkList())
MaxIndex = ListIndex(LinkList())
For i = MaxIndex To 0 Step -1
SelectElement(LinkList(), i)
Debug LinkList()
Next i
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 6:13 am
by STARGĂ…TE
Code: Select all
If LastElement(LinkList())
Repeat
Debug LinkList()
Until PreviousElement(LinkList()) = #False
EndIf
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 2:12 pm
by Tenaja
Bisonte wrote:not necessary ....
Most commands are not necessary, including the original ForEach, as well as most iteration commands.
The o/p referenced simplifying writing; just look how much more elegant this is (with two PB keywords not counting the iteration code)...
Code: Select all
ForEach LinkList()
Debug LinkList()
Next
Compared to this (with six PB keywords)...
Code: Select all
If LastElement(LinkList())
Repeat
Debug LinkList()
Until PreviousElement(LinkList()) = #False
EndIf
...Which is clearly the most elegant solution so far. (Especially if your loop happens to insert elements.)
If Fred adds a Step, it won't be much worse than the current ForEach, but if he chooses a ForEachReverse command, it will be just as elegant as the current ForEach. (And likely easier to implement, but less flexible.)
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 7:53 pm
by BorisTheOld
Bisonte wrote:not necessary ....
While I agree the proposed feature is not necessary, it's certainly a lot clearer than your long solution.
I'm very much in favour of readable code, especially when the time comes for someone to maintain it many years from now.
We've set up many macros to remove the opacity from PB's commands. For example, which is more readable?
Code: Select all
DisableGadget(#Gadget, 0)
HideGadget(#Gadget, 0)
or
EnableButton(#Gadget)
ShowButton(#Gadget)
We currently use over 400 macros for supporting OOP, dynamic libraries, and readable code. These are all set up as custom keywords in the IDE.
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 8:04 pm
by Fred
You could also use constants to enhance a bit the readibility:
Code: Select all
DisableGadget(#Gadget, #False)
HideGadget(#Gadget, #False)
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 8:21 pm
by Little John
Fred wrote:You could also use constants to enhance a bit the readibility:
Code: Select all
DisableGadget(#Gadget, #False)
HideGadget(#Gadget, #False)
Absolutely.
And you can even use more meaningful names for the gadget constants, e.g.:
Code: Select all
DisableGadget(#ButtonOK, #False)
HideGadget(#ButtonCancel, #False)
I can't see any problem with readability here at all.
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 8:31 pm
by BorisTheOld
Fred wrote:You could also use constants to enhance a bit the readibility:
Code: Select all
DisableGadget(#Gadget, #False)
HideGadget(#Gadget, #False)
Yes, we thought about that, but decided it would still be confusing since the important information is at the end of the parameter list. When reading through a complex source listing, the eye tends to follow the commands, not scan every parameter looking for special situations.
An alternative might be to set up meaningful constants, such as:
Code: Select all
#HideGadget = 1
#ShowGadget = 0
#DisableGadget = 1
#EnableGadget = 0
DisableGadget(#Gadget, #EnableGadget)
HideGadget(#Gadget, #ShowGadget)
But we felt this was still a little like having to click on "Start" in order to stop Windows. We went with meaningful macro names so there was no confusion about the type of gadget being referenced.
Code: Select all
Macro ShowButton (GadgetNumber)
HideGadget(GadgetNumber, 0)
EndMacro
Macro ShowString (GadgetNumber)
HideGadget(GadgetNumber, 0)
EndMacro
etc
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Mon Jun 10, 2013 8:38 pm
by skywalk
I agree that my mind tends to support positive logic more readily.
And why so many characters to say 0 or 1?
I think it is universally understood what 0 means in these contexts.
Especially if you have a procedure with multiple boolean parameters to enter.

Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Tue Jun 11, 2013 5:44 am
by BorisTheOld
skywalk wrote:And why so many characters to say 0 or 1?
I think it is universally understood what 0 means in these contexts.
My intent is to simplify and clarify, not find a long way of specifying 0 or 1. In fact, my approach avoids having to specify the 0 or 1.
Hence, the statement:
actually uses fewer characters, and more clearly indicates what is being accomplished, than:
PB is a powerful language, but some of its command names don't work well in English. So we restructure some of the commands to make our code more readable and self documenting. We modify PB commands to use more traditional English word pairings, such as: add/delete, begin/end, start/stop, attach/detach, capture/release, create/destroy, etc.
For example, in PB, "ButtonGadget" creates a button, but "FreeGadget" deletes it. The problem here is that the word "Free" does not imply destruction. Something can be free but still exist. Also, does "FreeGadget" mean create a gadget of type "Free"? So, instead, we use the following constructs:
Code: Select all
CreateButton(#Gadget, .........)
DestroyButton(#Gadget)
All programming languages have quirky syntax. I've found that making a few changes, using macros, can simplify the coding process and make maintenance much easier in the future. I've also found that self-documenting commands obviate the need for additional comments to explain the code.
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Tue Jun 11, 2013 10:21 pm
by Tenaja
ShowButton(#Gadget)
I have made similar macros, especially when I first started using PB. The lack of F1-Help support has reduced that significantly in the past couple years though.
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Tue Jun 11, 2013 10:50 pm
by Neil
BorisTheOld wrote:
For example, in PB, "ButtonGadget" creates a button, but "FreeGadget" deletes it. The problem here is that the word "Free" does not imply destruction. Something can be free but still exist. Also, does "FreeGadget" mean create a gadget of type "Free"? So, instead, we use the following constructs:
Code: Select all
CreateButton(#Gadget, .........)
DestroyButton(#Gadget)
All programming languages have quirky syntax. I've found that making a few changes, using macros, can simplify the coding process and make maintenance much easier in the future. I've also found that self-documenting commands obviate the need for additional comments to explain the code.
Hi Boris,
Very interesting post (as usual !!).
I think I'll start adding some of these type of macros.
A particular command that took me ages to find was:
Code: Select all
DisableGadget(Button_Collect_Files,#True)
I was looking for something like:
Code: Select all
SetGadgetActive(Button_Collect_Files,#True)
The language I am usually using would have:
!This.Button_Collect_Files.Active = t or f
So I was looking for "Active" !!
So I guess now I can have:
Code: Select all
SetGadgetActive(Button_Collect_Files,[#True,#False])
or even (using your logic):
Code: Select all
SetGadgetActive(Button_Collect_Files)
SetGadgetInActive(Button_Collect_Files)
Re: ForEachReverse <-> ForEach with operating in reverse
Posted: Wed Jun 12, 2013 3:29 pm
by BorisTheOld
Neil wrote:Very interesting post (as usual !!).
Thanks - I'm glad you found it useful.
I'm an old mainframe Assembler programmer who very quickly learned the benefits of using macros to clarify code and increase coding efficiency -- all without adding CPU cycles to the code.
Here's a PB example. It's a macro for destroying a class instance, plus a couple of other general purpose macros.
Code: Select all
Macro DestroyObject (bvsObjectName)
If IsObject(bvsObjectName)
bvsObjectName = bvsObjectName\funDestroy()
EndIf
EndMacro
;
Macro IsObject (bvsDataParmName)
bvsDataParmName <> 0
EndMacro
;
Macro Me
*Self
EndMacro
;
;------ destroy an object in the current class
;
DestroyObject(Me\oObjectName)
;
;------ this is the expanded code that executes the object's "Destroy" method
;
If *Self\oObjectName <> 0
*Self\oObjectName = *Self\oObjectName\funDestroy()
EndIf
This is a simple example that shows how much coding can be saved and how much clearer the code is.
Judicious use of macros saves huge amounts of coding effort, simplifies the code, reduces the chance of making errors, and makes maintenance easier.
By the way, we use Polish notation in our code. So "oObjectName" refers to an object pointer named "ObjectName". And "funDestroy" refers to a function procedure named "Destroy". In our code, functions return a value, but subroutines don't.
In the above example, if the object is successfully destroyed then the object pointer is set to zero.