lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Paige DePol once stated:
> With all the talk in another thread about tables vs arrays the need for
> unpacking was also mentioned. As many of you know I am working on a hard
> fork of Lua which adds a new data type, the Index, which is essentially
> an array of Lua types with a max size of 255. Support for directly using
> an Index was also added to VM instructions, which was extended to 64-bit.
> 
> I am using this Index data type to implement a number of systems, including
> structures, anonymous tuples, encapsulation of object and class variables,
> variable function arguments, namespaces, and also providing access to fast
> arrays of random Lua types (but limited in size).
> 
> With new data types we still need to unpack the structures, however, using
> table.unpack won't work as an Index is not a Table. Nor would an Array or a
> Hash be a Table should they be separated into distinct data types. To allow
> unpacking of a variety of data types I was thinking of adding an "unpack"
> operator, much as it seems Python has.
> 
> In Python the "*" operator unpacks only the values of the supplied variable,
> where "**" unpacks both the keys and values of the variable. I was thinking
> of adding such an operator to my Lua fork so that all supported variables
> can be unpacked. I am trying to decide on the appropriate symbol to use and
> was thinking "$" and "$$" as the "$" sigil is not currently used in Lua, and
> the "$" looks like an "S", so "unpack to $tack" could be the mnemonic.
> 
> For example, I also plan to make "..." be directly usable via syntax instead
> of creating a table first. Instead, my vargs will use the Index data type,
> which itself will use a managed memory pool for speed.
> 
> This means that "#..." and "...[1]" and "$..." would work for length of the
> vargs, getting varg #1, and unpacking all vargs. I suppose adding syntax for
> array slices may also be useful for unpacking only some vargs, so "$...[2:4]"
> could unpack only vargs 2, 3, and 4, for example. For unpacking a table the
> "$" or "$$" operator could also take key names as in "$tbl{one,two,three}"
> to only unpack the specified key names.
> 
> From a coding standpoint I can see the benefit of declaring a variable as
> being only an array, or only a hash. From a compiler standpoint it could
> also help for generating more optimised code... especially if, as the Ravi
> author mentioned, the variable type for the entire array will be the same!
> 
> I just thought I would see what everyone thought of an "unpack" operator
> since this discussion of tables vs arrays reminded me about my plans to
> implement such an operator in the near future.

  Over a decade ago, I was perusing a book on the VAX architecture when I
came across two instructions, CALLS and CALLG.  To use CALLS, you first push
data onto the stack, then the number of arguments, then issue the CALLS:

			PUSHL	#84
			PUSHL	#600
			CALLS	#2,foo

  CALLG is slightly different.  There, you declare an array and the size of
the array:

	fooargs		.LONG	2
			.LONG	600
			.LONG	84

and then issue the instruction:

			CALLG	fooargs,foo

  The subroutine foo() doesn't care how it was called, as it's given a
pointer to the argument list in a set register (R12, aka AP).  It would be
cliche to say I had an epiphany, but I had an epiphany.  Arguments on the
stack is an ad-hoc array.

  There is no particular need for an unpack() function if you implement the
langauge just right.  The issue is distinguishing between a CALLS and a
CALLG type situation:

		CALLS:	foo(1,2,3,4)
		CALLG:	a = [1,2,3,4] foo ??? a ???

(question marks because I don't know how to designate what type of call I
want in an untyped language)

  Related (tangent alert)---a structure (struct in C, record in Pascal) is
nothing more than an array with possibly unequal sized items:

	#include <stdio.h>
	
	struct { int a; int b; int c; } foo;
	int bar[3];
	
	int main(void)
	{
	  printf("struct: %zu array: %zu\n",sizeof(foo),sizeof(bar));
	  return 0;
	}

	struct: 12 array: 12

  Now, take a look at this function:

	int XDrawLine(
		Display  *display,
		Drawable  d,
		GC        gc,
		int       x1,
		int       y1,
		int       x2,
		int       y2,
	) { ... }

and now this:

	struct xdrawline {
		Display  *display,
		Drawable  d,
		GC        gc,
		int       x1,
		int       y1;
		int       x2;
		int       y2;
	};

  Now imagine some hypothetical version of C that supports both the CALLS
and CALLG type function calls.  You can still do things the old fasioned
way:

	XDrawLine(dsp,win,ctx,x,y,x+34,y+17);

But also (because C has some typing, a compiler can take care of the details
here):

	struct xdrawline param = { dsp , win , ctx , x , y , x + 34 , y + 17 };
	XDrawLine(param);

and because C99 now allows both designated initialization *and* immediate
structures in function calls:

	XDrawLine((struct xdrawline) {
		.x1      = x,
		.y1      = y,
		.x2      = x + 34,
		.y2      = y + 17,
		.gc      = ctx,
		.display = dsp,
		.d       = win
	});

  Look at that---named parameters in a function call!

  Now, I'm not saying your langauge has to unify arrays, structures and
function parameters, but it could lead to some interesting features.

  -spc (It looks like you've already unified several types already ... )