digitalmars.D - A new class -->String
- jinheking (184/184) Apr 03 2007 I want to make a Class like java's String Class.
- Frits van Bommel (31/234) Apr 04 2007 Those last two are unnecessary. wchar[] + slicing takes care of everythi...
- jinheking (9/254) Apr 04 2007 String opAssign(wchar[] value) {
- Frits van Bommel (19/28) Apr 04 2007 I'm sorry, I don't understand what you're trying to say.
- jinheking (22/50) Apr 04 2007 Your advice is right
- jinheking (2/9) Apr 04 2007 Next time,I will do it.If I have this power.
- David B. Held (11/13) Apr 04 2007 Well, I believe the intention is that when 'invariant' gets added to the...
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (9/24) Apr 04 2007 D has that already :)
- David B. Held (11/38) Apr 05 2007 Well, it isn't general:
- =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= (6/24) Apr 05 2007 Hm, I wonder if that's a compiler bug. I have not used this feature
- Daniel Keep (18/45) Apr 05 2007 From what I understand, it's not a feature, it's a bug. No, I'm
- Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= (6/44) Apr 05 2007 In Scala language this can be "safely" done with views and implicit type
- Dan (7/7) Apr 05 2007 I totally disagree with Class'ing a simple data type just to introduce f...
- Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= (15/29) Apr 05 2007 I'm sure we all agree on that. Extending previously closed classes is a
- Dan (3/20) Apr 05 2007 If what you want is operator overrides, I'd recommend a struct. Semanti...
- David B. Held (7/11) Apr 05 2007 The free vs. method syntax proposal I mentioned earlier is not
- Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= (6/20) Apr 06 2007 What I had in mind was that view + impl. conversion approach. In D it mi...
- Frank Benoit (keinfarbton) (3/3) Apr 04 2007 I wonder if you are currently starting to port java code to D.
- BLS (9/13) Apr 04 2007 Hi ,
- jinheking (369/369) Apr 05 2007 //module jdk2d.lang;
- jinheking (3/3) Apr 05 2007 Document HTML
I want to make a Class like java's String Class. module jdk2d.lang; import std.stdio; /* * The <code>String</code> class represents character strings. All * string literals in D programs, such as <code>"abc"</code>, are * implemented as instances of this class. * author Caoqi * version 0.001, 07/03/30 * since JDK2D 0.02 * url http://jinheking.javaeye.com/admin * <p> */ public class String{ private final wchar[] value; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count; /* * Initializes a newly created { code String} object so that it represents * an empty character sequence. Note that use of this constructor is * unnecessary since Strings are immutable. */ this(){ this.offset = 0; this.count = 0; this.value = new wchar[0]; } String opAssign(wchar[] value) { int size = value.length; offset = 0; count = size; value = value; return this; } /* * Allocates a new { code String} so that it represents the sequence of * characters currently contained in the character array argument. The * contents of the character array are copied; subsequent modification of * the character array does not affect the newly created string. * * param value * The initial value of the string */ public this(wchar[] value) { int size = value.length; this.offset = 0; this.count = size; this.value = value; } /** * Returns the length of this string. * The length is equal to the number of <a href="Character.html#unicode">Unicode * code units</a> in the string. * * return the length of the sequence of characters represented by this * object. */ public int length() { return count; } /** * Returns <tt>true</tt> if, and only if, { link #length()} is <tt>0</tt>. * * return <tt>true</tt> if { link #length()} is <tt>0</tt>, otherwise * <tt>false</tt> * * since JDK2D 0.01 */ public bool isEmpty() { return count == 0; } /** * Returns the index within this string of the first occurrence of the * specified substring. The integer returned is the smallest value * <i>k</i> such that: * <blockquote><pre> * this.startsWith(str, <i>k</i>) * </pre></blockquote> * is <code>true</code>. * * param str any string. * return if the string argument occurs as a substring within this * object, then the index of the first character of the first * such substring is returned; if it does not occur as a * substring, <code>-1</code> is returned. */ public int indexOf(String str) { return indexOf(str, 0); } public int indexOf(wchar[] str) { return indexOf(str, 0); } /** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. The integer * returned is the smallest value <tt>k</tt> for which: * <blockquote><pre> * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k) * </pre></blockquote> * If no such value of <i>k</i> exists, then -1 is returned. * * param str the substring for which to search. * param fromIndex the index from which to start the search. * return the index within this string of the first occurrence of the * specified substring, starting at the specified index. */ public int indexOf(String str, int fromIndex) { return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } public int indexOf(wchar[] wstr, int fromIndex) { String str=new String(wstr); return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } /** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target * is the string being searched for. * * param source the characters being searched. * param sourceOffset offset of the source string. * param sourceCount count of the source string. * param target the characters being searched for. * param targetOffset offset of the target string. * param targetCount count of the target string. * param fromIndex the index to begin searching from. */ static int indexOf(wchar[] source, int sourceOffset, int sourceCount, wchar[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } wchar first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { i++; while (i <= max && source[i] != first){ i++; } } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && (source[j] == target[k]);j++){ k++; } if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; } char[] toString(){ return cast(char[])std.utf.toUTF8(this.value); } } public static void main() { String str = new String("The quick brown fox jumped over the lazy dog."); String s1 = new String("abc"); s1="abc"; writefln(s1); printf("%d\n",str.indexOf("z")); printf("%d\n",str.isEmpty()); }
Apr 03 2007
jinheking wrote:I want to make a Class like java's String Class. module jdk2d.lang; import std.stdio; /* * The <code>String</code> class represents character strings. All * string literals in D programs, such as <code>"abc"</code>, are * implemented as instances of this class.I don't think last bit is going to happen.* author Caoqi * version 0.001, 07/03/30 * since JDK2D 0.02 * url http://jinheking.javaeye.com/admin * <p> */ public class String{ private final wchar[] value; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count;Those last two are unnecessary. wchar[] + slicing takes care of everything. So all you need is private final wchar[] value; (and when the new constness proposal comes through, add const (or better yet, invariant) to that)/* * Initializes a newly created { code String} object so that it represents * an empty character sequence. Note that use of this constructor is * unnecessary since Strings are immutable. */ this(){ this.offset = 0; this.count = 0; this.value = new wchar[0];just this.value = null; will do just fine.} String opAssign(wchar[] value) { int size = value.length; offset = 0; count = size; value = value; return this;(You forgot a 'this' in front of the left-hand 'value' in that assignment) this.value = value.dup; To be sure the code outside can't modify the contents. Once constness comes through, add an overload that takes an invariant wchar[] and doesn't dup.} /* * Allocates a new { code String} so that it represents the sequence of * characters currently contained in the character array argument. The * contents of the character array are copied; subsequent modification of * the character array does not affect the newly created string. * * param value * The initial value of the string */ public this(wchar[] value) { int size = value.length; this.offset = 0; this.count = size; this.value = value;Same as above: this.value = value.dup;} /** * Returns the length of this string. * The length is equal to the number of <a href="Character.html#unicode">Unicode * code units</a> in the string. * * return the length of the sequence of characters represented by this * object. */ public int length() { return count;return value.length;} /** * Returns <tt>true</tt> if, and only if, { link #length()} is <tt>0</tt>. * * return <tt>true</tt> if { link #length()} is <tt>0</tt>, otherwise * <tt>false</tt> * * since JDK2D 0.01 */ public bool isEmpty() { return count == 0;return value.length == 0;} /** * Returns the index within this string of the first occurrence of the * specified substring. The integer returned is the smallest value * <i>k</i> such that: * <blockquote><pre> * this.startsWith(str, <i>k</i>) * </pre></blockquote> * is <code>true</code>. * * param str any string. * return if the string argument occurs as a substring within this * object, then the index of the first character of the first * such substring is returned; if it does not occur as a * substring, <code>-1</code> is returned. */ public int indexOf(String str) { return indexOf(str, 0); } public int indexOf(wchar[] str) { return indexOf(str, 0); } /** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. The integer * returned is the smallest value <tt>k</tt> for which: * <blockquote><pre> * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k) * </pre></blockquote> * If no such value of <i>k</i> exists, then -1 is returned. * * param str the substring for which to search. * param fromIndex the index from which to start the search. * return the index within this string of the first occurrence of the * specified substring, starting at the specified index. */ public int indexOf(String str, int fromIndex) { return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } public int indexOf(wchar[] wstr, int fromIndex) { String str=new String(wstr); return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } /** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target * is the string being searched for. * * param source the characters being searched. * param sourceOffset offset of the source string. * param sourceCount count of the source string. * param target the characters being searched for. * param targetOffset offset of the target string. * param targetCount count of the target string. * param fromIndex the index to begin searching from. */ static int indexOf(wchar[] source, int sourceOffset, int sourceCount, wchar[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } wchar first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { i++; while (i <= max && source[i] != first){ i++; } } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && (source[j] == target[k]);j++){ k++; } if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; }Using slicing so offset and counts don't need to be passed will allow you to implement these more cleanly, I think.char[] toString(){ return cast(char[])std.utf.toUTF8(this.value);This is broken for your implementation but just fine for mine. (It doesn't work for substrings in yours, it'll convert the entire string instead of just the part this String object represents)} } public static void main() { String str = new String("The quick brown fox jumped over the lazy dog."); String s1 = new String("abc"); s1="abc"; writefln(s1); printf("%d\n",str.indexOf("z")); printf("%d\n",str.isEmpty()); }As a final note, there's a (less Java-like) string class implementation at http://www.dprogramming.com/dstring.php. It stores its data as char[], wchar[] or dchar[] and tries to use whichever is the most space-efficient yet can still store all elements in a single array element. The last bit allows it to implement "intuitive" slicing, never slicing in the middle of a group of UTF-8 or UTF-16 code units that form a single character point (if I got the terminology right).
Apr 04 2007
String opAssign(wchar[] value) { int size = value.length; offset = 0; count = size; value = value; return this; } That is this funcation! "Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> дÈëÏûÏ¢ÐÂÎÅ:euvo53$3rg$1 digitalmars.com...jinheking wrote:I want to make a Class like java's String Class. module jdk2d.lang; import std.stdio; /* * The <code>String</code> class represents character strings. All * string literals in D programs, such as <code>"abc"</code>, are * implemented as instances of this class.I don't think last bit is going to happen.* author Caoqi * version 0.001, 07/03/30 * since JDK2D 0.02 * url http://jinheking.javaeye.com/admin * <p> */ public class String{ private final wchar[] value; /** The offset is the first index of the storage that is used. */ private final int offset; /** The count is the number of characters in the String. */ private final int count;Those last two are unnecessary. wchar[] + slicing takes care of everything. So all you need is private final wchar[] value; (and when the new constness proposal comes through, add const (or better yet, invariant) to that)/* * Initializes a newly created { code String} object so that it represents * an empty character sequence. Note that use of this constructor is * unnecessary since Strings are immutable. */ this(){ this.offset = 0; this.count = 0; this.value = new wchar[0];just this.value = null; will do just fine.} String opAssign(wchar[] value) { int size = value.length; offset = 0; count = size; value = value; return this;(You forgot a 'this' in front of the left-hand 'value' in that assignment) this.value = value.dup; To be sure the code outside can't modify the contents. Once constness comes through, add an overload that takes an invariant wchar[] and doesn't dup.} /* * Allocates a new { code String} so that it represents the sequence of * characters currently contained in the character array argument. The * contents of the character array are copied; subsequent modification of * the character array does not affect the newly created string. * * param value * The initial value of the string */ public this(wchar[] value) { int size = value.length; this.offset = 0; this.count = size; this.value = value;Same as above: this.value = value.dup;} /** * Returns the length of this string. * The length is equal to the number of <a href="Character.html#unicode">Unicode * code units</a> in the string. * * return the length of the sequence of characters represented by this * object. */ public int length() { return count;return value.length;} /** * Returns <tt>true</tt> if, and only if, { link #length()} is <tt>0</tt>. * * return <tt>true</tt> if { link #length()} is <tt>0</tt>, otherwise * <tt>false</tt> * * since JDK2D 0.01 */ public bool isEmpty() { return count == 0;return value.length == 0;} /** * Returns the index within this string of the first occurrence of the * specified substring. The integer returned is the smallest value * <i>k</i> such that: * <blockquote><pre> * this.startsWith(str, <i>k</i>) * </pre></blockquote> * is <code>true</code>. * * param str any string. * return if the string argument occurs as a substring within this * object, then the index of the first character of the first * such substring is returned; if it does not occur as a * substring, <code>-1</code> is returned. */ public int indexOf(String str) { return indexOf(str, 0); } public int indexOf(wchar[] str) { return indexOf(str, 0); } /** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. The integer * returned is the smallest value <tt>k</tt> for which: * <blockquote><pre> * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k) * </pre></blockquote> * If no such value of <i>k</i> exists, then -1 is returned. * * param str the substring for which to search. * param fromIndex the index from which to start the search. * return the index within this string of the first occurrence of the * specified substring, starting at the specified index. */ public int indexOf(String str, int fromIndex) { return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } public int indexOf(wchar[] wstr, int fromIndex) { String str=new String(wstr); return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } /** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target * is the string being searched for. * * param source the characters being searched. * param sourceOffset offset of the source string. * param sourceCount count of the source string. * param target the characters being searched for. * param targetOffset offset of the target string. * param targetCount count of the target string. * param fromIndex the index to begin searching from. */ static int indexOf(wchar[] source, int sourceOffset, int sourceCount, wchar[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } wchar first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { i++; while (i <= max && source[i] != first){ i++; } } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && (source[j] == target[k]);j++){ k++; } if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; }Using slicing so offset and counts don't need to be passed will allow you to implement these more cleanly, I think.char[] toString(){ return cast(char[])std.utf.toUTF8(this.value);This is broken for your implementation but just fine for mine. (It doesn't work for substrings in yours, it'll convert the entire string instead of just the part this String object represents)} } public static void main() { String str = new String("The quick brown fox jumped over the lazy dog."); String s1 = new String("abc"); s1="abc"; writefln(s1); printf("%d\n",str.indexOf("z")); printf("%d\n",str.isEmpty()); }As a final note, there's a (less Java-like) string class implementation at http://www.dprogramming.com/dstring.php. It stores its data as char[], wchar[] or dchar[] and tries to use whichever is the most space-efficient yet can still store all elements in a single array element. The last bit allows it to implement "intuitive" slicing, never slicing in the middle of a group of UTF-8 or UTF-16 code units that form a single character point (if I got the terminology right).
Apr 04 2007
jinheking wrote:String opAssign(wchar[] value) { int size = value.length; offset = 0; count = size; value = value; return this; } That is this funcation!I'm sorry, I don't understand what you're trying to say. If you were confused about my comment on that function in particular, let me try to reword it: The way I would code that function (assuming the class fields stay the same) would be like so: --- String opAssign(wchar[] value) { offset = 0; count = value.length; this.value = value.dup; return this; } --- The 'this.' makes sure it assigns to the 'value' defined at the top of the class, not the one parameter. The '.dup' makes a copy of the string passed in to make sure nobody else can change the value of the String object, since you want it to be immutable.
Apr 04 2007
Your advice is right I changed my fun below: /** * * <code>String str=new String("abc");</code> * <code>str="abcd";</code> * param wc * The initial value of the string */ String opAssign(wchar[] wc) { this.offset = 0; this.count = wc.length; this.value = wc.dup; return this; } void test(){ String str=new String("abc"); //True str="abcd"; //True String s2="aa";//false //which reason } How do do it? "Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> дÈëÏûÏ¢ÐÂÎÅ:euvsh7$ekg$1 digitalmars.com...jinheking wrote:String opAssign(wchar[] value) { int size = value.length; offset = 0; count = size; value = value; return this; } That is this funcation!I'm sorry, I don't understand what you're trying to say. If you were confused about my comment on that function in particular, let me try to reword it: The way I would code that function (assuming the class fields stay the same) would be like so: --- String opAssign(wchar[] value) { offset = 0; count = value.length; this.value = value.dup; return this; } --- The 'this.' makes sure it assigns to the 'value' defined at the top of the class, not the one parameter. The '.dup' makes a copy of the string passed in to make sure nobody else can change the value of the String object, since you want it to be immutable.
Apr 04 2007
As a final note, there's a (less Java-like) string class implementation at http://www.dprogramming.com/dstring.php. It stores its data as char[], wchar[] or dchar[] and tries to use whichever is the most space-efficient yet can still store all elements in a single array element. The last bit allows it to implement "intuitive" slicing, never slicing in the middle of a group of UTF-8 or UTF-16 code units that form a single character point (if I got the terminology right).Next time,I will do it.If I have this power. I hope you help me.ok?
Apr 04 2007
jinheking wrote:I want to make a Class like java's String Class. [...]Well, I believe the intention is that when 'invariant' gets added to the language, we will get string thusly: alias invariant char[] string; Note that this leaves out all of the member functions that one expects from String. However, with immutable strings, it is perfectly safe (and, perhaps, preferable) to implement all that functionality as free functions. If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...). Dave
Apr 04 2007
David B. Held wrote:jinheking wrote:D has that already :) char[] moo; void doSomething(char[] baa) { ... } void main() { moo.doSomething(); }I want to make a Class like java's String Class. [...]Well, I believe the intention is that when 'invariant' gets added to the language, we will get string thusly: alias invariant char[] string; Note that this leaves out all of the member functions that one expects from String. However, with immutable strings, it is perfectly safe (and, perhaps, preferable) to implement all that functionality as free functions. If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...).
Apr 04 2007
Jari-Matti Mäkelä wrote:David B. Held wrote:Well, it isn't general: void foo(int x) { int y = x; } unittest { int z = 5; z.foo(); } test.d(43): Error: no property 'foo' for type 'int' test.d(43): Error: function expected before (), not 1 of type int Davejinheking wrote:D has that already :) char[] moo; void doSomething(char[] baa) { ... } void main() { moo.doSomething(); }I want to make a Class like java's String Class. [...]Well, I believe the intention is that when 'invariant' gets added to the language, we will get string thusly: alias invariant char[] string; Note that this leaves out all of the member functions that one expects from String. However, with immutable strings, it is perfectly safe (and, perhaps, preferable) to implement all that functionality as free functions. If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...).
Apr 05 2007
David B. Held wrote:Jari-Matti Mäkelä wrote:David B. Held wrote:If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...).D has that already :)Well, it isn't general: void foo(int x) { int y = x; } unittest { int z = 5; z.foo(); } test.d(43): Error: no property 'foo' for type 'int' test.d(43): Error: function expected before (), not 1 of type intHm, I wonder if that's a compiler bug. I have not used this feature recently, but I recall it used to work. I even have bindings where this feature is used to provide an alternative syntax for a wrapper class. Now that I tested it, it only seems to work with arrays and AAs anymore. But it's still enough to implement those string functions though.
Apr 05 2007
Jari-Matti Mäkelä wrote:David B. Held wrote:From what I understand, it's not a feature, it's a bug. No, I'm serious: this happens because of a bug in DMD. The only reason it's never been fixed is because people actually really, really like that it works :) The whole "switch function to member of first arg" thing is only usable, as you said, on arrays and AAs. Having it usable in general would be wicked-nifty-awesome-keen, to mix my colloquialisms. :) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/Jari-Matti Mäkelä wrote:David B. Held wrote:If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...).D has that already :)Well, it isn't general: void foo(int x) { int y = x; } unittest { int z = 5; z.foo(); } test.d(43): Error: no property 'foo' for type 'int' test.d(43): Error: function expected before (), not 1 of type intHm, I wonder if that's a compiler bug. I have not used this feature recently, but I recall it used to work. I even have bindings where this feature is used to provide an alternative syntax for a wrapper class. Now that I tested it, it only seems to work with arrays and AAs anymore. But it's still enough to implement those string functions though.
Apr 05 2007
Daniel Keep wrote:Jari-Matti Mäkelä wrote:Ah, you're right. I didn't find it in the language docs either.David B. Held wrote:From what I understand, it's not a feature, it's a bug. No, I'm serious: this happens because of a bug in DMD. The only reason it's never been fixed is because people actually really, really like that it works :)Jari-Matti Mäkelä wrote:David B. Held wrote:If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...).D has that already :)Well, it isn't general: void foo(int x) { int y = x; } unittest { int z = 5; z.foo(); } test.d(43): Error: no property 'foo' for type 'int' test.d(43): Error: function expected before (), not 1 of type intHm, I wonder if that's a compiler bug. I have not used this feature recently, but I recall it used to work. I even have bindings where this feature is used to provide an alternative syntax for a wrapper class. Now that I tested it, it only seems to work with arrays and AAs anymore. But it's still enough to implement those string functions though.The whole "switch function to member of first arg" thing is only usable, as you said, on arrays and AAs. Having it usable in general would be wicked-nifty-awesome-keen, to mix my colloquialisms. :)In Scala language this can be "safely" done with views and implicit type conversions. If this "poor man's version" isn't a good solution in the long run, at least there is another way to do this that has strong academic backing behind it. That alternative is also much more flexible.
Apr 05 2007
I totally disagree with Class'ing a simple data type just to introduce functions to handle it. Especially since you can use that pretty OO notation on arrays simply by having the functions accept the array as the first argument. This works: void slice(inout char[] s, size_t start, size_t finish){ ... } char[] myS = "Hello! How are you?"; myS.slice(2,6);
Apr 05 2007
Dan wrote:I totally disagree with Class'ing a simple data type just to introduce functions to handle it.I'm sure we all agree on that. Extending previously closed classes is a valuable feature in modern object oriented programming.Especially since you can use that pretty OO notation on arrays simply by having the functions accept the array as the first argument. This works: void slice(inout char[] s, size_t start, size_t finish){ ... } char[] myS = "Hello! How are you?"; myS.slice(2,6);That is what I pointed out previously. But the current syntax is limited to a few special cases. You cannot do something like auto myS = "moo"; char[] opMul(char[] str, int count) { char[] tmp; for(int i=0; i<count; i++) tmp ~= str; return tmp; } auto s2 = myS * 3; // = "moomoomoo" Also you cannot specify constraints on the use of these implicit conversions. I have not enough expertise on this, but it is good to know that some other languages have found working solutions.
Apr 05 2007
Jari-Matti Mäkelä Wrote:Dan wrote:...I totally disagree with Class'ing a simple data type just to introduce functions to handle it.I'm sure we all agree on that. Extending previously closed classes is a valuable feature in modern object oriented programming.a few special cases. You cannot do something like auto myS = "moo"; char[] opMul(char[] str, int count) { char[] tmp; for(int i=0; i<count; i++) tmp ~= str; return tmp; } auto s2 = myS * 3; // = "moomoomoo"If what you want is operator overrides, I'd recommend a struct. Semantically, it's equivalent to using the simple data type, while allowing you to sugar coat it in the same way as a class.
Apr 05 2007
Jari-Matti Mäkelä wrote:[...] I'm sure we all agree on that. Extending previously closed classes is a valuable feature in modern object oriented programming. [...]The free vs. method syntax proposal I mentioned earlier is not equivalent to extending closed classes. The latter would imply the ability to add virtual functions and method overloads outside the definition of the class, or accessing private members, which are not possible under this proposal. Dave
Apr 05 2007
David B. Held wrote:Jari-Matti Mäkelä wrote:You're right and I wasn't referring to that anymore ;)[...] I'm sure we all agree on that. Extending previously closed classes is a valuable feature in modern object oriented programming. [...]The free vs. method syntax proposal I mentioned earlier is not equivalent to extending closed classes.The latter would imply the ability to add virtual functions and method overloads outside the definition of the class, or accessing private members, which are not possible under this proposal.What I had in mind was that view + impl. conversion approach. In D it might be possible to do that all statically. Adding new members and overloading old would be possible, but I'm not sure if accessing private or even protected members through this mechanism is the right choice.Dave
Apr 06 2007
I wonder if you are currently starting to port java code to D. If so, I want to introduce you to this project: http://www.dsource.org/projects/tioport
Apr 04 2007
Hi , Pretty sure that you ll like this stuff . http://www.mbutscher.de/antlrd/ Quote from ANTLR-D < Because of the different string concepts of D and Java, the string handling is rather inconvenient. The runtime sources use a class WString which is similar to Java's String class. WString is based on 16 bit wchar characters.beside it would be nice if you are willing to share your Tool chain with us. I am f.i. interested in building a GUI-Frontend, based on NetBeans for TIOPORT .... Bjoern Frank Benoit (keinfarbton) Wrote:I wonder if you are currently starting to port java code to D. If so, I want to introduce you to this project: http://www.dsource.org/projects/tioport
Apr 04 2007
//module jdk2d.lang; import std.stdio; import std.string; /** * The <code>String</code> class represents character strings. All * string literals in D programs, such as <code>String str=new String("abc");</code>, * <br /><code>str="Hello world";</code> * are implemented as instances of this class.<br /> * final wchar[] value; The value is the String's value.<br /> * final int offset; The offset is the first index of the storage that is used.<br /> * final int count; The count is the number of characters in the String. <br /> * Authors: Caoqi * version: 0.021 * Date: April 5, 2007 * History: March 30,2007 V0.01 * License: BSD * See_Also: My blog, <a href=" http://jinheking.javaeye.com/"> http://jinheking.javaeye.com/</a> * <p> */ /// Documentation for String public class String{ private: final wchar[] value; ///The value is the String's value. final int offset; ///The offset is the first index of the storage that is used. final int count; ///The count is the number of characters in the String. public: /** * Initializes a newly created { code String} object so that it represents * an empty character sequence. Note that use of this constructor is * unnecessary since Strings are immutable. */ this(){ this.offset = 0; this.count = 0; this.value = null; } /** * Params:wc = The initial value of the string * Return: * String * <code>String str=new String("abc");</code><br /> * <code>str="abcd";</code> */ String opAssign(wchar[] wc) { this.offset = 0; this.count = wc.length; this.value = wc.dup; return this; } /** * <code>s1>s2</code> * Params: s = The initial value of the string * Return: bool */ int opCmp(String s){ return std.string.cmp(cast(char[])this.value, cast(char[])s.value); } /* * Allocates a new { code String} so that it represents the sequence of * characters currently contained in the character array argument. The * contents of the character array are copied; subsequent modification of * the character array does not affect the newly created string. * * Param: value = The initial value of the string */ public this(wchar[] value) { int size = value.length; this.offset = 0; this.count = size; this.value = value; } /** * Returns the length of this string. * The length is equal to the number of <a href="Character.html#unicode">Unicode * code units</a> in the string. * * Return: The length of the sequence of characters represented by this * object. */ public int length() { return this.value.length; } /** * Returns <tt>true</tt> if, and only if, { link #length()} is <tt>0</tt>. * * Return <tt>true</tt> if { link #length()} is <tt>0</tt>, otherwise * <tt>false</tt> */ public bool isEmpty() { return count == 0; } /** * Returns the index within this string of the first occurrence of the * specified substring. The integer returned is the smallest value * <i>k</i> such that: * <blockquote><pre> * this.startsWith(str, <i>k</i>) * </pre></blockquote> * is <code>true</code>. * * Params: str = any String. * Return: if the string argument occurs as a substring within this * object, then the index of the first character of the first * such substring is returned; if it does not occur as a * substring, <code>-1</code> is returned. */ public int indexOf(String str) { return indexOf(str, 0); } /** * Returns the index within this string of the first occurrence of the * specified substring. The integer returned is the smallest value * <i>k</i> such that: * <blockquote><pre> * this.startsWith(str, <i>k</i>) * </pre></blockquote> * is <code>true</code>. * * Params: str = any String. * Return: if the string argument occurs as a substring within this * object, then the index of the first character of the first * such substring is returned; if it does not occur as a * substring, <code>-1</code> is returned. */ public int indexOf(wchar[] str) { return indexOf(str, 0); } /** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. The integer * returned is the smallest value <tt>k</tt> for which: * <blockquote><pre> * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k) * </pre></blockquote> * If no such value of <i>k</i> exists, then -1 is returned. * * Param: str = the substring for which to search. * Param: fromIndex = the index from which to start the search. * Return: the index within this string of the first occurrence of the * specified substring, starting at the specified index. */ public int indexOf(String str, int fromIndex) { return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } /** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. The integer * returned is the smallest value <tt>k</tt> for which: * <blockquote><pre> * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k) * </pre></blockquote> * If no such value of <i>k</i> exists, then -1 is returned. * * Param: str = the substring for which to search. * Param: fromIndex = the index from which to start the search. * Return: the index within this string of the first occurrence of the * specified substring, starting at the specified index. */ public int indexOf(wchar[] wstr, int fromIndex) { String str=new String(wstr); return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); } /** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target * is the string being searched for. * * Params: source = the characters being searched. * Params: sourceOffset= offset of the source string. * Params: sourceCount= count of the source string. * Params: target = the characters being searched for. * Params: targetOffset =offset of the target string. * Params: targetCount = count of the target string. * Params: fromIndex = the index to begin searching from. * Return: the index within this string of the first occurrence of the * specified substring, starting at the specified index. */ static int indexOf(wchar[] source, int sourceOffset, int sourceCount, wchar[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } wchar first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { i++; while (i <= max && source[i] != first){ i++; } } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && (source[j] == target[k]);j++){ k++; } if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; } /** * Return:The String's value */ char[] toString(){ return cast(char[])std.utf.toUTF8(this.value); } } /++++++++++++++++++++++++ + Our function. + Example: + -------------------------- + import std.stdio; + + void foo() + { + String str=new String("Hi,jdk2d String,I need you!") ; + writefln(str); /* print the string */ + str="Next,I calculate the str's length" + writefln(str); /* print the string */ + printf("%d\n",str.length()); + } + -------------------------- +/ public static void main() { String str = new String("The quick brown fox jumped over the lazy dog."); String s1 = new String("abc"); s1="abc"; String s2=new String("ab"); writef("s1="); writefln(s1); writef("s2="); writefln(s2); if(s1>s2) printf("s1>s2=%.*s\n","true"); else printf("s1>s2=%.*s\n","false"); String s3=new String("ab"); String s4=new String("abc"); writef("s3="); writefln(s3); writef("s4="); writefln(s4); if(s3>s4) printf("s3>s4=%.*s\n","true"); else printf("s3>s4=%.*s\n","false"); printf("%d\n",str.indexOf("z")); printf("%d\n",str.isEmpty()); } ----------------------------------------------------------------------------------- String.ddoc B = <b>$0</b> I = <i>$0</i> U = <u>$0</u> P = <p>$0</p> DL = <dl>$0</dl> DT = <dt>$0</dt> DD = <dd>$0</dd> TABLE = <table>$0</table> TR = <tr>$0</tr> TH = <th>$0</th> TD = <td>$0</td> OL = <ol>$0</ol> UL = <ul>$0</ul> LI = <li>$0</li> BIG = <big>$0</big> SMALL = <small>$0</small> BR = <br> LINK = <a href="$0">$0</a> LINK2 = <a href="$1">$+</a> RED = <font color=red>$0</font> BLUE = <font color=blue>$0</font> GREEN = <font color=green>$0</font> YELLOW =<font color=yellow>$0</font> BLACK = <font color=black>$0</font> WHITE = <font color=white>$0</font> D_CODE = <pre class="d_code">$0</pre> D_COMMENT = $(GREEN $0) D_STRING = $(RED $0) D_KEYWORD = $(BLUE $0) D_PSYMBOL = $(U $0) D_PARAM = $(I $0) DDOC = <html><head> <META http-equiv="content-type" content="text/html; charset=utf-8"> <title>$(TITLE)</title> </head><body> <h1>$(TITLE)</h1> $(BODY) </body></html> DDOC_COMMENT = <!-- $0 --> DDOC_DECL = $(DT $(BIG $0)) DDOC_DECL_DD = $(DD $0) DDOC_DITTO = $(BR)$0 DDOC_SECTIONS = $0 DDOC_SUMMARY = $0$(BR)$(BR) DDOC_DESCRIPTION = $0$(BR)$(BR) DDOC_AUTHORS = $(B Authors:)$(BR) $0$(BR)$(BR) DDOC_BUGS = $(RED BUGS:)$(BR) $0$(BR)$(BR) DDOC_COPYRIGHT = $(B Copyright:)$(BR) $0$(BR)$(BR) DDOC_DATE = $(B Date:)$(BR) $0$(BR)$(BR) DDOC_DEPRECATED = $(RED Deprecated:)$(BR) $0$(BR)$(BR) DDOC_EXAMPLES = $(B Examples:)$(BR) $0$(BR)$(BR) DDOC_HISTORY = $(B History:)$(BR) $0$(BR)$(BR) DDOC_LICENSE = $(B License:)$(BR) $0$(BR)$(BR) DDOC_RETURNS = $(B Returns:)$(BR) $0$(BR)$(BR) DDOC_SEE_ALSO = $(B See Also:)$(BR) $0$(BR)$(BR) DDOC_STANDARDS = $(B Standards:)$(BR) $0$(BR)$(BR) DDOC_THROWS = $(B Throws:)$(BR) $0$(BR)$(BR) DDOC_VERSION = $(B Version:)$(BR) $0$(BR)$(BR) DDOC_SECTION_H = $(B $0)$(BR)$(BR) DDOC_SECTION = $0$(BR)$(BR) DDOC_MEMBERS = $(DL $0) DDOC_MODULE_MEMBERS = $(DDOC_MEMBERS $0) DDOC_CLASS_MEMBERS = $(DDOC_MEMBERS $0) DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0) DDOC_ENUM_MEMBERS = $(DDOC_MEMBERS $0) DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0) DDOC_PARAMS = $(B Params:)$(BR)\n$(TABLE $0)$(BR) DDOC_PARAM_ROW = $(TR $0) DDOC_PARAM_ID = $(TD $0) DDOC_PARAM_DESC = $(TD $0) DDOC_BLANKLINE = $(BR)$(BR) DDOC_PSYMBOL = $(U $0) DDOC_KEYWORD = $(B $0) DDOC_PARAM = $(I $0) ------------------------------------------------------------------------------------ dmd -D String.d String.ddoc
Apr 05 2007
Document HTML http://www.caoqi.com/d DÓïÑÔÊÇÓÉDigital Mars¹«Ë¾¿ª·¢µÄ±à³ÌÓïÑÔ£¬ÆðÒòÊÇΪÁ˸ĽøC£«£«¡£ËüÓëC¶þ½øÖƼæÈÝ£¨²»ÍêÈ«£©£¬¿É±à
Apr 05 2007