Arc Forumnew | comments | leaders | submitlogin
Reference parameters
4 points by xTERM 6169 days ago | 11 comments
Does Arc support reference parameters for functions? Coping all content of function parameters takes lots of time, especially if they are very big. And function cannot modify them. Can you make something like this to be possible: (def foo (x y z &very-big-database a b c &writable-parameter) (...)) ?


2 points by pg 6168 days ago | link

I'm not sure what reference parameters are, but I think it may already do what you hope. E.g. if you pass a hash table as an argument, the code in the called function can modify the original.

-----

3 points by ryantmulligan 6168 days ago | link

I think by reference parameters he means "by-reference argument passing."

Yes, this is what lisps do.

-----

4 points by nex3 6168 days ago | link

Lisps pass some objects (lists, hash tables) by reference, but others (integers, symbols) by value. In languages that offer it like C++, explicit pass-by-reference is useful because A) these languages don't deal with objects as references by default and B) to pass extra information to the caller of the function (e.g. having a boolean reference that's set to true if some condition is met).

However, A is a non-issue in Lisps and B is trivially solvable by returning a pair, so I don't see how pass-by-reference could be useful.

-----

2 points by rkts 6168 days ago | link

Consider deleting a node from a binary tree. You want a function that looks at a node and, if it's a match, unlinks it from its parent. Passing by reference allows you to do this cleanly. The alternative is to peek ahead at each subnode (messy) or to pass information up the call stack (inefficient, as the function can no longer be tail-recursive).

I'm not advocating C++ references, which I think are too implicit. If a function call foo(x) can change the value of x, there needs to be some visual indication of this. I'd prefer something like plain C pointers, with which you can pass the address of an object: foo(&x).

Of course an alternative is store objects wrapped in containers, and this isn't too bad a solution.

  (def ref (x) (obj contents x))
  (mac deref (x) `(,x 'contents))
But of course this is inefficient. If anything, this argues for adding arrays to Arc.

-----

1 point by EliAndrewC 6168 days ago | link

> However, A is a non-issue in Lisps and B is trivially solvable by returning a pair, so I don't see how pass-by-reference could be useful.

Is there an Arc equivalent to Common Lisp's multiple-value-bind macro? Because it's very awkward to have to say

    (let values (f x)
        (with (a (values 0)
               b (values 1))
            (whatever ....

-----

3 points by rkts 6167 days ago | link

Yes:

  (let (a b) (f x) ...)
although technically this is a destructuring-bind, not a multiple-value-bind.

-----

2 points by rkts 6168 days ago | link

A Lisp variable is implicitly a pointer to an object. Passing it to a function generates a copy of the pointer, which is pass-by-value. With pass-by-reference, the function would get a reference to the pointer. So e.g. reverse could be called for side effect: you could say (rev xs) instead of (= xs (rev xs)).

-----

2 points by Jekyll 6168 days ago | link

This behaviour is already standard in all lisps. Try: (with (a (list 1 2) b [ = (car _) 3]) (b a) a)

=>(3 2)

the list (1 2) is passed to function b, which modifies the car of the first cons cell, changing the original list.

-----

2 points by cadaver 6168 days ago | link

I'm new to lisp/scheme/arc so this may not be an issue in practice, but what if you want to add a new pair to the beginning of the list?

The only way to do this would be to insert a new pair after the first, then copy the car from the first to the second, then set the first car as desired.

Unfortunately this does not work if you have references to this first pair in particular, because of its car, rather than because it is the beginning of the list;

-----

1 point by cadaver 6167 days ago | link

Now that I think of it, passing parameters by reference would not be useful in this case.

Passing lists (pairs) by reference simply means creating a level of indirection to where the address of the first pair is stored. However, in a running program, there can be an arbitrary number of such locations.

I think that the problem of lists, of which the sort order is significant and which may be modified in arbitrary ways, can only be solved by, a) having a global binding, that is, a global level of indirection that everyone uses, or b) using a pair, of which the cdr remains unused, or some other reference-object as a level of indirection.

I suppose this is where arrays come in.

-----

1 point by Jekyll 6165 days ago | link

My example wasn't exactly orthodox lisp style. Normally, you should explicitly set any variables you are manipulating, so you'd be writing: (= a (f a)) rather than relying side effects to set it for you (This is especially important when calling functions like sort). It's such a common idiom that in common lisp I have a ! macro to turn (! f a . b) into (setf a (f a . b)).

-----