Thread overview | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 10, 2005 Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
So, I have this complicated piece of code: |import std.file; |import std.stream; |int main() |{ | File log = new File("myfile.txt",FileMode.Out); | log.write("this is a test"); | log.close(); | return 1; |} and I try to compile it, I get, |ftest.d(6): function std.stream.Stream.write called with argument types: | (char[14]) |matches both: | std.stream.Stream.write(char[]) |and: | std.stream.Stream.write(wchar[]) Shouldn't it just match "std.stream.Stream.write(char[])"? thanks, josé |
November 10, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to jicman | jicman wrote:
> So, I have this complicated piece of code:
>
> |import std.file;
> |import std.stream;
> |int main()
> |{
> | File log = new File("myfile.txt",FileMode.Out);
> | log.write("this is a test");
> | log.close();
> | return 1;
> |}
>
> and I try to compile it, I get,
>
> |ftest.d(6): function std.stream.Stream.write called with argument types:
> | (char[14])
> |matches both:
> | std.stream.Stream.write(char[])
> |and:
> | std.stream.Stream.write(wchar[])
>
> Shouldn't it just match "std.stream.Stream.write(char[])"?
The problem is that literal string literals can be implicitly converted to char, wchar, and dchar strings. To fix the overload resolution problem, try this:
log.write( "this is a test"c );
the 'c' indicates that the above is a char string.
Sean
|
November 10, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to jicman | This is the long standing mishmash between character literal arguments and parameters of type char[], wchar[], and/or dchar[]. Character literals don't really have a "solid" type ~ the compiler can, and will, convert between wide and narrow representations on the fly. Suppose you have the following methods: void write (char[] x); void write (wchar[] x); void write (dchar[] x); Given a literal argument: write ("what am I?"); D doesn't know whether to invoke the char[] or wchar[] signature, since the literal is treated as though it's possibly any of the three types. This is the kind of non-determinism you get when the compiler becomes too 'smart' (unwarranted automatic conversion, in this case). To /patch/ around this problem, literals may be now be suffixed with a type-identifier, including 'c', 'w', and 'd'. Thus, the above example will compile when you do the following: write ( "I am a char[], dammit!" c ); I, for one, think this is silly. To skirt the issue, APIs end up being written as follows: void write (char[]); void writeW (wchar[]); void writeD (dchar[]); Is that redundant, or what? Well, it's what Phobos is forced to do in the Stream code (take a look). The error you ran into appears to be a situation where Walter's own code (std.file) bumps into this ~ wish that were enough to justify a real fix for this long-running concern. BTW; the correct thing happens when not using literals. For example, the following operates intuitively: char[] msg = "I am a char[], dammit!"; write (msg); - Kris "jicman" <jicman_member@pathlink.com> wrote in message news:dl0hja$2aal$1@digitaldaemon.com... > > So, I have this complicated piece of code: > > |import std.file; > |import std.stream; > |int main() > |{ > | File log = new File("myfile.txt",FileMode.Out); > | log.write("this is a test"); > | log.close(); > | return 1; > |} > > and I try to compile it, I get, > > |ftest.d(6): function std.stream.Stream.write called with argument types: > | (char[14]) > |matches both: > | std.stream.Stream.write(char[]) > |and: > | std.stream.Stream.write(wchar[]) > > Shouldn't it just match "std.stream.Stream.write(char[])"? > > thanks, > > josé > > |
November 10, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | This produces a compile error: void write (char[] x){} void write (wchar[] x){} void main() { write ("part 1" "part 2" c); } The compiler complains about the two literal types not matching. This also fails: void main() { write ("part 1" c "part 2" c); } This strange looking suffixing is present due to unwarranted & unwanted automatic type conversion, is it not? Wouldn't it be better to explicitly request conversion when it's actually wanted instead? Isn't that what the cast() operator is for? - Kris "Sean Kelly" <sean@f4.ca> wrote in message news:dl0in9$2bet$1@digitaldaemon.com... > jicman wrote: >> So, I have this complicated piece of code: >> >> |import std.file; >> |import std.stream; >> |int main() >> |{ >> | File log = new File("myfile.txt",FileMode.Out); >> | log.write("this is a test"); >> | log.close(); >> | return 1; >> |} >> >> and I try to compile it, I get, >> >> |ftest.d(6): function std.stream.Stream.write called with argument types: >> | (char[14]) >> |matches both: >> | std.stream.Stream.write(char[]) >> |and: >> | std.stream.Stream.write(wchar[]) >> >> Shouldn't it just match "std.stream.Stream.write(char[])"? > > The problem is that literal string literals can be implicitly converted to char, wchar, and dchar strings. To fix the overload resolution problem, try this: > > log.write( "this is a test"c ); > > the 'c' indicates that the above is a char string. > > > Sean |
November 10, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | On Thu, 10 Nov 2005 15:32:04 -0800, Kris wrote: > This produces a compile error: > > void write (char[] x){} > void write (wchar[] x){} > > void main() > { > write ("part 1" > "part 2" c); > } > > The compiler complains about the two literal types not matching. This also fails: > > void main() > { > write ("part 1" c > "part 2" c); > } > > This strange looking suffixing is present due to unwarranted & unwanted automatic type conversion, is it not? Wouldn't it be better to explicitly request conversion when it's actually wanted instead? Isn't that what the cast() operator is for? > > - Kris I don't think you are supposed to have any whitespace in between the quoted string and the suffix character. "part 1" c -- BAD "part 1"c -- Good. When I removed the extra space it compiled fine. -- Derek (skype: derek.j.parnell) Melbourne, Australia 11/11/2005 10:52:02 AM |
November 11, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Thanks, Derek. Still, it troubles me that one has to decorate string literals in this manner, when the type could be inferred by the content, or by a cast() operator where explicit conversion is required. Makes it a hassle to create and use APIs that deal with all three array types. This doesn't come up vey often, and I'd guess it's because there's just a handful of people using APIs that have to deal with a combination of both wide- and narrow-char types? |
November 11, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | "Kris" <fu@bar.com> wrote in message news:dl0ngf$2f7s$1@digitaldaemon.com... > Still, it troubles me that one has to decorate string literals in this manner, when the type could be inferred by the content, or by a cast() operator where explicit conversion is required. If I'm not mistaken, these suffixes were created to get _away_ from the casts ;) |
November 11, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | Kris wrote: > This is the long standing mishmash between character literal > arguments and parameters of type char[], wchar[], and/or dchar[]. > Character literals don't really have a "solid" type ~ the compiler > can, and will, convert between wide and narrow representations on the > fly. Compared to the bit thing I recently "bitched" about, this, IMHO, is an issue one can accept better. :-) It is a problem for small example programs. Larger programs tend to (and IMHO should) have wrappers anyhow: void logwrite(char[] logfile, char[] entry) { std.stream.Stream.write(logfile, entry) } > BTW; the correct thing happens when not using literals. > For example, the following operates intuitively: > > char[] msg = "I am a char[], dammit!"; write (msg); Hmm, Kris's comment above gives me an idea for a _very_ easy fix for this in Phobos: Why not change Phobos void write ( char[] s) {.....}; void write (wchar[] s) {.....}; void write (dchar[] s) {.....}; into void _write ( char[] s) {.....}; void _write (wchar[] s) {.....}; void _write (dchar[] s) {.....}; void write (char[] s) {_write(s)}; I think this would solve the issue with string literals as discussed in this thread. Also, overloading would not be hampered. And, those who really _need_ types other than the 8 bit chars, could still have their types work as usual. (( I also had 2 more lines void writeD (wchar[] s) {_write(s)}; void writeW (dchar[] s) {_write(s)}; above, but they're actually not needed, based on the assumption that the compiler is smart enough to not make redundant char type conversions, which I believe it is. -- And if not, then the 2 lines should be included. )) > To /patch/ around this problem, literals may be now be suffixed with > a type-identifier, including 'c', 'w', and 'd'. Thus, the above > example will compile when you do the following: > > write ( "I am a char[], dammit!" c ); > > I, for one, think this is silly. To skirt the issue, APIs end up > being written as follows: > > void write (char[]); void writeW (wchar[]); void writeD (dchar[]); > > Is that redundant, or what? Well, it's what Phobos is forced to do in > the Stream code (take a look). The error you ran into appears to be a > situation where Walter's own code (std.file) bumps into this |
November 11, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> jicman wrote:
>
>> So, I have this complicated piece of code:
>>
>> |import std.file;
>> |import std.stream;
>> |int main()
>> |{
>> | File log = new File("myfile.txt",FileMode.Out);
>> | log.write("this is a test");
>> | log.close();
>> | return 1;
>> |}
>>
>> and I try to compile it, I get,
>>
>> |ftest.d(6): function std.stream.Stream.write called with argument types:
>> | (char[14])
>> |matches both:
>> | std.stream.Stream.write(char[])
>> |and:
>> | std.stream.Stream.write(wchar[])
>>
>> Shouldn't it just match "std.stream.Stream.write(char[])"?
>
>
> The problem is that literal string literals can be implicitly converted to char, wchar, and dchar strings. To fix the overload resolution problem, try this:
>
> log.write( "this is a test"c );
>
> the 'c' indicates that the above is a char string.
I just posted a "nice" fix on this thread. But it seems overkill (and brittle), if one assumes this is just a problem with string literals!
_If_ it is true that this "problem" exists only with string literals, then it should be even easier to fix!
The compiler knows (or at least _should_ know) the character width of the source code file. Now, if there's an undecorated string literal in it, then _simply_assume_ that is the _intended_ type of the string!
(( At this time opponents will say "what if the source code file gets converted into another character width?" -- My answer: "Tough, ain't it!", since there's a law against gratuituous mucking with source code. ))
So, implicitly just assume the source code literal character width.
The '"c' does _not_ exist so the compiler can force you to state the obvious. It's there so you _can_ be explicit _when_ it really matters to you.
---
Oh, and if we want to be real fancy, we could also have a pragma stating the default for character literals!
And when the pragma is not used, then assume based on the source.
|
November 11, 2005 Re: Stream and File understanding. | ||||
---|---|---|---|---|
| ||||
Posted in reply to jicman | In article <dl0hja$2aal$1@digitaldaemon.com>, jicman says... > >So, I have this complicated piece of code: > >|import std.file; >|import std.stream; >|int main() >|{ >| File log = new File("myfile.txt",FileMode.Out); >| log.write("this is a test"); >| log.close(); >| return 1; >|} Also note one thing though: Stream.write() will write the string in binary format, ie. it will write a binary int with the length, and then the string. If you want a plain ASCII file, which is probably what you want in a log file, you should use Stream.writeString(), or Stream.writeLine() which inserts a line break. Or you can use writef/writefln for more advanced formatting. If you already knew this then disregard this post ;-) Nick |
Copyright © 1999-2021 by the D Language Foundation