[net.lang] Multiple assignments long, but some is code

chris@umcp-cs.UUCP (Chris Torek) (05/23/86)

In article <1482@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes:
>In article <825@bentley.UUCP> kwh@bentley.UUCP writes:
>>In article <1455@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes:
>>>... Supposing that "$" is being used for this ["multi-assignment"] operator,
>>>then to set both "a" and "b" to zero, one would write "a $ b = 0", rather
>>>than "a = b = 0", as C does....  
>>
>>What do you mean by this?  I don't see how this operator allows you to do
>>anything that simple assignment doesn't.  Examples?
>
>Well, in C it doesn't, since C supports call by value only.

True but misleading: one gets the effect of call-by-reference by
passing the value of the address of a variable.  The called routine
then determines whether the effect is more like call- by-reference
or like value-result.  *I* think this is the `right' way to do it;
I dislike the `Pascal effect':

	{ near the top of a ~20000 line program: }
	procedure gorf(var p : TablePtr); ...

	{ many pages of code later: }
		tp := p1;
		gorf(tp);
		tp := p1;	{ why is this here? }

That is, there is no way to tell at the point of call that a given
procedure or function may modify one or more of its arguments.  In
C this is immediately obvious:

		tp = p1;
		gorf(&tp);
		tp = p1;	/* since gorf could clobber tp */

Anyway, back to the main issue:

>With a "$" operator [and call-by-reference], one could then write
>something like "getlin(fp, buff, buflen, actlen$lenread);";
>without it, one must use a separate assignment.

True.  I have never used a language that will do something like this.
I am curious about how such a language would treat aliasing problems.
Suppose I have the following (beware, random source language mix):

	procedure ugly options(main);
	type ty = array [1..3] of integer;
	var i, w, z : ty;

		procedure tricky(in out a, b : ty);
		begin	a[i[1]] := 3;
			i[1] := 2;
			b[2] := a[i[1]] + 2
		end;

	begin	i[1] := 1;
		tricky(w $ i, i $ z)
	end.

Now if the language is implemented using call-by-reference with a
`hidden' assignment afterwards, it behaves differently than if it
is implemented using `thunks' and call-by-name (which is the method
that sprang to my mind upon seeing the original example).

I think the aliasing problems are bad enough when all aliasing is
explicit, as in C (I have to take an address of a non-heap variable,
or copy a pointer variable, to create an alias).  However, the
ability to create aliases is useful, and I think the Pascal method
of keeping non-heap variables `pure' (but watch those call-by-references!)
is too limiting:

	/*
	 * Build a linked list such that the first thing entered
	 * into it is also at the head of the list.
	 */
	struct list *
	buildlist()
	{
		register struct list *p, **np;
		struct list *top;
		extern struct list *getitem();

		np = &top;
		while ((p = getitem()) != NULL) {
			*np = p;
			np = &(*np)->next;
		}
		*np = NULL;
		return (top);
	}

This routine is more complex if one is unable to alter `top' in
this way:

	function buildlist : listptr;
	var head, cur, p : listptr;
	begin	head := nil;
		p := getitem;
		while p <> nil do begin
			if head <> nil then cur^.next := p else head := p;
			cur := p;
			p := getitem
		end;
		if head <> nil then cur^.next := nil;
		buildlist := head
	end;

Even ignoring the extra `getitem', the two `if' tests are ugly.
But I have digressed again.  I think I should vote against a
`multiple assignment' operator, given a choice.  It seems to me to
add only a bit of functionality at the cost of a lot of complexity.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu