Simulating call-by-reference with Dylan macros 
Author Message
 Simulating call-by-reference with Dylan macros


Quote:

>It seems to me that there are certain instances when "call-by-reference"
>is a handy feature that can make a program shorter and more elegant.  My
>question is this:  "Is there a way to simulate "call-by-reference" in
>Dylan?

  Why? "call by reference" seems to me a mechanism for doing one of two
  things.  

        i. to return multiple values from a functin/procedure

        ii. to perform a side-effect upon some object

  Dylan provides direct mechanism for doing i.  
  And since all variables are bound by reference in Dylan you can
  preform ii by simply passing the reference by value.

  In ii. I draw a distinction between preforming some side effect upon
  the object referred to by a variable and changing the binding of a
  variable.  

  If you wish to change a binding of a variable then you should use
  the setters explicitly instead of trying to hide it buried in some
  macro somewhere.  For example

Quote:
>  Syntax for normal Dylan parameter passing:
>      increment(a);

   would simply be

        a := increment(a) ;

   From the example code it is not the immutable object 1 which you wish
   to change. You wish to change the binding of a. So just change the binding
   of a.  

  if you have multiple bindings you wish to change then return those and
  rebind
        let ( a b c ) = foo ( a b c ) ;

Quote:
>Could this functionality be encapsulated using macros?

  You'd have to write a macro for defining these sorts of functions.
  Only they wouldn't be functions but macros... ugh...

  so something like:

        foo ( &a  &b .... ) ;

  expanded into something like

        begin
        let ( refarg0 refarg1 ... result ) = foo ( a b ... )
        a := refarg0 ;
        b := refarg1 ;
        result;
        end

  [ If the function returned no value then you wouldn't need the "result"
    variable above.]

  Which, like I said up above, is just suffling a bunch of varialbe rebindings
  under a macro.. I'm not sure you really need to intro C-like syntax to
  to this. I think it would tend to confuse those making the switch more
  the help.  

--
Lyman S. Taylor                 Scully: "I have a date."

                                Scully: "Unlike you, Mulder, I would
                                                like to have a life."
                                Mulder: "I have a life!"



Thu, 11 Mar 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros

Date :02:29:52 PM Wed 13 Nov 1996 GMT



Quote:


> >It seems to me that there are certain instances when "call-by-reference"
> >is a handy feature that can make a program shorter and more elegant.  My
> >question is this:  "Is there a way to simulate "call-by-reference" in
> >Dylan?

>   Why? "call by reference" seems to me a mechanism for doing one of two
>   things.

>    i. to return multiple values from a functin/procedure

>    ii. to perform a side-effect upon some object

>   Dylan provides direct mechanism for doing i.
>   And since all variables are bound by reference in Dylan you can
>   preform ii by simply passing the reference by value.

>   In ii. I draw a distinction between preforming some side effect upon
>   the object referred to by a variable and changing the binding of a
>   variable.

>   If you wish to change a binding of a variable then you should use
>   the setters explicitly instead of trying to hide it buried in some
>   macro somewhere.  For example

> >  Syntax for normal Dylan parameter passing:
> >         increment(a);

>    would simply be

>    a := increment(a) ;

>    From the example code it is not the immutable object 1 which you wish
>    to change. You wish to change the binding of a. So just change the
binding
>    of a.

Perhaps not, he may have many refereces to the same object, all of which
need to see the incremented object automatically.

Quote:
>   if you have multiple bindings you wish to change then return those and
>   rebind
>    let ( a b c ) = foo ( a b c ) ;

Which won't cover the above.  Isn't this were destructive functions (like
sort! as opposed to sort) are used in the DRM?
Peter somehow needs an increment! function.

As you say he can pass the reference by value, I don't know how to do this,
and neither perhaps, does he.  How do you do this?

Quote:
> >Could this functionality be encapsulated using macros?

>   You'd have to write a macro for defining these sorts of functions.
>   Only they wouldn't be functions but macros... ugh...

