lua-users home
lua-l archive

Re: Unpack Operator

[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 ... )

AltStyle によって変換されたページ (->オリジナル) /