subscripts are.... objects?

6 views
Skip to first unread message

Yuval Kogman

unread,
Apr 12, 2005, 11:58:29 AM4/12/05
to perl6-l...@perl.org

We blitzed a discussion on #perl 3 minutes ago, reaching the
conclusion that negated subscripts are cool.

So i was thinking:

subscripts are objects.

They are sets, really.

You can perform set operations on them:

[!-2]

is the subscript for everything but the second to last element.

By using a context enforcer (subscript [] ?, maybe since lists are
lazyy they can just be subscripts when used that way?) you can get a
subscript object, which you can then use in a subscript, and it
flattens out.

The set math is done by special casing junctions, perhaps?


my @array;

@array[$subscript];
@array[$other];

@array[$subscript | $other]; # union
@array[$subscript & $other]; # intersection

@array[!-1]; # -1 but false? this means that it's masking

my $not_1 = [!-1];

@array[$subscript & $not_1]; # subscript without -1
@array[$subscript | $not_1]; # subscript with -1, since it's a union
# with the complement of just -1


I've found myself replicating sets like these for accessing data
many a time in perl 5.

Maybe if refined this can be useful?

--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &
/\ kung foo master: /me wields bonsai kittens: neeyah!!!!!!!!!!!!!!!!

Thomas Sandlaß

unread,
Apr 12, 2005, 12:32:05 PM4/12/05
to perl6-l...@perl.org
Yuval Kogman wrote:
> You can perform set operations on them:
>
> [!-2]

Hmm, that would produce a boolean index.


> is the subscript for everything but the second to last element.
>
> By using a context enforcer (subscript [] ?, maybe since lists are
> lazyy they can just be subscripts when used that way?) you can get a
> subscript object, which you can then use in a subscript, and it
> flattens out.
>
> The set math is done by special casing junctions, perhaps?

I'm not the junction expert, but it's said that they wrap around
indexing/slicing! So the @array[!-2] would just read @array[none(-2)]?
But how does none() get the base set where the second to last is excluded
from?


> my @array;
>
> @array[$subscript];
> @array[$other];
>
> @array[$subscript | $other]; # union

That is valid already.


> @array[$subscript & $other]; # intersection

This'll do autothreaded, indexed access with the outcome of the
all() junction.


Regards,
--
TSa (Thomas Sandlaß)

Rod Adams

unread,
Apr 12, 2005, 10:31:17 PM4/12/05
to perl6-l...@perl.org
Thomas Sandlaß wrote:

> Yuval Kogman wrote:
>
>> You can perform set operations on them:
>>
>> [!-2]
>
>
> Hmm, that would produce a boolean index.
>
>
>> is the subscript for everything but the second to last element.
>>
>> By using a context enforcer (subscript [] ?, maybe since lists are
>> lazyy they can just be subscripts when used that way?) you can get a
>> subscript object, which you can then use in a subscript, and it
>> flattens out.
>>
>> The set math is done by special casing junctions, perhaps?
>
>
> I'm not the junction expert, but it's said that they wrap around
> indexing/slicing! So the @array[!-2] would just read @array[none(-2)]?
> But how does none() get the base set where the second to last is excluded
> from?

It does no such thing. It creates a new none() junction over what was
stored at index -2. It's when you evaluate the new junction that the
none comes into effect.

And once again, I feel the need to remind people that junctions and sets
are two different things.

If I get to do what I'd like to to junctions, the above would actually
be illegal. But for that I have to wait for Damian to get back. Given
that when he left he said "I'll be away for the rest of the week", and
that was on Feb 22, one can be left to assume that Damian is suffering
from a very long week. Poor Damian. Sadly, my recent weeks have felt as
if they were 2 months long. <toast>Here's to a return of the 7 day
week!</toast>

-- Rod Adams

Thomas Sandlaß

unread,
Apr 13, 2005, 12:58:48 PM4/13/05
to perl6-l...@perl.org
Rod Adams wrote:

> Thomas Sandlaß wrote:
>> I'm not the junction expert, but it's said that they wrap around
>> indexing/slicing! So the @array[!-2] would just read @array[none(-2)]?
>> But how does none() get the base set where the second to last is excluded
>> from?
>
> It does no such thing. It creates a new none() junction over what was
> stored at index -2. It's when you evaluate the new junction that the
> none comes into effect.

Interesting, how does that differ from none(@array[-2])?


> And once again, I feel the need to remind people that junctions and sets
> are two different things.

I know. I've dubbed junction as "oracle value". But that somewhat restricts
them to advanced control flow as a generalized form of boolean conditionals.