I agree, while it could be implemented with macros, its not nice, and a lot
of hard work each time you want to do something like that.

--
Sam Liddicott                  |   Nothing I say is to be attributed as
Campbell Scientific Ltd.       | a company statement or representation.
14-20 Field Street, Shepshed,  *----------------------------------------
Leicestershire, United Kingdom. LE12 9AL      Phone: +44 (0) 1509 601141



Sun, 02 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros

[stuff about increment/decrement functions and "pass by reference"]

Well, Dylan makes a sharp distinction between objects and variables, and I
think rightly so. Variables are bindings that simply provide names for
objects, but they themselves are not objects. In C, however, a variable is
an object in that you can take its address, refer to the memory it
occupies, alter it via a pointer, and I think this simply introduces
opportunities for trouble.

So far, the only argument (no pun intended) I've seen for "pass by
reference" is increment() and decrement(). I've only been programming in
Dylan full-time for a few weeks now, but I haven't needed this once, and
I've only seen one use of this in someone elses code. As a C/C++ veteran,
I'm fond of the concise ++ and -- operators, but I think the reason they
are used so much is that they are required for almost every use of
iteration. Dylan (IMHO) has a much more sensible (and less error prone) way
to express iteration (i.e. from/to/by/in).

I think you'll find either that "foo := increment(foo);" simply isn't used
frequently enough to be annoying, or that these functions are unique enough
that defining macros for them won't impact readability.

As for sharing objects, I think you'll find that any non-trivial object in
a program is either a collection or a user-defined class with slots, and
that the perceived need to share <integer> objects (for example) is
unfounded because you're generally better off defining a class with an
<integer> slot to represent the concept you're trying to express (e.g.
<velocity>, <mass>, <height>, <color>, <spiffyness>).

...........................................................................
Chris Page                                       define module usenet-post
Dylan Hacker                                       use dylan;
Harlequin, Inc.                                    use standard-disclaimer;
<http://www.best.com/~page/>                     end module usenet-post;



Tue, 04 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros


Quote:
>Peter somehow needs an increment! function.

>As you say he can pass the reference by value, I don't know how to do this,
>and neither perhaps, does he.  How do you do this?

define macro increment!
  { increment! ( ?place:expression ) } =>
     { let old = ?place; ?place = old + 1 }
  { increment! ( ?place:expression, ?amount:expression ) } =>
     { let old = ?place; ?place = old + ?increment }
end;

Not quite as good as INCF, but sufficient for most purposes.



Wed, 05 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros

Quote:

>So far, the only argument (no pun intended) I've seen for "pass by
>reference" is increment() and decrement().

How about things like Common Lisp's PUSH and POP?

Quote:
> I've only been programming in
>Dylan full-time for a few weeks now, but I haven't needed this once, and
>I've only seen one use of this in someone elses code. As a C/C++ veteran,
>I'm fond of the concise ++ and -- operators, but I think the reason they
>are used so much is that they are required for almost every use of
>iteration. Dylan (IMHO) has a much more sensible (and less error prone) way
>to express iteration (i.e. from/to/by/in).

Common Lisp also has nice (and many) iteration mechanisms, yet I've still
found plenty of use for INCF and DECF.  For instance, a program to generate
word frequencies in text might contain something like:

(incf (gethash word *freq-table*))

(Actually, this particular idiom works better in Perl, because it will
automatically create the hash table entry the first time, while in Lisp
it's necessary to check whether the entry exists, which would extract the
value in the process, so I would just store the new value rather than use
INCF.)
--
Barry Margolin
BBN Planet, Cambridge, MA

(BBN customers, please call (800) 632-7638 option 1 for support)



Wed, 05 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros



Quote:

...
>define macro increment!
...
>  { increment! ( ?place:expression, ?amount:expression ) } =>
>     { let old = ?place; ?place = old + ?increment }

                          ^^^^^^^^^^^^^^^^^^^^^^^^^ probably should be

                           ?place := old + ?amount
                                                    correct ?   :-)

Quote:
>end;
...

>Not quite as good as INCF, but sufficient for most purposes.

  I suppose that refers to the ?place expression being evaluated only once
  with INCF.   Doesn't seem to be a way around that one, since can't decompose
  expressions.

--

Lyman S. Taylor           "Computers are too reliable to replace

                                Commander Nathan Spring, "Starcops"



Thu, 06 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros


Quote:


>>So far, the only argument (no pun intended) I've seen for "pass by
>>reference" is increment() and decrement().

>How about things like Common Lisp's PUSH and POP?

  Yeah but this seems to be in the same sort of "code idiom". Short pieces
  of commonly reused code that is generally useful.  Hence implemented
  as a macro.  In general I really don't see "call by reference" as a
  substitute for macros... but I guess you could look at it that way
  if the language didn't have macros ( e.g. Ada). But for those that
  do, it would seem that macros were more apropriate.  Especially for this
  sorts of utilities: swap, increment, decrement, push , pop, etc.

  they're all max "three liners" and only add syntactic sugar to the code.

Quote:
>(incf (gethash word *freq-table*))

>(Actually, this particular idiom works better in Perl, because it will
>automatically create the hash table entry the first time, while in Lisp
>it's necessary to check whether the entry exists, which would extract the
>value in the process, so I would just store the new value rather than use
>INCF.)

  but isn't the above taken care of by

   (incf (gethash word *freq-table* 0 ))

    [ Effectively
                (let*  ( (var1 word )
                         (var2 *freq-table* )
                         (defaultvar 0 )
                         (var3 (+ (gethash var1 var2 defaultvar ) 1)))
                     (puthash  var1 var2 var3 ))

           puthash being whatever dumps values into hashtables.  ]

   Or in Dylan with increment! macro from a couple of posts ago.

        increment!( element(*freq-table*, word, default: 0 )) ;

   Hmmm, will ':=' throw away the default when this is transformed into
   and element-setter call or could/would  :=  transform this into
   some implementation specific magic.  i.e. is

    element( table , key , default: value ) := ....  ;

    illegal?  Looks like it.  since the transform should look like.

    element-setter ( .... , table , key ) ;

    or is the := to *-setter mapping suppose to be smart about throwing
    away optional arguments?

--

Lyman S. Taylor           "Computers are too reliable to replace

                                Commander Nathan Spring, "Starcops"



Thu, 06 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros



Quote:


>>How about things like Common Lisp's PUSH and POP?
>  they're all max "three liners" and only add syntactic sugar to the code.

The "three liner" versions of these macros probably may not deal with side
effects and order of evaluation properly.  Call by reference doesn't have
those problems (although it may have problems with aliasing).
--
Barry Margolin
BBN Planet, Cambridge, MA

(BBN customers, please call (800) 632-7638 option 1 for support)


Thu, 06 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros


...

Quote:

>The "three liner" versions of these macros probably may not deal with side
>effects and order of evaluation properly.

  Yeah, but the "meat" of the macro is only "three lines". The rest is
  dodging these problems. :-)

Quote:
>  Call by reference doesn't have
>those problems (although it may have problems with aliasing).

  Not necessarily. If the language were to allow a computable lvalue it
  would matter.  I  can't think of any language that allows call by reference
  in which the reference can't be statically determined in the context.

  For example in Dylan

        some-function(  object.slot1  ,element( key, find-table() ) ,... );

  if call by reference were added then the lvalue of object.slot would
  have to passed along.  Or some "thunk" like item which could provide access
  to the slot1 getter and setter as needed.  

  But what about that second expression. It is legal to use as an lvalue
  in the language. Would find-table be evaluated once by the magic "thunk"
  or just once?

  More problematical now is that you're on a slippery slope. Which expressions
  are now lvalues and which ones aren't.... although I guess that has to be
  checked at some point for ":=" processing too.

