Jump to page: 1 2 3
Thread overview
pu$€le
Jul 18, 2010
strtr
Jul 18, 2010
strtr
Re: pu$�le
Jul 18, 2010
Jonathan M Davis
Jul 18, 2010
strtr
Jul 18, 2010
Jonathan M Davis
Jul 18, 2010
strtr
Jul 18, 2010
Jonathan M Davis
Jul 18, 2010
strtr
Re: pu$�le
Jul 18, 2010
Jonathan M Davis
Jul 18, 2010
strtr
Jul 18, 2010
Jonathan M Davis
Jul 18, 2010
strtr
Jul 18, 2010
Jonathan M Davis
Jul 18, 2010
Jonathan M Davis
Re: pu$�le
Jul 18, 2010
bearophile
Jul 18, 2010
Jonathan M Davis
Re: pu$�le
Jul 18, 2010
strtr
Re: pu$ᅵle
Jul 18, 2010
Jonathan M Davis
Re: pu$�le
Jul 18, 2010
strtr
Re: pu$ᅵle
Jul 18, 2010
Jonathan M Davis
Re: pu$�le
Jul 19, 2010
strtr
Re: pu$ᅵle
Jul 19, 2010
Jonathan M Davis
Re: pu$�le
Jul 18, 2010
Jonathan M Davis
Jul 18, 2010
strtr
Jul 19, 2010
strtr
Jul 19, 2010
Jonathan M Davis
Jul 19, 2010
strtr
Jul 19, 2010
Jonathan M Davis
Jul 19, 2010
strtr
Jul 19, 2010
Jonathan M Davis
July 18, 2010
What does this program print?

----
const char[] coins = `$€`;

void main()
{
	writef(`I made `);
	int stash = 0;
	scope(exit) writefln(stash,`.`);
	scope(failure) stash--;

	foreach(coin;coins)
	{
		scope(exit) stash++;
		scope(success) stash++;
		scope(failure) stash--;
		scope(failure) continue;
		writef(coin);
	}
}
----
July 18, 2010
That is [dollar sign, euro sign]

The reason I post it is because I expected the stash to be 3 lower.
July 18, 2010
On Saturday 17 July 2010 18:59:18 strtr wrote:
> That is [dollar sign, euro sign]
> 
> The reason I post it is because I expected the stash to be 3 lower.

Well, if I replace writef with write, I get

I made $€8.

If I leave in the writef though, I get this error:

/home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/stdio.d(623):
Error: static assert  "You must pass a formatting string as the first argument to
writef or writefln. If no formatting is needed, you may want to use write or
writeln."
/home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/stdio.d(1442):
instantiated from here: writef!(const(char))
t.d(18):        instantiated from here: writef!(const(char))

I'm not quite sure why you're using writef here since writef requires a string as its first argument, and you're passing it something other than a string as the first argument.

- Jonathan M Davis
July 18, 2010
On Saturday 17 July 2010 18:59:18 strtr wrote:
> That is [dollar sign, euro sign]
> 
> The reason I post it is because I expected the stash to be 3 lower.

As to why it's not working right, change th foreach loop to this:

foreach(dchar coin; coins)
{
...
}

Otherwise, instead of looping over each code point, you're looping over each code unit. char[] and string are encoded in utf-8, so each char is a code unit, and 1 - 4 code units are put together to form a code point, which is what you'd normally think of as a character.

The dollar sign takes one code unit in utf-8, but the euro sign takes 3. So, you're looping 4 times instead of 2. By specifying dchar, the compiler automatically processes the code units correctly to make it so that you loop over each code point (i.e. character) rather than each code unit (i.e. char).

You should pretty much never deal with each individual char or wchar in a string or wstring. Do the conversion to dchar or dstring if you want to access individual characters. You can also use std.utf.stride() to iterate over to the next code unit which starts a code point, but you're still going to have to make sure that you convert it to a dchar to process it properly. Otherwise, only ASCII characters will work right (since they fit in a single code unit). Fortunately, foreach takes care of all this for is if we specify the element type as dchar.

As for why it's 4 rather than 2 in the corrected version (or 8 instead of 4 in the incorrect version), that's because you have both scope(exit) and scop(success) there. Both will be run, so both will increment stash, and you get double the increments that you seem to be expecting.

