Re: Pass by address
- Posted by David Cuny <dcuny at LANSET.COM> Aug 17, 2000
- 531 views
Andy Cranston wrote: > "The problem is that a function can take multiple > arguments but can only return one value?" There's also a problem if you want to alter a parameter of something you passed to a routine. For example, let's say that I have a 'window' object that I want to position in the center of the screen: window[x] = (screen[width]/2) - (window[width]/2) window[y] = (screen[height]/2) - (window[height]/2) All fine and good, now you want to clean up your code by putting it in a routine: procedure center_window( sequence w ) w[x] = (screen[width]/2) - (w[width]/2) w[y] = (screen[height]/2) - (w[height]/2) end procedure The problem with this is that a *copy* of the window is centered. If you want to center the window, you have to write a function: function center_window( sequence w ) w[x] = (screen[width]/2) - (w[width]/2) w[y] = (screen[height]/2) - (w[height]/2) return w end function and then call it like this: window = center_window( window ) I'm cringing just writing that code. *bleah* After coding in C, QBasic and Java, this just feels unnatural. When you pass an object (in the class sense, not the Euphoria data type sense), you *typically* want operations on that object, not on a copy of the object. That's why languages like Java pass all complex data types as pointers by default. (Well, that and it's computationally much cheaper to pass a pointer than to clone an object.) If you want a copy of an object in one of those languages, you have to explicitly ask for one. But passing by reference isn't all blue skies and oysters. The problem with this sort of thing is you have to remember if you are dealing with a real object, a pointer, a clone... Soon you get into writing C-style code: &foo = *bar++; One solution would be to emulate pointers with a large sequence, and pass indexes. For example, in most of my OOP libraries, I define a global sequence called 'the' or 'my'. The center_window routine would look like this: procedure center_window( integer window ) my[window][x] = (screen[width]/2) - (my[window][width]/2) my[window][y] = (screen[height]/2) - (my[window][height]/2) end procedure This results in a lot more typing, and because of the extra index, the code is slower. So I'd actually code is as: procedure center_window( integer window ) sequence w w = my[window] w[x] = (screen[width]/2) - (w[width]/2) w[y] = (screen[height]/2) - (w[height]/2) my[window] = w end procedure which is truely horrible code. This kind of stuff is no fun to code, and it looks ugly! Rather than pass by reference, Euphoria allow a sort of dot notation. Most of the time, you're only passing one object to be altered. So: a.bar( b, c ) would be shorthand for: a = bar( a, b, c ) if bar was a function, and shorthand for: bar( a, b, c ) if bar was a procedure. That way, you could write: window.center_window() and it would behave *properly*, as if it were a reference, without actually introducing reference passing to the language. No special keywords, no question about if a variable is a value or a reference. The syntax is natural: myWindow.make_visible() myPoint.add_point( 12, 32 ) myAccount.debit( 5000.00 ) myShape.draw() It looks like it's OOP, but it's not. It's just syntactic sugar. I've actually written up a pre-processor that implements this notation and posted it some time back. I recoded a large chunk of my code using it, and I was able to write things like this: foo.plus( 12 ) long before Robert introduced the += construct to Euphoria. And the code looked great (and was less filling). I think it's a fine solution to passing by reference, but of course I'm biased. -- David Cuny