--

Lyman S. Taylor           "Computers are too reliable to replace

                                Commander Nathan Spring, "Starcops"



Thu, 06 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros


Quote:

>Common Lisp also has nice (and many) iteration mechanisms, yet I've still
>found plenty of use for INCF and DECF.  For instance, a program to generate
>word frequencies in text might contain something like:

>(incf (gethash word *freq-table*))

>(Actually, this particular idiom works better in Perl, because it will
>automatically create the hash table entry the first time, while in Lisp
>it's necessary to check whether the entry exists, which would extract the
>value in the process, so I would just store the new value rather than use
>INCF.)
>--

But you could use

 (incf (gethash word *freq-table* 0))

"automatic" creation like in Perl, but with the option to use any default
you might want.

cheers, Bernhard

--
-----------------------------------------------------------------------------
Bernhard Pfahringer



Fri, 07 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros


Quote:


>...
>>define macro increment!
>...
>>  { increment! ( ?place:expression, ?amount:expression ) } =>
>>     { let old = ?place; ?place = old + ?increment }
>                      ^^^^^^^^^^^^^^^^^^^^^^^^^ probably should be

>                       ?place := old + ?amount
>                                                correct ?   :-)

Yes.  Probably still not correct, as I did not compile my code -- but you
get the idea.

Quote:
>>end;
>...

>>Not quite as good as INCF, but sufficient for most purposes.

>  I suppose that refers to the ?place expression being evaluated only once
>  with INCF.   Doesn't seem to be a way around that one, since can't decompose
>  expressions.

Yes.  Lisp's DEFSETF, etc. system allows you to specify arbitrary mappings
from rvalue to lvalue and to avoid multiple evaluations of the subforms of
the rvalue.  Dylan's simple mapping from foo to foo-setter is not as
precise or flexible.


Fri, 07 May 1999 03:00:00 GMT  
 Simulating call-by-reference with Dylan macros

    Date: Sat, 16 Nov 1996 23:08 EST


    >So far, the only argument (no pun intended) I've seen for "pass by
    >reference" is increment() and decrement().

    How about things like Common Lisp's PUSH and POP?

    > I've only been programming in
    >Dylan full-time for a few weeks now, but I haven't needed this once, and
    >I've only seen one use of this in someone elses code. As a C/C++ veteran,
    >I'm fond of the concise ++ and -- operators, but I think the reason they
    >are used so much is that they are required for almost every use of
    >iteration. Dylan (IMHO) has a much more sensible (and less error prone) way
    >to express iteration (i.e. from/to/by/in).

    Common Lisp also has nice (and many) iteration mechanisms, yet I've still
    found plenty of use for INCF and DECF.  For instance, a program to generate
    word frequencies in text might contain something like:

    (incf (gethash word *freq-table*))

    (Actually, this particular idiom works better in Perl, because it will
    automatically create the hash table entry the first time, while in Lisp
    it's necessary to check whether the entry exists, which would extract the
    value in the process, so I would just store the new value rather than use
    INCF.)

Bite your tongue Barry.  It works just fine if you specify a default
value in the call to GETHASH:

      (setq foo (make-hash-table))
    #<Table :TEST EQL 0/120 401052347>

      (incf (gethash 'bar foo 0))
    1

      (gethash 'bar foo)
    1
    T



Fri, 07 May 1999 03:00:00 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. Simulating call-by-reference with Dylan macros

2. Simulating call-by-reference in Ruby

3. Call by reference in Dylan

4. Simulating multi-dim array problem - OR - reference confusions

5. IV Called by reference doesn't open when called

6. are dylan macros Turing-complete?

7. C++ Templates used like Dylan Macros

8. C++ Templates used like Dylan Macros

9. Simple Reader Macros for Dylan

10. Simple Reader Macros for Dylan

11. dylan parser: Macros

12. Dylan program structure and macro parsing

 

 
Powered by phpBB® Forum Software