- Jonathan M Davis
July 18, 2010
== Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> On Saturday 17 July 2010 18:59:18 strtr wrote:
> > That is [dollar sign, euro sign]
> >
> > The reason I post it is because I expected the stash to be 3 lower.
> As to why it's not working right, change th foreach loop to this:
> foreach(dchar coin; coins)
> {
> ...
> }
> Otherwise, instead of looping over each code point, you're looping over each
> code unit. char[] and string are encoded in utf-8, so each char is a code unit,
> and 1 - 4 code units are put together to form a code point, which is what you'd
> normally think of as a character.
> The dollar sign takes one code unit in utf-8, but the euro sign takes 3. So,
> you're looping 4 times instead of 2. By specifying dchar, the compiler
> automatically processes the code units correctly to make it so that you loop
> over each code point (i.e. character) rather than each code unit (i.e. char).
> You should pretty much never deal with each individual char or wchar in a string
> or wstring. Do the conversion to dchar or dstring if you want to access
> individual characters. You can also use std.utf.stride() to iterate over to the
> next code unit which starts a code point, but you're still going to have to make
> sure that you convert it to a dchar to process it properly. Otherwise, only
> ASCII characters will work right (since they fit in a single code unit).
> Fortunately, foreach takes care of all this for is if we specify the element
> type as dchar.
> As for why it's 4 rather than 2 in the corrected version (or 8 instead of 4 in
> the incorrect version), that's because you have both scope(exit) and
> scop(success) there. Both will be run, so both will increment stash, and you get
> double the increments that you seem to be expecting.
> - Jonathan M Davis

Wasn't it obvious the puzzle was about exceptions, with half of the lines being
scope guards and all?
Part of the puzzle is the realization that chars aren't code points but code units.
The other part is understanding the order of scope guard execution.
I'm not sure whether the linux or the windows version of writef is the correct
one, but here I get a nice utf-exception. (Or did you maybe use D2? if not then we
have a discrepancy bug)
July 18, 2010
== Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> On Saturday 17 July 2010 18:59:18 strtr wrote:
> > That is [dollar sign, euro sign]
> >
> > The reason I post it is because I expected the stash to be 3 lower.
> Well, if I replace writef with write, I get
> I made $€8.
> If I leave in the writef though, I get this error:
> /home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/stdi
> o.d(623):
> Error: static assert  "You must pass a formatting string as the first argum
> ent to
> writef or writefln. If no formatting is needed, you may want to use write o
> r
> writeln."
> /home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/stdi
> o.d(1442):
> instantiated from here: writef!(const(char))
> t.d(18):        instantiated from here: writef!(const(char))
> I'm not quite sure why you're using writef here since writef requires a str
> ing
> as its first argument, and you're passing it something other than a string
> as the
> first argument.
> - Jonathan M Davis

Or you have an awesome D emulator in your brain, or you cheated by actually running the code ;P
July 18, 2010
On Saturday 17 July 2010 21:48:30 strtr wrote:
> == Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> 
> > On Saturday 17 July 2010 18:59:18 strtr wrote:
> > > That is [dollar sign, euro sign]
> > > 
> > > The reason I post it is because I expected the stash to be 3 lower.
> > 
> > As to why it's not working right, change th foreach loop to this:
> > foreach(dchar coin; coins)
> > {
> > ...
> > }
> > Otherwise, instead of looping over each code point, you're looping over
> > each code unit. char[] and string are encoded in utf-8, so each char is
> > a code unit, and 1 - 4 code units are put together to form a code point,
> > which is what you'd normally think of as a character.
> > The dollar sign takes one code unit in utf-8, but the euro sign takes 3.
> > So, you're looping 4 times instead of 2. By specifying dchar, the
> > compiler automatically processes the code units correctly to make it so
> > that you loop over each code point (i.e. character) rather than each
> > code unit (i.e. char). You should pretty much never deal with each
> > individual char or wchar in a string or wstring. Do the conversion to
> > dchar or dstring if you want to access individual characters. You can
> > also use std.utf.stride() to iterate over to the next code unit which
> > starts a code point, but you're still going to have to make sure that
> > you convert it to a dchar to process it properly. Otherwise, only ASCII
> > characters will work right (since they fit in a single code unit).
> > Fortunately, foreach takes care of all this for is if we specify the
> > element type as dchar.
> > As for why it's 4 rather than 2 in the corrected version (or 8 instead of
> > 4 in the incorrect version), that's because you have both scope(exit)
> > and scop(success) there. Both will be run, so both will increment stash,
> > and you get double the increments that you seem to be expecting.
> > - Jonathan M Davis
> 
> Wasn't it obvious the puzzle was about exceptions, with half of the lines
> being scope guards and all?
> Part of the puzzle is the realization that chars aren't code points but
> code units. The other part is understanding the order of scope guard
> execution. I'm not sure whether the linux or the windows version of writef
> is the correct one, but here I get a nice utf-exception. (Or did you maybe
> use D2? if not then we have a discrepancy bug)

