digitalmars.D.learn - How to extend the string class to return this inside the square
- Marcone (7/7) Aug 13 2021 How to extend the string class to return this inside the square
- user1234 (7/14) Aug 13 2021 this does not exist (and see few reason for) but algo + ufcs
- Marcone (4/20) Aug 13 2021 My example was just an example. I don't want this solution. I
- Steven Schveighoffer (4/12) Aug 13 2021 There is no string class to extend.
- Marcone (4/18) Aug 13 2021 Isn't there some unario operator template that I can use with
- jfondren (6/8) Aug 13 2021 So, something other than an exact "lit"[0..this.xx(..)] syntax is
- =?UTF-8?Q?Ali_=c3=87ehreli?= (24/35) Aug 13 2021 And I started writing the following but stopped because the semantics
- Marcone (36/74) Aug 13 2021 import std;
- Marcone (6/15) Aug 13 2021 writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]);
- jfondren (10/28) Aug 13 2021 ```d
- Paul Backus (11/16) Aug 13 2021 You can use the `pipe` function to bind an arbitrary expression
- user1234 (2/21) Aug 14 2021 nice, that's the best alternative.
- Marcone (3/27) Aug 14 2021 Very Good!!! This pipe!() is just what I am looking for. Thank
- =?UTF-8?Q?Ali_=c3=87ehreli?= (15/17) Aug 13 2021 I don't see the usefulness and there are the following problems with it:
- H. S. Teoh (49/60) Aug 13 2021 [...]
- Steven Schveighoffer (26/46) Aug 13 2021 Operator overloading is only available to custom types (structs or
How to extend the string class to return this inside the square bracket the same way opDollar $ returns the length of the string? Thank you. import std; void main(){ writeln("Hello World!"[0..this.indexOf("o")]); }
Aug 13 2021
On Friday, 13 August 2021 at 21:05:22 UTC, Marcone wrote:How to extend the string class to return this inside the square bracket the same way opDollar $ returns the length of the string? Thank you. import std; void main(){ writeln("Hello World!"[0..this.indexOf("o")]); }this does not exist (and see few reason for) but algo + ufcs allows this easily, e.g ``` "Hello World!".findSplit("o")[0].writeln; ``` bonus: both can throw bound error
Aug 13 2021
On Friday, 13 August 2021 at 21:14:29 UTC, user1234 wrote:On Friday, 13 August 2021 at 21:05:22 UTC, Marcone wrote:My example was just an example. I don't want this solution. I want to have the power to handle the string inside the square brackets.How to extend the string class to return this inside the square bracket the same way opDollar $ returns the length of the string? Thank you. import std; void main(){ writeln("Hello World!"[0..this.indexOf("o")]); }this does not exist (and see few reason for) but algo + ufcs allows this easily, e.g ``` "Hello World!".findSplit("o")[0].writeln; ``` bonus: both can throw bound error
Aug 13 2021
On 8/13/21 5:05 PM, Marcone wrote:How to extend the string class to return this inside the square bracket the same way opDollar $ returns the length of the string? Thank you. Â Â Â import std; Â Â Â void main(){ Â Â Â Â Â Â Â writeln("Hello World!"[0..this.indexOf("o")]); Â Â Â }There is no string class to extend. `$` is a special token the compiler changes to `arr.length` for arrays. -Steve
Aug 13 2021
On Friday, 13 August 2021 at 21:47:22 UTC, Steven Schveighoffer wrote:On 8/13/21 5:05 PM, Marcone wrote:Isn't there some unario operator template that I can use with lambda to handle a string literal?How to extend the string class to return this inside the square bracket the same way opDollar $ returns the length of the string? Thank you. Â Â Â import std; Â Â Â void main(){ Â Â Â Â Â Â Â writeln("Hello World!"[0..this.indexOf("o")]); Â Â Â }There is no string class to extend. `$` is a special token the compiler changes to `arr.length` for arrays. -Steve
Aug 13 2021
On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:Isn't there some unario operator template that I can use with lambda to handle a string literal?So, something other than an exact "lit"[0..this.xx(..)] syntax is fine? What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` then? What is a real example of something you want to do?
Aug 13 2021
On 8/13/21 4:08 PM, jfondren wrote:On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:And I started writing the following but stopped because the semantics are not clear. I first called it 'between' but then should the 'o' that was searched be a part of the output? Should "from 'o' to 'o'" produce an empty string, should it include a single 'o' or should it go all the way to the next 'o'? What about the last line which says "from 'd' to 'a'"? Is that an entirely empty range or just 'd' or 'd' till the end? I don't think the programming language can decide one way or the other. import std.algorithm; import std.range; import std.stdio; auto inclusive(R, E)(R range, E fromNeedle, E toNeedle) { auto found = range.find(fromNeedle); return chain(found.front.only, found.drop(1).findSplitAfter(only(toNeedle))[0]); } void main() { const s = "Hello World!"; auto r = s.inclusive('o', 'o'); writeln(r); writeln("abcdef".inclusive('d', 'a')); } AliIsn't there some unario operator template that I can use with lambda to handle a string literal?So, something other than an exact "lit"[0..this.xx(..)] syntax is fine? What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` then? What is a real example of something you want to do?
Aug 13 2021
On Friday, 13 August 2021 at 23:21:42 UTC, Ali Çehreli wrote:On 8/13/21 4:08 PM, jfondren wrote:import std; class None {} // Function slice() auto slice(T1, T2, T3 = None)(T1 conteudo, T2 inicio, T3 fim = T3.init) { int start, end, startlen; static if (is(T2 == int)) {inicio = inicio < 0 ? conteudo.length + inicio : inicio;} static if (is(T3 == int)) {fim = fim <= 0 ? conteudo.length + fim : fim;} static if (is(T2 == int)) {start = inicio;} else static if (is(T2 == string)){start = conteudo.countUntil(inicio);} static if (is(T2 == string)) {static if (is(T1 == string)){startlen = start + inicio.length + 1;} else {startlen = start + 1;}} static if (is(T3 == int)) {end = fim;} else static if (is(T3 == string)){end = startlen + conteudo[startlen..$].countUntil(fim);} static if (is(T3 == None)) {return conteudo[start];} else {return conteudo[start..end];} } void main(){ writeln("Hello World!".slice(1, 8)); // ello Wo writeln("Hello World!".slice("e", "r")); // ello Wo writeln("Hello World!".slice(1, "r")); // ello Wo writeln("Hello World!".slice("e", 8)); // ello Wo writeln("Hello World!".slice(6, -1)); // World (Same as $-1) writeln("Hello World!".slice(-12, -7)); // Hello (Same as $-12, $-7) writeln("Hello World!".slice("W", -1)); // World (Same as "W", $-1) writeln("Hello World!".slice(-12, " ")); // Hello (Same as $-12, " ") } Like this function, but inside []. So I can use functions to get index for slice.On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:And I started writing the following but stopped because the semantics are not clear. I first called it 'between' but then should the 'o' that was searched be a part of the output? Should "from 'o' to 'o'" produce an empty string, should it include a single 'o' or should it go all the way to the next 'o'? What about the last line which says "from 'd' to 'a'"? Is that an entirely empty range or just 'd' or 'd' till the end? I don't think the programming language can decide one way or the other. import std.algorithm; import std.range; import std.stdio; auto inclusive(R, E)(R range, E fromNeedle, E toNeedle) { auto found = range.find(fromNeedle); return chain(found.front.only, found.drop(1).findSplitAfter(only(toNeedle))[0]); } void main() { const s = "Hello World!"; auto r = s.inclusive('o', 'o'); writeln(r); writeln("abcdef".inclusive('d', 'a')); } AliIsn't there some unario operator template that I can use with lambda to handle a string literal?So, something other than an exact "lit"[0..this.xx(..)] syntax is fine? What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` then? What is a real example of something you want to do?
Aug 13 2021
On Friday, 13 August 2021 at 23:08:07 UTC, jfondren wrote:On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]); indexOf()is just a simple example, not the goal. I want handle literal inside [] like it bellow, but in literal: string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);Isn't there some unario operator template that I can use with lambda to handle a string literal?So, something other than an exact "lit"[0..this.xx(..)] syntax is fine? What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` then? What is a real example of something you want to do?
Aug 13 2021
On Friday, 13 August 2021 at 23:23:55 UTC, Marcone wrote:On Friday, 13 August 2021 at 23:08:07 UTC, jfondren wrote:```d unittest { import std.functional : pipe; import std.string : indexOf; assert("Hello, world!".pipe!(x => x[x.indexOf("e") .. x.indexOf("r")]) == "ello, wo"); } ```On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]); indexOf()is just a simple example, not the goal. I want handle literal inside [] like it bellow, but in literal: string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);Isn't there some unario operator template that I can use with lambda to handle a string literal?So, something other than an exact "lit"[0..this.xx(..)] syntax is fine? What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` then? What is a real example of something you want to do?
Aug 13 2021
On Friday, 13 August 2021 at 23:23:55 UTC, Marcone wrote:writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]); indexOf()is just a simple example, not the goal. I want handle literal inside [] like it bellow, but in literal: string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);You can use the `pipe` function to bind an arbitrary expression to a variable: ```d import std.functional: pipe; import std.algorithm: countUntil; import std.stdio: writeln; "Hello world!" .pipe!(s => s[s.countUntil('e') .. s.countUntil('r')]) .writeln; ```
Aug 13 2021
On Friday, 13 August 2021 at 23:33:05 UTC, Paul Backus wrote:On Friday, 13 August 2021 at 23:23:55 UTC, Marcone wrote:nice, that's the best alternative.writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]); indexOf()is just a simple example, not the goal. I want handle literal inside [] like it bellow, but in literal: string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);You can use the `pipe` function to bind an arbitrary expression to a variable: ```d import std.functional: pipe; import std.algorithm: countUntil; import std.stdio: writeln; "Hello world!" .pipe!(s => s[s.countUntil('e') .. s.countUntil('r')]) .writeln; ```
Aug 14 2021
On Saturday, 14 August 2021 at 08:24:41 UTC, user1234 wrote:On Friday, 13 August 2021 at 23:33:05 UTC, Paul Backus wrote:Very Good!!! This pipe!() is just what I am looking for. Thank you very much!!!!On Friday, 13 August 2021 at 23:23:55 UTC, Marcone wrote:nice, that's the best alternative.writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]); indexOf()is just a simple example, not the goal. I want handle literal inside [] like it bellow, but in literal: string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);You can use the `pipe` function to bind an arbitrary expression to a variable: ```d import std.functional: pipe; import std.algorithm: countUntil; import std.stdio: writeln; "Hello world!" .pipe!(s => s[s.countUntil('e') .. s.countUntil('r')]) .writeln; ```
Aug 14 2021
On 8/13/21 4:23 PM, Marcone wrote:string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);I don't see the usefulness and there are the following problems with it: - Not an algorithmic complexity issue but it sounds to me like a pessimization to go through the elements in linear fashion, obtain indexes and then iterate between the indexes again. - This approach requires random access, which only a subset of collections provide. - The semantics of the second index is not clear. What is the intent when we say "from 'f' to 'n'" in the string "confusing"? Is it an error because the indexes 3..2 would be illegal? Or did we mean second 'n' in the string? On the other hand, the programmer can build any semantic with the existing range algorithms. And that would work even with InputRanges. You didn't ask but sorry, this feature is not for me. :) Ali
Aug 13 2021
On Fri, Aug 13, 2021 at 04:35:54PM -0700, Ali Çehreli via Digitalmars-d-learn wrote:On 8/13/21 4:23 PM, Marcone wrote:[...] In the above example, what all those indexOf calls really want to say is, "give me a slice of x starting from the first occurrence of 'e' to the next occurrence of 'r'". Once this is understood, the rest follows: writeln(x.find('e') // find first occurrence of 'e' .until('r') // slice until next occurrence of 'r' ); Or more concisely: writeln(x.find('e').until('r')); This iterates x only once, and also avoids the pathological case where 'r' appears before 'e', which in the original code would throw a RangeError because it generates a slice of negative length. // OTOH, if the OP insists that he wants arbitrary expressions inside [...], one way to do it is to overload opSlice and opIndex, then create placeholder objects that abstractly refer to parts of a string that opIndex then interprets. Something like this: // Warning: untested code struct Idx { dchar ch; } struct SliceRange { size_t start, end; } struct StringWrapper { string impl; alias impl this; SliceRange opSlice(Idx i1, Idx i2) { return SliceRange(impl.indexOf(i1.ch), impl.indexOf(i2.ch)); // or whatever more efficient implementation you // wish to use } auto opIndex(SliceRange sr) { return StringWrapper(impl[sr.start, sr.end]); } // Don't forget to implement .opDollar, which I omit // here for conciseness. } StringWrapper blah = "abcdefgh"; assert(blah[Idx('c') .. Idx('g')] == "cdefg"); Note that the above is incomplete; it's just a sketch of the concept. To make it work for all cases, opSlice needs to handle if one or both of the indices are integers, etc.. And Idx probably needs operator overloading in order to support arbitrary expressions (it basically amounts to an expression template or a runtime expression tree, if taken to its logical conclusion). Truth be told, though, this is killing an ant with a nuclear warhead. Why not just write `x.find('e').until('r')` instead. ;-) T -- Valentine's Day: an occasion for florists to reach into the wallets of nominal lovers in dire need of being reminded to profess their hypothetical love for their long-forgotten.string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);I don't see the usefulness and there are the following problems with it: - Not an algorithmic complexity issue but it sounds to me like a pessimization to go through the elements in linear fashion, obtain indexes and then iterate between the indexes again.
Aug 13 2021
On 8/13/21 7:23 PM, Marcone wrote:On Friday, 13 August 2021 at 23:08:07 UTC, jfondren wrote:Operator overloading is only available to custom types (structs or classes), and not to arrays. You can create a type to do what you want. e.g.: ```d struct SliceByIndexOf { string s; auto opIndex(size_t[2] idxs) { return SliceByIndexOf(s[ idxs[0] .. idxs[1]]); } size_t[2] opSlice(size_t dim : 0)(string s1, string s2) { import std.string; return [s.indexOf(s1), s.indexOf(s2)]; } string toString() { return s; } } auto sbio(string s) { return SliceByIndexOf(s); } void main() { import std.stdio; writeln("Hello World!".sbio["e" .. "r"]); // "ello Wo" } ``` -SteveOn Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]); indexOf()is just a simple example, not the goal. I want handle literal inside [] like it bellow, but in literal: string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]);Isn't there some unario operator template that I can use with lambda to handle a string literal?So, something other than an exact "lit"[0..this.xx(..)] syntax is fine? What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` then? What is a real example of something you want to do?
Aug 13 2021