Question about Ruby implementation

I’ve been poking around the Ruby internals, trying to understand the
black magic that makes the whole thing run. :slight_smile: I think I finally
understand the garbage collection stuff (and how it determines the roots
from the stack and registers), but I have a question now about some of
the macros I’ve seen: why do some macros wrap their contents in a “do {
… } while(0)”? Is this preferable to simply wrapping them in curly
braces ("{…}")? Is it simply a matter of matz’s programming style, or
is there some subtler issue in effect here?

A few macros that do this (for curious persons to reference) are
JUMP_TAG (in eval.c) and RUBY_CRITICAL (in rubysig.h), though there are
several others.

Thanks! (And if there is a more appropriate list for posting questions
regarding the implementation of Ruby, please direct me there. Thanks
again!)

···


Jamis Buck
jgb3@email.byu.edu

ruby -h | ruby -e ‘a=[];readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a << r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

It’s good style in general. Consider

if (something)
MACRO;

and

if (something)
MACRO;
else
puts(“hello”);

With just {}'s around the macro, the second case wouldn’t compile
(because of the semicolon).

Cheers

Dave

···

On Dec 29, 2003, at 15:54, Jamis Buck wrote:

why do some macros wrap their contents in a “do { … } while(0)”?
Is this preferable to simply wrapping them in curly braces (“{…}”)?
Is it simply a matter of matz’s programming style, or is there some
subtler issue in effect here?

Hi,

[…] I have a question now about some of
the macros I’ve seen: why do some macros wrap their contents in a “do {
… } while(0)”? Is this preferable to simply wrapping them in curly
braces (“{…}”)? Is it simply a matter of matz’s programming style, or
is there some subtler issue in effect here?

It’s a ‘C’ language idiom. It makes a terminating semi-colon
a required part of the syntax, which helps avoid mistakes
with the one-liner form of (for instance) if/else statements,
and such.

#define THING1 {blah()}
#define THING2 do{blah()}while(0)

if (rand() & 1)
THING1();
else
THING2();

…note problem with THING1() usage, given the extraneous
semi-colon…

HTH,

Regards,

Bill

···

From: “Jamis Buck” jgb3@email.byu.edu

Dave Thomas wrote:

It’s good style in general. Consider

if (something)
MACRO;

and

if (something)
MACRO;
else
puts(“hello”);

With just {}'s around the macro, the second case wouldn’t compile
(because of the semicolon).

Cheers

Dave

Yah, I understand that, I think. But why have MACRO wrap its contents
in a “do{…}while(0)”, instead of just “{…}”? In other words, is
there a compelling reason to do this:

#define MACRO(x)
do {
x
} while(0)

instead of this:

#define MACRO(x)
{
x
}

I’m just curious – if it just comes down to a personal preference
thing, that’s fine. But if there is a good reason for doing one over
the other, I’d like to know. Thanks. :slight_smile:

···


Jamis Buck
jgb3@email.byu.edu

ruby -h | ruby -e ‘a=;readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a << r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

Bill Kelly wrote:

It’s a ‘C’ language idiom. It makes a terminating semi-colon
a required part of the syntax, which helps avoid mistakes
with the one-liner form of (for instance) if/else statements,
and such.

#define THING1 {blah()}
#define THING2 do{blah()}while(0)

if (rand() & 1)
THING1();
else
THING2();

…note problem with THING1() usage, given the extraneous
semi-colon…

Perfect – that’s what I was looking for. That makes perfect sense.
Thanks!

Reading through this stuff is humbling… I once considered myself a
pretty good C programmer, but puzzling out some of the stuff the
interpreter is doing has been very educational.

···


Jamis Buck
jgb3@email.byu.edu

ruby -h | ruby -e ‘a=;readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a << r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

See above… Compile it in your head with just the braces…

Dave

···

On Dec 29, 2003, at 16:22, Jamis Buck wrote:

Dave Thomas wrote:

if (something)
MACRO;
else
puts(“hello”);

With just {}'s around the macro, the second case wouldn’t compile
(because of the semicolon).
ah, I understand that, I think. But why have MACRO wrap its contents
in a “do{…}while(0)”, instead of just “{…}”? In other words, is
there a compelling reason to do this:

It’s good style in general. Consider
Yah, I understand that, I think. But why have MACRO wrap its contents
in a “do{…}while(0)”, instead of just “{…}”? In other words, is
there a compelling reason to do this:

#define MACRO(x)
do {
x
} while(0)

instead of this:

#define MACRO(x)
{
x
}

no one prefers this - some compilers actually generate code for the
do-while (which is incredible…), the reason is that braces used in the
second way isn’t standard in C89 (if i’m not mistaken) or at least not
supported by all compilers. A way would be to use another macro that
would encapsulate this stuff, as GLib does provide.
nikolai

···


::: name: Nikolai Weibull :: aliases: pcp / lone-star / aka :::
::: born: Chicago, IL USA :: loc atm: Gothenburg, Sweden :::
::: page: www.pcppopper.org :: fun atm: gf,lps,ruby,lisp,war3 :::
main(){printf(&linux[“\021%six\012\0”],(linux)[“have”]+“fun”-97);}