All I ever use is D2. I have no idea what D1 would be doing differently. In D2, writef(), the "f" is for format or formatted, and you have to have a "format" string like printf would in order for it to work. write() is the version which doesn't require a format string. I am using Linux if that changes anything, but as far as I can tell, you're using writef() incorrectly. In any case, I obviously don't quite get what you're trying to do since (at least in D2), I don't believe that you have any functions in that loop which will every throw an exception. If you were using File's writef() because you were writing to a file, then that would be different. But writef() by itself is to stdout and won't throw.

Now, as you're using D1, that may change things. But you gave no indication that you were using D1. In future questions, you should probably be more specific about that, since I think that most people around here are using D2, and they will likely assume that you're using D2 unless you say otherwise. I certainly did.

- Jonathan M Davis
July 18, 2010
On Saturday 17 July 2010 22:10:07 strtr wrote:
> == Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> 
> > On Saturday 17 July 2010 18:59:18 strtr wrote:
> > > That is [dollar sign, euro sign]
> > > 
> > > The reason I post it is because I expected the stash to be 3 lower.
> > 
> > Well, if I replace writef with write, I get
> > I made $€8.
> > If I leave in the writef though, I get this error:
> > /home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/st
> > di o.d(623):
> > Error: static assert  "You must pass a formatting string as the first
> > argum ent to
> > writef or writefln. If no formatting is needed, you may want to use write
> > o r
> > writeln."
> > /home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/st
> > di o.d(1442):
> > instantiated from here: writef!(const(char))
> > t.d(18):        instantiated from here: writef!(const(char))
> > I'm not quite sure why you're using writef here since writef requires a
> > str ing
> > as its first argument, and you're passing it something other than a
> > string as the
> > first argument.
> > - Jonathan M Davis
> 
> Or you have an awesome D emulator in your brain, or you cheated by actually running the code ;P

Cheated? I thought that you were trying to figure out why the code wasn't doing what you expected it to be doing. So, of course I ran it.

Though, it's more likely that I have an x86 emulator in my brain which can run dmd than that I have a D emulator in my brain if I figured this out in my head, since I gave you the exact error message that dmd does.

