Re: Routine_ID Is No Doubt My Solution...
- Posted by Derek Parnell <ddparnell at bigpond.com> Apr 16, 2003
- 459 views
On Wed, 16 Apr 2003 00:10:00 -0300, <rforno at tutopia.com> wrote: [snip] >> >> > and I'd prefer passing all parameters as >> > references, excepting constants and expressions. >> >> Now I can see why you want better tracing and debugging features - you > need >> them when passing by reference. Too many opportunitites for things to >> get >> 'accidently' updated. > But Derek, now I'm not passing variables a references (not possible in > current Euphoria), and I still think I need better tracing (this is so > because I am not doing commercial programming, some special kind of CPU > intensive programs). > Moreover, now you have > a = foo(b, c) and of course have 'a' updated. > Is it so big the difference with: > foo(a, b) where you can have 'a' and 'b' updated? >> The difference is that, using the current Euphoria functionality, the code reader (and thus the interpreter) can at this very point know if 'a' is being updated or not. When using pass-by-reference (PBR) the reader is *never* sure if the parameters being passed will also be updated, unless they also examine the code in the routine being called. By being sure at the time of the routine call, the interpreter can make some optimisations, and the code reader can focus on the immediately visible code rather than track any *potential* updating code that is not necessarily next to the code being read. A further complication occurs with sequences. Currently we always know that the whole sequence is being replaced by a new one, but with a PBR scheme, we are never sure which elements may or may not be being updated by the called routine. This just adds uncertainty, which needs to have extra effort to resolve when inspecting code. So in summary, there is nothing intrinsically wrong with PBR, its just that it increases the degree of difficulty in reading the code and increases the probability of mistakes being made. This is exactly the same effect with using GOTO. So my rule-of-thumb is that both PBR and GOTO should only be used if its the only way to gain the **NECESSARY** performance improvement for a specific algorithm or piece of code. The costs of maintaining code that uses these two techniques is larger than not using them, so this needs to be taken into consideration. We need to take a look at what problems the PBR technique is trying to solve. One of the main reasons for using PBR is to avoid the overheads of passing large 'stuctures' to routines and receiving large structures back again. So, an early recommendation for Euphoria was to introduce a simpler syntax for multiple return values. Something along the lines of ... $(a, b) = foo(a,b) or $(s[Name], s[Telephone]) = UpdateCust(s) and the special circumstance that current takes the form "x = func(x)" could be replaced by ... func( $x ) Another common use for PBR is in situation where the routine called only knows at runtime (rather than at the time the code was written) if the parameter needs updating or not, or which elements of a structure might need updating. Currently we usually perform the tests for updating outside of the called routine. if length(s[Addr]) = 0 then s[Addr] = NewAddress() else s[MailAddr] = NewAddress() end if But in the interests of putting all the 'smarts' in one place, this test would be better placed inside the routine. function NewAddress(sequence s) . . . if length(s[Addr] = 0 then return {newaddr, s[MailAddr]} else return {s[Addr], newaddr} end if end function $(s[Addr], s[MailAddr]) = NewAddress(s) And another PBR usage occurs when there are common data items shared by many routines, such as Stack or List structures. function Push(s, newitem) s = append(s, newitem) return s end function function Pop(s) object item if length(s) > 0 then item = s[length(s)] s = s[1..length(s)-1] return {item, s} else abend("Stack Empty") end if end function Currently we code like this... ParameterStack = Push(ParameterStack, item) OperationStack = Push(OperationStack, op) x = Pop(ParameterStack) item = x[1] ParameterStack = x[2] But with a syntax change we can get... Push($ParameterStack, item) Push($OperationStack, op) Pop($item, $ParameterStack) With this syntax idea, we emulate PBR and still tell the reader exactly what we are doing. Note that PBR is not actually happening, its just that we are using a coding shorthand to assign returned sequence elements to multiple items UPON return. -- cheers, Derek Parnell