> If I get to do what I'd like to to junctions, the above would actually
> be illegal. But for that I have to wait for Damian to get back.

Could we nonetheless start discussing our (mis)understandings? I for my
part have a big difficulty on forming a coherent model of typing and dispatch
on one side and the autothreading of junctions on the other side. In particular
why the compiler has to produce code that branches into completely different
implementations for junctions and non-junctions before the dispatcher sees
the types. Only when junctions are syntactically visible this code overlaying
can be optimized away. Consider the S09 example substr("camel", 0|1, 2&3) with
variables of unknown content instead of literals: substr("camel", $a, $b).
This would need to be compiled to something like:

if $a.does(Junction)
{
if $b.does(Junction)
{
autothread over $a and $b
}
else
{
autothread over $a
}
}
elsif $b.does(Junction)
{
autothread over $b
}
else
{
dispatch normally
}


This buries the type Junction deep inside the compiler, while types like
Array, Scalar or Ref have to go through the dispatcher. BTW, I neither like
it that this applies to the boolean type, too. But there it's just the usual
embedding into the int type---not code morphing in the large as in the
pseudocode above.


Coming back to the original subject of the thread, I think it could be achieved
by implementing &postcircumfix:<[ ]>:(Array,Exclusion:) and a function or
operator &exclude:(List returns Exclusion) that does nothing but re-typing its
slice input. E.g. @array[ exclude 1, 2, 3 ] is dispatched to a multi method that
knows the array and the fact that everything except the incoming slice shall be
returned.

Juerd

unread,
Apr 14, 2005, 1:29:43 PM4/14/05
to perl6-l...@perl.org
Larry Wall skribis 2005-04-14 10:11 (-0700):
> Interestingly, if .{} defaulted to smart matching, ordinary .{'foo'}
> would essentially fall out of the samantics of "find me all the keys
> that smartmatch "foo", which is only one of them, presuming a hash
> that guarantees uniqueness. One could view .{} as Perl's version of
> SQL's "select".

@foos = %hash{ /^foo_/ } ».value;

Wow. I love that.

%handles{IO::Socket}

Nice.

But the best thing about this is that it makes junctions more
meaningful:

%hash{'foo' | 'bar' | 'baz'}

I think meant

%hash<foo> | %hash<bar> | %hash<baz>

But indeed, SELECTing with ~~ is more useful:

%hash{ IO::Socket | IO::File | 'foo' }
%hash{ grep { %hash{$_}.does(IO::Socket|IO::File) || exists %hash{$_} }, %hash.keys }

So, what's the important downside of all this?


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Larry Wall

unread,
Apr 14, 2005, 1:11:30 PM4/14/05
to perl6-l...@perl.org
On Tue, Apr 12, 2005 at 06:58:29PM +0300, Yuval Kogman wrote:
:
: We blitzed a discussion on #perl 3 minutes ago, reaching the

: conclusion that negated subscripts are cool.
:
: So i was thinking:
:
: subscripts are objects.

I'm all in favor of powerful constructs, but we need to be *really*
careful not to compromise the visibility of ordinary integer
subscripting to the optimizer. At one time we proposed that a
subscript could be either an ordinary slice or any selector that
could be smartmatched against the available indexes, but lately we've
been leaning toward the idea that subscripts are simple slices of
integers, and there should probably be an explicit method syntax to
tell the compiler to pessimize calls to fancy selectors. As they say:
"Optimize for the common case." And the common case here is integer
subscripting, by far. That's basically all that distinguishes .[]
from .{}, after all (plus a bit of type checking).

Interestingly, if .{} defaulted to smart matching, ordinary .{'foo'}
would essentially fall out of the samantics of "find me all the keys
that smartmatch "foo", which is only one of them, presuming a hash
that guarantees uniqueness. One could view .{} as Perl's version of
SQL's "select".

It could be argued that the same optimizability concerns apply to
hashes as well as arrays, but hashes are already bound into a fairly
heavy set of semantics, so going to the most general semantics via
MMD might not actually cost us much. It might not cost us anything,
if general hash lookups have to go through MMD anyway.

Larry

Larry Wall

unread,
Apr 14, 2005, 1:42:16 PM4/14/05
to perl6-l...@perl.org
On Thu, Apr 14, 2005 at 07:29:43PM +0200, Juerd wrote:
: So, what's the important downside of all this?

The fact that smartmatching a list doesn't slice, but is defined to
be array equality with smartmatch of each element in order:

if @array ~~ (1,2,3,"many") { say "array can count" }

Larry

Reply all
Reply to author
Forward
0 new messages