- Jonathan M Davis
July 18, 2010
== Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> On Saturday 17 July 2010 21:48:30 strtr wrote:
> > == Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> >
> > > On Saturday 17 July 2010 18:59:18 strtr wrote:
> > > > That is [dollar sign, euro sign]
> > > >
> > > > The reason I post it is because I expected the stash to be 3 lower.
> > >
> > > As to why it's not working right, change th foreach loop to this:
> > > foreach(dchar coin; coins)
> > > {
> > > ...
> > > }
> > > Otherwise, instead of looping over each code point, you're looping over
> > > each code unit. char[] and string are encoded in utf-8, so each char is
> > > a code unit, and 1 - 4 code units are put together to form a code point,
> > > which is what you'd normally think of as a character.
> > > The dollar sign takes one code unit in utf-8, but the euro sign takes 3.
> > > So, you're looping 4 times instead of 2. By specifying dchar, the
> > > compiler automatically processes the code units correctly to make it so
> > > that you loop over each code point (i.e. character) rather than each
> > > code unit (i.e. char). You should pretty much never deal with each
> > > individual char or wchar in a string or wstring. Do the conversion to
> > > dchar or dstring if you want to access individual characters. You can
> > > also use std.utf.stride() to iterate over to the next code unit which
> > > starts a code point, but you're still going to have to make sure that
> > > you convert it to a dchar to process it properly. Otherwise, only ASCII
> > > characters will work right (since they fit in a single code unit).
> > > Fortunately, foreach takes care of all this for is if we specify the
> > > element type as dchar.
> > > As for why it's 4 rather than 2 in the corrected version (or 8 instead of
> > > 4 in the incorrect version), that's because you have both scope(exit)
> > > and scop(success) there. Both will be run, so both will increment stash,
> > > and you get double the increments that you seem to be expecting.
> > > - Jonathan M Davis
> >
> > Wasn't it obvious the puzzle was about exceptions, with half of the lines
> > being scope guards and all?
> > Part of the puzzle is the realization that chars aren't code points but
> > code units. The other part is understanding the order of scope guard
> > execution. I'm not sure whether the linux or the windows version of writef
> > is the correct one, but here I get a nice utf-exception. (Or did you maybe
> > use D2? if not then we have a discrepancy bug)
> All I ever use is D2. I have no idea what D1 would be doing differently. In D2,
> writef(), the "f" is for format or formatted, and you have to have a "format"
> string like printf would in order for it to work. write() is the version which
> doesn't require a format string. I am using Linux if that changes anything, but
> as far as I can tell, you're using writef() incorrectly. In any case, I
> obviously don't quite get what you're trying to do since (at least in D2), I
> don't believe that you have any functions in that loop which will every throw an
> exception. If you were using File's writef() because you were writing to a file,
> then that would be different. But writef() by itself is to stdout and won't
> throw.
> Now, as you're using D1, that may change things. But you gave no indication that
> you were using D1. In future questions, you should probably be more specific
> about that, since I think that most people around here are using D2, and they
> will likely assume that you're using D2 unless you say otherwise. I certainly
> did.
> - Jonathan M Davis
I think I'll start subject tagging my posts: [D1/D2]
std.stdio in D1 doesn't mention a write function and feeding the writef function
an illegal UTF string will result in a UTF exception.
With this information, what do you think the output should be?


July 18, 2010
== Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> On Saturday 17 July 2010 22:10:07 strtr wrote:
> > == Quote from Jonathan M Davis (jmdavisprog@gmail.com)'s article
> >
> > > On Saturday 17 July 2010 18:59:18 strtr wrote:
> > > > That is [dollar sign, euro sign]
> > > >
> > > > The reason I post it is because I expected the stash to be 3 lower.
> > >
> > > Well, if I replace writef with write, I get
> > > I made $€8.
> > > If I leave in the writef though, I get this error:
> > > /home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/
> st
> > > di o.d(623):
> > > Error: static assert  "You must pass a formatting string as the first
> > > argum ent to
> > > writef or writefln. If no formatting is needed, you may want to use wri
> te
> > > o r
> > > writeln."
> > > /home/jmdavis/Downloaded_Files/dmd/dmd2/linux/bin/../../src/phobos/std/
> st
> > > di o.d(1442):
> > > instantiated from here: writef!(const(char))
> > > t.d(18):        instantiated from here: writef!(const(char))
> > > I'm not quite sure why you're using writef here since writef requires a
> > > str ing
> > > as its first argument, and you're passing it something other than a
> > > string as the
> > > first argument.
> > > - Jonathan M Davis
> >
> > Or you have an awesome D emulator in your brain, or you cheated by actual
> ly
> > running the code ;P
> Cheated? I thought that you were trying to figure out why the code wasn't d
> oing
> what you expected it to be doing. So, of course I ran it.
> Though, it's more likely that I have an x86 emulator in my brain which can
> run
> dmd than that I have a D emulator in my brain if I figured this out in my h
> ead,
> since I gave you the exact error message that dmd does.
> - Jonathan M Davis

I don't find it more likely that you have a x86 emulator in your brain which then
ran dmd to compile some code.
I might even think that almost impossible ;P
If you knew the compiler well enough you might be capable of giving that error
message with only the extra knowledge of where your files recite and version and
OS infos.
« First   ‹ Prev
1 2 3