## digitalmars.D - What's the deal with __buck?

• Andrei Alexandrescu (30/30) Jan 28 2009 I stumbled upon a very interesting problem. Consider an infinite range
• Bill Baxter (18/46) Jan 28 2009 You need to give your DollarType an int and some arithmetic operators
• Bill Baxter (9/61) Jan 28 2009 Nevermind, it just sunk in what you meant.
• BCS (2/8) Jan 28 2009
• Andrei Alexandrescu (14/20) Jan 29 2009 Ok, thanks to all. So __dollar is looked up at module scope for anything
• Jarrett Billingsley (5/24) Jan 29 2009 Sounds good. Question - since length will work for multiple indices,
• Don (2/29) Jan 29 2009 You can do that with opIndex already.
• Bill Baxter (4/40) Jan 29 2009 Can you? How? As far as I know any index expression with more than
• Don (3/36) Jan 29 2009 Aargh, you're right. I remembered that I'd got it to generate an AST for...
• Andrei Alexandrescu (5/32) Jan 29 2009 That's rather exotic. After that the road is opened for free-form
• Bill Baxter (5/13) Jan 29 2009 Multi-dim slicing is bread and butter for array math packages like
• Jarrett Billingsley (15/20) Jan 29 2009 Hm.. if you _wanted_ to interleave slices and single indices, how
• Don (11/34) Jan 30 2009 That's exactly what I did in Blade. opSlice() is a dead end.
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```I stumbled upon a very interesting problem. Consider an infinite range
that generates the numbers 1, 2, 3, ...

That range doesn't have a "length" member. However, it is a random
access range, which makes things rather interesting. Now consider I want
to advance 10 steps in that range. Being an obedient D programmer I'd write:

auto r = iota(1);
// skip 10 steps
r = r[10 .. \$];

Now this is very cool. If a range is infinite, I can use the \$ symbol in
the right position, but nothing else. So I tried to effect that and got
the following to compile:

struct DollarType {}
enum DollarType __dollar = DollarType();

struct S
{
void opSlice(uint, DollarType)
{
}
}

void main()
{
S s;
s[0 .. \$];
}

This is cool because it allows detection of passing \$. Now the problem
is, I can't seem to get rid of the __dollar definition! Has anyone found
a general-enough trick? I'd want a[...\$...] to morph the \$ into a.length
*iff* a defines length, and go with the __dollar otherwise.

Thanks,

Andrei
```
Jan 28 2009
Bill Baxter <wbaxter gmail.com> writes:
```On Thu, Jan 29, 2009 at 1:37 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
I stumbled upon a very interesting problem. Consider an infinite range that
generates the numbers 1, 2, 3, ...

That range doesn't have a "length" member. However, it is a random access
range, which makes things rather interesting. Now consider I want to advance
10 steps in that range. Being an obedient D programmer I'd write:

auto r = iota(1);
// skip 10 steps
r = r[10 .. \$];

Now this is very cool. If a range is infinite, I can use the \$ symbol in the
right position, but nothing else. So I tried to effect that and got the
following to compile:

struct DollarType {}
enum DollarType __dollar = DollarType();

struct S
{
void opSlice(uint, DollarType)
{
}
}

void main()
{
S s;
s[0 .. \$];
}

This is cool because it allows detection of passing \$. Now the problem is, I
can't seem to get rid of the __dollar definition! Has anyone found a
general-enough trick? I'd want a[...\$...] to morph the \$ into a.length *iff*
a defines length, and go with the __dollar otherwise.

You need to give your DollarType an int and some arithmetic operators
and have it represent an /offset/ from the end rather than signifying
the end itself.
Otherwise  a[\$-1] can't work.

Once you do that, then you can do things like
struct S
{
T opSlice(uint a,  DollarType b) {
return opSlice(a, length+b.offset);
}
T opSlice(uint a, uint b) {
....
}
...
}

--bb
```
Jan 28 2009
Bill Baxter <wbaxter gmail.com> writes:
```On Thu, Jan 29, 2009 at 1:48 PM, Bill Baxter <wbaxter gmail.com> wrote:
On Thu, Jan 29, 2009 at 1:37 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
I stumbled upon a very interesting problem. Consider an infinite range that
generates the numbers 1, 2, 3, ...

That range doesn't have a "length" member. However, it is a random access
range, which makes things rather interesting. Now consider I want to advance
10 steps in that range. Being an obedient D programmer I'd write:

auto r = iota(1);
// skip 10 steps
r = r[10 .. \$];

Now this is very cool. If a range is infinite, I can use the \$ symbol in the
right position, but nothing else. So I tried to effect that and got the
following to compile:

struct DollarType {}
enum DollarType __dollar = DollarType();

struct S
{
void opSlice(uint, DollarType)
{
}
}

void main()
{
S s;
s[0 .. \$];
}

This is cool because it allows detection of passing \$. Now the problem is, I
can't seem to get rid of the __dollar definition! Has anyone found a
general-enough trick? I'd want a[...\$...] to morph the \$ into a.length *iff*
a defines length, and go with the __dollar otherwise.

You need to give your DollarType an int and some arithmetic operators
and have it represent an /offset/ from the end rather than signifying
the end itself.
Otherwise  a[\$-1] can't work.

Once you do that, then you can do things like
struct S
{
T opSlice(uint a,  DollarType b) {
return opSlice(a, length+b.offset);
}
T opSlice(uint a, uint b) {
....
}
...
}

Nevermind, it just sunk in what you meant.
I think it's only a problem when you want to have some things in a
module with special __dollar and some with not?

Or I suppose you're probably trying to make template things which may
or may not be infinite?

I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

--bb
```
Jan 28 2009
BCS <none anon.com> writes:
```Hello Bill,

I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

I think that is the correct solution.

--bb

```
Jan 28 2009
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```BCS wrote:
Hello Bill,
I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

I think that is the correct solution.

Ok, thanks to all. So __dollar is looked up at module scope for anything
that's not a built-in array.

I thought some more about it and I think there's no need for __dollar.
It's enough that:

a) In slice expressions and index expressions with one argument, \$
expands to value.length, where value is the object being indexed/sliced
(if an unnamed temporary, the value is of course only evaluated once)

b) In index expressions with multiple arguments, \$ expand to
value.length(i), where i is the zero-based argument position.

This is exactly enough what's needed to make it all work. Infinite
ranges may define a symbolic infinite length and overload slicing on it.

Andrei

Andrei
```
Jan 29 2009
Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
```On Thu, Jan 29, 2009 at 12:48 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
BCS wrote:
Hello Bill,
I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

I think that is the correct solution.

Ok, thanks to all. So __dollar is looked up at module scope for anything
that's not a built-in array.

I thought some more about it and I think there's no need for __dollar.
It's enough that:

a) In slice expressions and index expressions with one argument, \$ expands
to value.length, where value is the object being indexed/sliced (if an
unnamed temporary, the value is of course only evaluated once)

b) In index expressions with multiple arguments, \$ expand to
value.length(i), where i is the zero-based argument position.

This is exactly enough what's needed to make it all work. Infinite
ranges may define a symbolic infinite length and overload slicing on it.

Sounds good.  Question - since length will work for multiple indices,
will it ever be possible to have .. multiple slices?

a[x1 .. x2, y1 .. y2] = b;
```
Jan 29 2009
Don <nospam nospam.com> writes:
```Jarrett Billingsley wrote:
On Thu, Jan 29, 2009 at 12:48 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
BCS wrote:
Hello Bill,
I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

I think that is the correct solution.

Ok, thanks to all. So __dollar is looked up at module scope for anything
that's not a built-in array.

I thought some more about it and I think there's no need for __dollar.
It's enough that:

a) In slice expressions and index expressions with one argument, \$ expands
to value.length, where value is the object being indexed/sliced (if an
unnamed temporary, the value is of course only evaluated once)

b) In index expressions with multiple arguments, \$ expand to
value.length(i), where i is the zero-based argument position.

This is exactly enough what's needed to make it all work. Infinite
ranges may define a symbolic infinite length and overload slicing on it.

Sounds good.  Question - since length will work for multiple indices,
will it ever be possible to have .. multiple slices?

a[x1 .. x2, y1 .. y2] = b;

You can do that with opIndex already.
```
Jan 29 2009
Bill Baxter <wbaxter gmail.com> writes:
```On Fri, Jan 30, 2009 at 5:58 AM, Don <nospam nospam.com> wrote:
Jarrett Billingsley wrote:
On Thu, Jan 29, 2009 at 12:48 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
BCS wrote:
Hello Bill,
I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

I think that is the correct solution.

Ok, thanks to all. So __dollar is looked up at module scope for anything
that's not a built-in array.

I thought some more about it and I think there's no need for __dollar.
It's enough that:

a) In slice expressions and index expressions with one argument, \$
expands
to value.length, where value is the object being indexed/sliced (if an
unnamed temporary, the value is of course only evaluated once)

b) In index expressions with multiple arguments, \$ expand to
value.length(i), where i is the zero-based argument position.

This is exactly enough what's needed to make it all work. Infinite
ranges may define a symbolic infinite length and overload slicing on it.

Sounds good.  Question - since length will work for multiple indices,
will it ever be possible to have .. multiple slices?

a[x1 .. x2, y1 .. y2] = b;

You can do that with opIndex already.

Can you?  How?  As far as I know any index expression with more than
one  ..  in it automatically generates a compiler error.

--bb
```
Jan 29 2009
Don <nospam nospam.com> writes:
```Bill Baxter wrote:
On Fri, Jan 30, 2009 at 5:58 AM, Don <nospam nospam.com> wrote:
Jarrett Billingsley wrote:
On Thu, Jan 29, 2009 at 12:48 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
BCS wrote:
Hello Bill,
I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

I think that is the correct solution.

Ok, thanks to all. So __dollar is looked up at module scope for anything
that's not a built-in array.

I thought some more about it and I think there's no need for __dollar.
It's enough that:

a) In slice expressions and index expressions with one argument, \$
expands
to value.length, where value is the object being indexed/sliced (if an
unnamed temporary, the value is of course only evaluated once)

b) In index expressions with multiple arguments, \$ expand to
value.length(i), where i is the zero-based argument position.

This is exactly enough what's needed to make it all work. Infinite
ranges may define a symbolic infinite length and overload slicing on it.

Sounds good.  Question - since length will work for multiple indices,
will it ever be possible to have .. multiple slices?

a[x1 .. x2, y1 .. y2] = b;

You can do that with opIndex already.

Can you?  How?  As far as I know any index expression with more than
one  ..  in it automatically generates a compiler error.

Aargh, you're right. I remembered that I'd got it to generate an AST for
me, but I forgot that I had put in a hack for ..
```
Jan 29 2009
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```Jarrett Billingsley wrote:
On Thu, Jan 29, 2009 at 12:48 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
BCS wrote:
Hello Bill,
I guess what's required is the ability to define the __dollar in the
scope of a class/struct/template.

I think that is the correct solution.

Ok, thanks to all. So __dollar is looked up at module scope for anything
that's not a built-in array.

I thought some more about it and I think there's no need for __dollar.
It's enough that:

a) In slice expressions and index expressions with one argument, \$ expands
to value.length, where value is the object being indexed/sliced (if an
unnamed temporary, the value is of course only evaluated once)

b) In index expressions with multiple arguments, \$ expand to
value.length(i), where i is the zero-based argument position.

This is exactly enough what's needed to make it all work. Infinite
ranges may define a symbolic infinite length and overload slicing on it.

Sounds good.  Question - since length will work for multiple indices,
will it ever be possible to have .. multiple slices?

a[x1 .. x2, y1 .. y2] = b;

combinations of a .. b and a. But I can definitely see some good uses
for it.

Andrei
```
Jan 29 2009
Bill Baxter <wbaxter gmail.com> writes:
```On Fri, Jan 30, 2009 at 8:00 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
Jarrett Billingsley wrote:

Sounds good.  Question - since length will work for multiple indices,
will it ever be possible to have .. multiple slices?

a[x1 .. x2, y1 .. y2] = b;

combinations of a .. b and a. But I can definitely see some good uses for
it.

Multi-dim slicing is bread and butter for array math packages like
Matlab or NumPy.

--bb
```
Jan 29 2009
Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
```On Thu, Jan 29, 2009 at 6:00 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
a[x1 .. x2, y1 .. y2] = b;

combinations of a .. b and a. But I can definitely see some good uses for
it.

Hm.. if you _wanted_ to interleave slices and single indices, how
would you do it?  How about we take a page from Python's book: it
doesn't (used to but no longer) distinguish between slicing and
indexing.  It uses the same "operator overload" for both, but slicing
passes a 2-tuple as the "index", kind of like:

blah opIndex(int x) // used for a[0]
blarg opIndex(Slice!(int, int) x) // used for a[0 .. 1]

Assuming we have a "struct Slice(Lo, Hi) { Lo lo; Hi hi; }" type.

Then, you could just have opIndex[Assign] take multiple parameters -
like it does now.  And of course, it could just take a tuple and
figure out what to do based on whether each thing is an int or if it's
a slice.  Complex, but completely doable, and it still leaves simple
cases simple.
```
Jan 29 2009
Don <nospam nospam.com> writes:
```Jarrett Billingsley wrote:
On Thu, Jan 29, 2009 at 6:00 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
a[x1 .. x2, y1 .. y2] = b;

combinations of a .. b and a. But I can definitely see some good uses for
it.

Hm.. if you _wanted_ to interleave slices and single indices, how
would you do it?  How about we take a page from Python's book: it
doesn't (used to but no longer) distinguish between slicing and
indexing.  It uses the same "operator overload" for both, but slicing
passes a 2-tuple as the "index", kind of like:

blah opIndex(int x) // used for a[0]
blarg opIndex(Slice!(int, int) x) // used for a[0 .. 1]

Assuming we have a "struct Slice(Lo, Hi) { Lo lo; Hi hi; }" type.

Then, you could just have opIndex[Assign] take multiple parameters -
like it does now.  And of course, it could just take a tuple and
figure out what to do based on whether each thing is an int or if it's
a slice.  Complex, but completely doable, and it still leaves simple
cases simple.

That's exactly what I did in Blade. opSlice() is a dead end.
The algebra for combining consecutive slices is quite interesting, but
it's not really that complicated. You can always transform any
expression like:
x[3..5, 6, 2..\$][4, \$][5..\$][3..7][6];
into a single mixed opIndex() call.
You can do mixed index and slices either by making every slice a tuple,
or by having a bool array stating whether each entry is an index, or
just the second part of a slice. (This way every parameter in opIndex is
the same type:  there's less template bloat).
```
Jan 30 2009