[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Unpack Operator
- From: Sean Conner <sean@...>
- Date: Sun, 21 Jan 2018 18:32:11 -0500
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 ... )