Re: Pass by address

new topic     » goto parent     » topic index » view thread      » older message » newer message

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. smile

-- David Cuny

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu