digitalmars.D - opSlice and $
- Russell Lewis (6/6) Sep 11 2007 It appears to me, looking at the spec, that there isn't a way to support...
- Sean Kelly (4/12) Sep 11 2007 The '$' symbol should map to "size_t length()" when used with opSlice,
- Oskar Linde (5/17) Sep 11 2007 The problem how that generalizes to multidimensional slicing:
- Sean Kelly (3/20) Sep 11 2007 Ugh. I guess we'd need an opLength after all, huh?
- Witold Baryluk (46/63) Sep 11 2007 Yes. It will be nice to have this. Currenly I use temporary class for
- Janice Caron (7/11) Sep 11 2007 Just a suggestion, but the signature could be
- Kirk McDonald (46/66) Sep 11 2007 If I may wax Pythonic, there is a better way: Slice objects. Take the
- Janice Caron (5/7) Sep 11 2007 Sounds good to me!
- Oskar Linde (12/91) Sep 11 2007 I fully agree and have proposed the same more than once. What I have
- Bill Baxter (4/97) Sep 11 2007 I fully agree too. Some sort of slice object would make writing and
- Sean Kelly (4/9) Sep 11 2007 I would love this. It would be quite useful for ordered associative
- Robert Fraser (2/14) Sep 11 2007 Got my vote!
- Jarrett Billingsley (42/47) Sep 11 2007 ...?
- Sean Kelly (4/14) Sep 11 2007 Yeah, that stinks. It's on the "to do" list somewhere.
- Witold Baryluk (29/41) Sep 11 2007 [cut]
- S. (3/22) Sep 11 2007 Multidimensional slicing isn't mentioned in the language spec. When was...
- Witold Baryluk (32/41) Sep 12 2007 Never. yet.
- Daniel Keep (21/57) Sep 12 2007 Two ideas:
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (11/39) Sep 12 2007 Or what about
- Matti Niemenmaa (5/8) Sep 11 2007 Nope, no way. Requests for opDollar or the equivalent have been made, bu...
It appears to me, looking at the spec, that there isn't a way to support the use of $ in operator overloading. Is there anything I've overlooked? What I'm looking for, of course, is to be able to do: class MyClass {....} MyClass c = new MyClass; auto x = c[1..$];
Sep 11 2007
Russell Lewis wrote:It appears to me, looking at the spec, that there isn't a way to support the use of $ in operator overloading. Is there anything I've overlooked? What I'm looking for, of course, is to be able to do: class MyClass {....} MyClass c = new MyClass; auto x = c[1..$];The '$' symbol should map to "size_t length()" when used with opSlice, but at the moment I don't think this is the case. Sean
Sep 11 2007
Sean Kelly wrote:Russell Lewis wrote:The problem how that generalizes to multidimensional slicing: c[1..$, 2..$] -- OskarIt appears to me, looking at the spec, that there isn't a way to support the use of $ in operator overloading. Is there anything I've overlooked? What I'm looking for, of course, is to be able to do: class MyClass {....} MyClass c = new MyClass; auto x = c[1..$];The '$' symbol should map to "size_t length()" when used with opSlice, but at the moment I don't think this is the case.
Sep 11 2007
Oskar Linde wrote:Sean Kelly wrote:Ugh. I guess we'd need an opLength after all, huh? SeanRussell Lewis wrote:The problem how that generalizes to multidimensional slicing: c[1..$, 2..$]It appears to me, looking at the spec, that there isn't a way to support the use of $ in operator overloading. Is there anything I've overlooked? What I'm looking for, of course, is to be able to do: class MyClass {....} MyClass c = new MyClass; auto x = c[1..$];The '$' symbol should map to "size_t length()" when used with opSlice, but at the moment I don't think this is the case.
Sep 11 2007
Dnia Tue, 11 Sep 2007 21:27:44 +0200 Oskar Linde <oskar.lindeREM OVEgmail.com> napisa=B3/a:Sean Kelly wrote:Yes. It will be nice to have this. Currenly I use temporary class for remebering first dimension of slice, and object from which we slice. c[1..3][1..5] It is also problem that you can only have size_t in opSlice what about other types? c[ "a" .. "b"] or c[ "names", "A" .. "Z" ] c[ "numbers", 1 .. 9 ],=20 or more complicated slices... c[ "x", 2..5, "as" .. $, $ .. $-1, 4, 5]. ^a ^b where a is different from b. I dont know even what signature it will have, how to distinguish such uses: c[1, 2..3] c[1..2,3] mayby: opSlice(int, SliceTuple!(int, int)); opSlice(SliceTuple!(int, int), int); this then can be extended to things like: c [ 1 .. 2 .. 3] // SliceTuple!(int, int, int), ie. all paths // from 1 to 3 throught 3 or c [ 0 .. "9198231987397813" ] but what about $'s ? Not all of this is practical, but it will be good to have some elastic syntax for it. Creating temporary objects are very general, but why not have small syntactic sugar ([ .. ] is also syntactic sugar for opSlice call) or automatic creation of this objects and then rewriting this to: c[ "x" ][ 2..5 ][ "as" .. $ ][ $ .. $-1 ][ 4 ][ 5 ]. now all is simple. Every prefix will acumulate every pair and at the last call it will call some method. It can be good excerise to write some very general template mechanism for this. Generating temporary object is also good for things like: c[1..3][4..5] +=3D b[1..3][4..5]; it is quite trivial when using temporary object (overload opAddAssign). D have no opSlice*Assign (similary there is no opIndex*Assign). :/ --=20 Witold Baryluk, aleph0 MAIL: baryluk smp.if.uj.edu.pl JID: movax jabber.autocom.plRussell Lewis wrote:=20 The problem how that generalizes to multidimensional slicing: c[1..$, 2..$]It appears to me, looking at the spec, that there isn't a way to=20 support the use of $ in operator overloading. Is there anything I've overlooked? What I'm looking for, of course, is to be able to do: class MyClass {....} MyClass c =3D new MyClass; auto x =3D c[1..$];=20 The '$' symbol should map to "size_t length()" when used with opSlice, but at the moment I don't think this is the case.
Sep 11 2007
I dont know even what signature it will have, how to distinguish such uses: c[1, 2..3] c[1..2,3]Just a suggestion, but the signature could be opSlice(int[] ...) where the passed array always had an even number of parameters, and non-slice parameters get passed as the tuple n, n+1. In that case, your two cases would be distinguished as [ 1, 2, 2, 3 ] and [ 1, 2, 3, 4 ] (since 1 is equivalent to 1..2, and 3 is equivalent to 3..4). Only works for ints, but hey! Better than nothing.
Sep 11 2007
Janice Caron wrote:If I may wax Pythonic, there is a better way: Slice objects. Take the following Python code: class C(object): def __getitem__(self, i): return i __getitem__ is roughly the equivalent of opIndex:I dont know even what signature it will have, how to distinguish such uses: c[1, 2..3] c[1..2,3]Just a suggestion, but the signature could be opSlice(int[] ...) where the passed array always had an even number of parameters, and non-slice parameters get passed as the tuple n, n+1. In that case, your two cases would be distinguished as [ 1, 2, 2, 3 ] and [ 1, 2, 3, 4 ] (since 1 is equivalent to 1..2, and 3 is equivalent to 3..4). Only works for ints, but hey! Better than nothing.10 However, it handles slicing, as well:c = C() c[10]slice(2, 10, None)c[2:10]slice(1, 5, 2) Slices in Python have two or three items in them. The first two are the start and stop indices, which work just like in D. The third is an optional "step". If you set it to (e.g.) 2, you would get every other item. As the above code shows, it defaults to None. The slice object is very simple, and has three attributes of note, start, stop, and step, which are the values passed to the slice. If I may make up some syntax, we could invent a new "slice" type in D. I am admittedly not very good at making up syntax, but maybe something like this: alias void[int..int] slice; // a slice from an int to an int (A better keyword than "void" might be thought of.) You could then declare opIndex like this: class C { int[] arr; int opIndex(slice s) { return arr[s.start..s.stop]; // or just: return arr[s]; } } The examples mentioned previously become easy as pie. These: c[1, 2..3] c[1..2, 3] Would require the following opIndex methods: int opIndex(int, slice); int opIndex(slice, int); opSlice would, therefore, become entirely obsolete, unless I am missing some edge-case or other. This is possibly a little wild and crazy. I feel the basic idea is sound, however. What do other people think? -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.orgc[1:5:2]
Sep 11 2007
On 9/11/07, Kirk McDonald <kirklin.mcdonald gmail.com> wrote:This is possibly a little wild and crazy. I feel the basic idea is sound, however. What do other people think?Sounds good to me! Except that, if you had N dimensions, you'd have to overload the function N squared times, so it doesn't scale. A variadic function would fix that.
Sep 11 2007
Kirk McDonald wrote:Janice Caron wrote:I fully agree and have proposed the same more than once. What I have been doing is something that would also handle $ properly. See attached file. The class template code for opIndex then need to handle arguments of types int, End, EndRel, EndMod, FullRange, Range, EndRange, EndRelRange, etc... This may all be a bit overkill. But it is a low overhead solution to the problem. And variadic templates make opIndex simple to implement. Template bloat is a problem though. -- OskarIf I may wax Pythonic, there is a better way: Slice objects. Take the following Python code: class C(object): def __getitem__(self, i): return i __getitem__ is roughly the equivalent of opIndex: >>> c = C() >>> c[10] 10 However, it handles slicing, as well: >>> c[2:10] slice(2, 10, None) >>> c[1:5:2] slice(1, 5, 2) Slices in Python have two or three items in them. The first two are the start and stop indices, which work just like in D. The third is an optional "step". If you set it to (e.g.) 2, you would get every other item. As the above code shows, it defaults to None. The slice object is very simple, and has three attributes of note, start, stop, and step, which are the values passed to the slice. If I may make up some syntax, we could invent a new "slice" type in D. I am admittedly not very good at making up syntax, but maybe something like this: alias void[int..int] slice; // a slice from an int to an int (A better keyword than "void" might be thought of.) You could then declare opIndex like this: class C { int[] arr; int opIndex(slice s) { return arr[s.start..s.stop]; // or just: return arr[s]; } } The examples mentioned previously become easy as pie. These: c[1, 2..3] c[1..2, 3] Would require the following opIndex methods: int opIndex(int, slice); int opIndex(slice, int); opSlice would, therefore, become entirely obsolete, unless I am missing some edge-case or other. This is possibly a little wild and crazy. I feel the basic idea is sound, however. What do other people think?I dont know even what signature it will have, how to distinguish such uses: c[1, 2..3] c[1..2,3]Just a suggestion, but the signature could be opSlice(int[] ...) where the passed array always had an even number of parameters, and non-slice parameters get passed as the tuple n, n+1. In that case, your two cases would be distinguished as [ 1, 2, 2, 3 ] and [ 1, 2, 3, 4 ] (since 1 is equivalent to 1..2, and 3 is equivalent to 3..4). Only works for ints, but hey! Better than nothing.
Sep 11 2007
Oskar Linde wrote:Kirk McDonald wrote:I fully agree too. Some sort of slice object would make writing and using multi-dim array classes much easier. --bbJanice Caron wrote:I fully agree and have proposed the same more than once. What I have been doing is something that would also handle $ properly. See attached file. The class template code for opIndex then need to handle arguments of types int, End, EndRel, EndMod, FullRange, Range, EndRange, EndRelRange, etc... This may all be a bit overkill. But it is a low overhead solution to the problem. And variadic templates make opIndex simple to implement. Template bloat is a problem though.If I may wax Pythonic, there is a better way: Slice objects. Take the following Python code: class C(object): def __getitem__(self, i): return i __getitem__ is roughly the equivalent of opIndex: >>> c = C() >>> c[10] 10 However, it handles slicing, as well: >>> c[2:10] slice(2, 10, None) >>> c[1:5:2] slice(1, 5, 2) Slices in Python have two or three items in them. The first two are the start and stop indices, which work just like in D. The third is an optional "step". If you set it to (e.g.) 2, you would get every other item. As the above code shows, it defaults to None. The slice object is very simple, and has three attributes of note, start, stop, and step, which are the values passed to the slice. If I may make up some syntax, we could invent a new "slice" type in D. I am admittedly not very good at making up syntax, but maybe something like this: alias void[int..int] slice; // a slice from an int to an int (A better keyword than "void" might be thought of.) You could then declare opIndex like this: class C { int[] arr; int opIndex(slice s) { return arr[s.start..s.stop]; // or just: return arr[s]; } } The examples mentioned previously become easy as pie. These: c[1, 2..3] c[1..2, 3] Would require the following opIndex methods: int opIndex(int, slice); int opIndex(slice, int); opSlice would, therefore, become entirely obsolete, unless I am missing some edge-case or other. This is possibly a little wild and crazy. I feel the basic idea is sound, however. What do other people think?I dont know even what signature it will have, how to distinguish such uses: c[1, 2..3] c[1..2,3]Just a suggestion, but the signature could be opSlice(int[] ...) where the passed array always had an even number of parameters, and non-slice parameters get passed as the tuple n, n+1. In that case, your two cases would be distinguished as [ 1, 2, 2, 3 ] and [ 1, 2, 3, 4 ] (since 1 is equivalent to 1..2, and 3 is equivalent to 3..4). Only works for ints, but hey! Better than nothing.
Sep 11 2007
Witold Baryluk wrote:It is also problem that you can only have size_t in opSlice what about other types? c[ "a" .. "b"]I would love this. It would be quite useful for ordered associative sequences (red-black tree, etc). Sean
Sep 11 2007
Sean Kelly Wrote:Witold Baryluk wrote:Got my vote!It is also problem that you can only have size_t in opSlice what about other types? c[ "a" .. "b"]I would love this. It would be quite useful for ordered associative sequences (red-black tree, etc). Sean
Sep 11 2007
"Robert Fraser" <fraserofthenight gmail.com> wrote in message news:fc70uu$o8r$1 digitalmars.com...Sean Kelly Wrote:...? class Blah { private int[char[]] mData; void opIndexAssign(int val, char[] key) { mData[key] = val; } int opIndex(char[] key) { return mData[key]; } int[] opSlice(char[] lo, char[] hi) { int[] ret; foreach(k, v; mData) if(k >= lo && k < hi) ret ~= v; return ret; } } void main() { scope b = new Blah(); b["a"] = 5; b["b"] = 10; b["hello"] = 13; b["x"] = 15; b["y"] = 20; b["z"] = 25; int[] x = b["b" .. "n"]; int[] y = b["x" .. "z"]; foreach(v; x) Stdout.format("{} ", v); Stdout.newline; foreach(v; y) Stdout.format("{} ", v); Stdout.newline; }I would love this. It would be quite useful for ordered associative sequences (red-black tree, etc).Got my vote!
Sep 11 2007
Jarrett Billingsley wrote:"Robert Fraser" <fraserofthenight gmail.com> wrote in message news:fc70uu$o8r$1 digitalmars.com...I thought this worked, too. Ah well, next time I'll test before replying.Sean Kelly Wrote:int[] opSlice(char[] lo, char[] hi)I would love this. It would be quite useful for ordered associative sequences (red-black tree, etc).Got my vote!Yeah, that stinks. It's on the "to do" list somewhere. Sean
Sep 11 2007
Dnia Tue, 11 Sep 2007 18:08:12 -0400 "Jarrett Billingsley" <kb3ctd2 yahoo.com> napisa=B3/a:"Robert Fraser" <fraserofthenight gmail.com> wrote in message=20 news:fc70uu$o8r$1 digitalmars.com...[cut] Thanks. I have read D specification too literally :) Indeed this works: import std.stdio; class A { char[] opSlice(char[] x, char[] y) { return x ~ y; } char[] opSlice(char[] x, int y) { char[] z =3D ""; for (int i =3D 0; i < y; i++) { z ~=3D x; } return z; } } void main() { auto a =3D new A(); auto b =3D a["a" .. "z"]; writefln(b); // prints az auto c =3D a["a" .. 7]; writefln(c); // prints aaaaaaaa } --=20 Witold Baryluk, aleph0 MAIL: baryluk smp.if.uj.edu.pl JID: movax jabber.autocom.plSean Kelly Wrote:=20 ...? =20I would love this. It would be quite useful for ordered associative sequences (red-black tree, etc).Got my vote!
Sep 11 2007
Oskar Linde Wrote:Sean Kelly wrote:Multidimensional slicing isn't mentioned in the language spec. When was this added? I would rather see $ be an alias for int.max for overloaded operators. This should be included in the spec, and then it is up to the overloaded operator to handle this to mean the last item. (either that or there could be another type added for indexes that includes this concept as a special bit sequence)Russell Lewis wrote:The problem how that generalizes to multidimensional slicing: c[1..$, 2..$] -- OskarIt appears to me, looking at the spec, that there isn't a way to support the use of $ in operator overloading. Is there anything I've overlooked? What I'm looking for, of course, is to be able to do: class MyClass {....} MyClass c = new MyClass; auto x = c[1..$];The '$' symbol should map to "size_t length()" when used with opSlice, but at the moment I don't think this is the case.
Sep 11 2007
Dnia Tue, 11 Sep 2007 16:16:58 -0400 S. <S s.com> napisa=B3/a:=20 Multidimensional slicing isn't mentioned in the language spec. When was this added?Never. yet.=20 I would rather see $ be an alias for int.max for overloaded operators. This should be included in the spec, and then it is up to the overloaded operator to handle this to mean the last item. (either that or there could be another type added for indexes that includes this concept as a special bit sequence)Good, idea, but what about $-1, or $-100000000, it will not be easy to distinguish this from normal numbers. Things like c[1 .. $/2] are correct. Problem is also with other types, like strings. c["a" .. $-4]. Is $ some special value, some special symbol, or index of last item (or beyond last item)? Imho this should be a choice of user via some operator overloading. like char[] opDollar() but there will be problem with (hypothetical) multidimensional slices. (and also multidimensional arrays). c[1..$,2..$] each of dollar means something different c[$/2,$/3]. similary. mayby type1 opDollar_1() type2 opDollar_2() but not always second dollar is independend of first. for example let c be kind od triangular array, then $ here will be like second index in first subslice. c[1..4, 1..$] // $ =3D=3D 4 c[1..5, 1..$] // $ =3D=3D 5 Creating temporary objects are very very genneral for such constructions, but anyway we will need opDollar. --=20 Witold Baryluk, aleph0 MAIL: baryluk smp.if.uj.edu.pl JID: movax jabber.autocom.pl
Sep 12 2007
Witold Baryluk wrote:[snip] Imho this should be a choice of user via some operator overloading. like char[] opDollar() but there will be problem with (hypothetical) multidimensional slices. (and also multidimensional arrays). c[1..$,2..$] each of dollar means something different c[$/2,$/3]. similary. mayby type1 opDollar_1() type2 opDollar_2() but not always second dollar is independend of first. for example let c be kind od triangular array, then $ here will be like second index in first subslice. c[1..4, 1..$] // $ == 4 c[1..5, 1..$] // $ == 5 Creating temporary objects are very very genneral for such constructions, but anyway we will need opDollar.Two ideas: elemT[] opSlice(Repeat!(offset,2) xr, Repeat!(offset,2) yr); c[1..$,2..$] --> c.opSlice(offset(1), offset.dollar(0), offset(2), offset.dollar(0)); c[1..$,2..$-1] --> c.opSlice(offset(1), offset.dollar(0), offset(2), offset.dollar(-1)); You could create such a type by sacrificing the upper-most bit of a size_t type; if that bit is set, treat it as a one's complement signed offset from whatever "dollar" happens to be. Other idea: Tuple!(size_t, size_t) opDollar(); Or, if we aren't allowed to have tuple return types: void opDollar(out size_t, out size_t); That gives us multidimensional dollars. Come to think of it, the second is probably the better syntax since it will allow for overloading based on how many dimensions the user is indexing on. This could be useful for, say, matrices which could be accessed as columns of vectors, or individual scalars. Just something to chew on :) -- Daniel
Sep 12 2007
Daniel Keep wrote:Two ideas: elemT[] opSlice(Repeat!(offset,2) xr, Repeat!(offset,2) yr); c[1..$,2..$] --> c.opSlice(offset(1), offset.dollar(0), offset(2), offset.dollar(0)); c[1..$,2..$-1] --> c.opSlice(offset(1), offset.dollar(0), offset(2), offset.dollar(-1)); You could create such a type by sacrificing the upper-most bit of a size_t type; if that bit is set, treat it as a one's complement signed offset from whatever "dollar" happens to be. Other idea: Tuple!(size_t, size_t) opDollar(); Or, if we aren't allowed to have tuple return types: void opDollar(out size_t, out size_t); That gives us multidimensional dollars. Come to think of it, the second is probably the better syntax since it will allow for overloading based on how many dimensions the user is indexing on. This could be useful for, say, matrices which could be accessed as columns of vectors, or individual scalars. Just something to chew on :)Or what about retType opDollar(int dollar_idx = 0)(idxType); It would also need some changes in the way compiler handles templated methods and template default parameters currently. But I live in faith that those will change :) A bit OT, but I was browsing some older posts and came across several instances of amazingly similar concepts that have been discussed lately (for example ndim slices, macros and multiple return values). That just makes me wonder whether time really is linear or are we stuck in an eternal loop (modulo 42) ? :)
Sep 12 2007
Russell Lewis wrote:It appears to me, looking at the spec, that there isn't a way to support the use of $ in operator overloading. Is there anything I've overlooked?Nope, no way. Requests for opDollar or the equivalent have been made, but no response so far. -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Sep 11 2007