already used in a 'child' scope to denote something else

  • Thread starter valentin tihomirov
  • Start date
B

Ben Voigt [C++ MVP]

valentin tihomirov said:
And what is the point if not using the language you must to use? The idea
to stop doing anything is the development of the popular idea that all
possible hinderances increase safety.





I always told I do not like the hinderances that protect me doing sensable
things, that "protect" me from going simply, easily, naturally,
strightforwardly, directy.

<sarcasm>
C# is designed with human resources in mind, not the programmer. With C#,
you guarantee that no code contains features that your ubiquitous "person
with C# programming on their resume" can't understand. This drives down the
maximum salary which can be earned by a C# progammer, because any time the
employee asks too much, HR can just replace them.

The way C# accomplishes this is by using language restrictions to drive
everyone into the mold of writing code "the way".

Don't like it, use Perl instead, where the motto is "There's more than one
way to do it".
</sarcasm>
 
J

Jon Skeet [C# MVP]

valentin tihomirov said:
And what is the point if not using the language you must to use? The idea to
stop doing anything is the development of the popular idea that all possible
hinderances increase safety.

What's forcing you to use C#? Even if you're using it professionally, I
suspect there are plenty of jobs around using any *reasonably*
mainstream language these days.
I always told I do not like the hinderances that protect me doing sensable
things, that "protect" me from going simply, easily, naturally,
strightforwardly, directy.

I don't think adding "goto" very occasionally is really hindering you
hugely, is it? At the same time, it's protecting everyone from
*accidental* fallthrough, which as I say happens a lot more often than
deliberate fallthrough, in my experience.
 
J

Jon Skeet [C# MVP]

valentin tihomirov said:
Finally in the constructor?

You can use finally in constructors, certainly.
The constructors are ubiquitous but they must rollback the construction
in a case of error.

Well, you can't roll back the creation of the object, but you could
certainly use finally (along with a success flag) to roll back any
resources acquired.
You cannot use finally
therefore. You could use the except. But it is silly to duplicate the code,
which must be supplied in destructor.

Who said anything about requiring a destructor? Such things don't even
exist in C# (well, from C# 2 onwards - finalizers used to be called
destructors).

I can't remember the last time I needed a finalizer - they're very
rare.
So, neither 'try' nor 'finally'
replace the seek for code entry point. They rather compliment it. I tried to
explain these considerations in my unfinished blogg
http://valjok.blogspot.com/2007/05/rollbacks-destructors-for-successfully.html .
Unfortunately, C# designers abridged the technique to jump at code starting
point making this my technique ugly.

Ick - macros as well. I can't say I'm thinking "simple and natural"
here... It also doesn't seem to be addressing any problem I can
remember having.
 
V

valentin tihomirov

Don't like it, use Perl instead, where the motto is "There's more than one
way to do it".

Firstly, I never asked for many wasy of doing everything. I asked for direct
ways from which I should not be protected. Secondly, these are designers who
chose the tools. And since the disigners are the managers they choose the
mainstream dictated by Microsoft. Peahaps, there will be a chance to check
J#, which should have a fundamental design advantage over the C feature to
pile everything into one global scope-- Java allows declaration of objects
(classes, code) in the local scope where it is used.
 
V

valentin tihomirov

You can use finally in constructors, certainly.

Who tells the contrary?


Well, you can't roll back the creation of the object, but you could
certainly use finally (along with a success flag) to roll back any
resources acquired.

Creation is rolled back by exception. If constructor returns an exception,
the object is not created. Again, constructor is used to allocate resources.
It is nonsense to use finally to unconditionally release the resourses you
need to allocate. You do not want to use finally, therefore. To rollback the
allocated resources in the case of error, the 'catch' is used. Again,
neither 'catch' nor 'finally' replace the facility to jump to a beginning of
code.


Who said anything about requiring a destructor? Such things don't even
exist in C# (well, from C# 2 onwards - finalizers used to be called
destructors).

I can't remember the last time I needed a finalizer - they're very
rare.


If GC does all the deallocation for you means you do not allocate anything
besides memory. You have no need to create a destructor.


Ick - macros as well. I can't say I'm thinking "simple and natural"
here... It also doesn't seem to be addressing any problem I can
remember having.

Wrapping the function invokations by macros, as I do, reduces the code
amount multiple times (increasing readability accordingly). You cannot
invoke 'return' from inside a result checking function to cancel function
execution in case of error simulating excetpion handling -- you should
generate the code. Effectively, such use of macros is C fulfills the job of
exceptions in OOP languages.
 
B

Ben Voigt [C++ MVP]

valentin tihomirov said:
Finally in the constructor? The constructors are ubiquitous but they must
rollback the construction in a case of error. You cannot use finally
therefore. You could use the except. But it is silly to duplicate the
code, which must be supplied in destructor. So, neither 'try' nor
'finally' replace the seek for code entry point. They rather compliment
it. I tried to explain these considerations in my unfinished blogg
http://valjok.blogspot.com/2007/05/rollbacks-destructors-for-successfully.html .
Unfortunately, C# designers abridged the technique to jump at code
starting point making this my technique ugly.

Your technique is far inferior to the accepted methods. As you say, it
can't work in C# (no macros among other reasons). And in C++, RAII provides
for centralized cleanup in an automatic, reusable, easy-to-follow fashon.

With C++/CLI supporting stack semantics for IDisposable objects, it is the
language of choice for deterministic destruction.

About the closest you can come with C# is:

struct Rollback : IDisposable
{
private LinkedList<IDisposable> resources;
public Rollback(IDisposable first) {
resources = new LinkedList<IDisposable>;
resources.Add(first);
}
public Rollback(Rollback other)
{
resources = other.resources;
other.resources = null;
}
public void Add(IDisposable resource)
{
resources.Add(resource);
}
void IDisposable.Dispose()
{
if (resources != null) {
foreach (IDisposable resource in resources) resource.Dispose();
}
}
}

Rollback components;

// in constructor
using (Rollback rollback = new Rollback(fs = new FileStream(...))) {
fs.Open(...);
rollback.Add(ev = new Event(...));
TrackEvent(ev);

...

components = new Rollback(rollback);
}

// in Dispose method
components.Dispose();


It's not very pretty, and it's hardly automatic, but it does ensure
subobjects are properly Disposed even if an exception occurs. Of course,
all the cleanup code belongs in the subobject Dispose, so it is reusable.
You still have to remember to assign components before you return, though.
 
B

Ben Voigt [C++ MVP]

valentin tihomirov said:
Who tells the contrary?




Creation is rolled back by exception. If constructor returns an exception,
the object is not created. Again, constructor is used to allocate
resources.

In .NET, the object is "alive" before any user constructor code starts
running, and has the ultimate runtime type associated. This is why calls to
virtual functions go directly to the most derived type. This also means a
finalizer is called, even if an exception was thrown during construction.
 
V

valentin tihomirov

It's not very pretty, and it's hardly automatic, but it does ensure
subobjects are properly Disposed even if an exception occurs. Of course,
all the cleanup code belongs in the subobject Dispose, so it is reusable.
You still have to remember to assign components before you return, though.

You build a list of functions to execute. In this you approach you simulate
the code rather than execute it. I entailed the rollback as an example of
where you may need to jump to a beginning of code to execute. The code
executes till the end. The starting point may vary . The possible entry
points are marked by lables. Selecting the label by switch was a natural way
to jump to the code entry point.
 
B

Ben Voigt [C++ MVP]

valentin tihomirov said:
You build a list of functions to execute. In this you approach you
simulate

I'm afraid it's not even that efficient. It's a list of interfaces, each of
which contains the function pointer, so there's an extra level of
indirection. The JIT has no opportunity to inline or anything. That's why
C++ automatic destruction of member objects and objects with local scope is
so far superior.
the code rather than execute it. I entailed the rollback as an example of
where you may need to jump to a beginning of code to execute. The code
executes till the end. The starting point may vary . The possible entry
points are marked by lables. Selecting the label by switch was a natural
way to jump to the code entry point.

switch-controlled construction and destruction are perfectly valid in C and
some C++ environments which don't support exceptions. C# has exceptions
though, and your method looks incompatible with exceptions, even if it
didn't suffer from so many other problems.
 
J

Jon Skeet [C# MVP]

valentin tihomirov said:
Creation is rolled back by exception. If constructor returns an exception,
the object is not created.

That's simply not true. In most cases the created object is then
eligible for garbage collection, but that's not necessarily the case.
Indeed, it can't be, because the constructor could have assigned
"this" to a static variable. Consider the following program:

using System;

class Test
{
int i;

static Test foo;

Test()
{
i = 10;
foo = this;
throw new Exception();
}

static void Main()
{
try
{
new Test();
}
catch {}
Console.WriteLine (foo.i);
}
}

Please explain how the above code prints "10" if object creation is
rolled back when a constructor throws an exception.
Again, constructor is used to allocate resources.
It is nonsense to use finally to unconditionally release the resourses you
need to allocate.

Hence "along with a success flag".
You do not want to use finally, therefore.

No, you don't want to use a finally and rollback *unconditionally*.
Just keep a single boolean flag to say whether or not the whole
operation succeeded, and make each finally block check it. Simple.
If GC does all the deallocation for you means you do not allocate anything
besides memory. You have no need to create a destructor.

I use plenty of non-memory resources, but don't rely on the GC to
release them - I use the IDisposable pattern.
Wrapping the function invokations by macros, as I do, reduces the code
amount multiple times (increasing readability accordingly). You cannot
invoke 'return' from inside a result checking function to cancel function
execution in case of error simulating excetpion handling -- you should
generate the code. Effectively, such use of macros is C fulfills the job of
exceptions in OOP languages.

The use of macros has made life incredibly painful for millions of
developers, which is why macros don't tend to be in modern languages.
 
V

valentin tihomirov

Please explain how the above code prints "10" if object creation is
rolled back when a constructor throws an exception.

Because you do not roll back the assignment.

Hence "along with a success flag".


No, you don't want to use a finally and rollback *unconditionally*.
Just keep a single boolean flag to say whether or not the whole
operation succeeded, and make each finally block check it. Simple.

Peahaps, the try-catch is in your list of discouraged constructrions along
with goto. That is why you prefer finally with a flag instead of the
construct, which intentionally intorduced to take action in case of error.


I use plenty of non-memory resources, but don't rely on the GC to
release them - I use the IDisposable pattern.

Which is a destructor. I told nothing about a need to use finalizers.

The use of macros has made life incredibly painful for millions of
developers, which is why macros don't tend to be in modern languages.

Improperly, unconsciously applied hammer can be even more painful and
dangerous. Macros are code generators. Using them greatly reduces amount of
code (program redability). The alternative of not using them in C is loads
of code. You can live without them in OOP languages because we have
exceptions supported at language level. Nevertheless, occasionally, the lack
of macros is observed. For instance, in logging
public void log (int severity, str message) {
if (severity >= debug_level)
print(message);
}

you have a lot of log function invocations. If the debug level is high
(normally, you log only errors), the function will do nothing. According to
Log4j project, the most logging time is spent on constructing the text
message. So, you construct a message to discard it. And the function is
public, so it cannot be inlined. In Delphi, which lacks ternary operators, I
also felt the lack of macros to implemement it. However in C, avoiding
macros is huge waste of labour and storage resourses.
 
J

Jon Skeet [C# MVP]

valentin tihomirov said:
Because you do not roll back the assignment.

But if the object itself were "uncreated" then that wouldn't make any
odds.

The object is clearly still alive, contrary to your previous statement.
Peahaps, the try-catch is in your list of discouraged constructrions along
with goto. That is why you prefer finally with a flag instead of the
construct, which intentionally intorduced to take action in case of error.

I'm perfectly happy to use try/catch where appropriate. Using try/catch
and then rethrowing is another alternative to using try/finally.

So, now we have two different ways, neither of which require using
fallthrough/"goto" in a switch/case statement. So much for it being
indispensible.
Which is a destructor. I told nothing about a need to use finalizers.

No, IDisposable is *not* a destructor. I believe that there's some
relationship in C++/CLI between IDisposable and destructors, but in C#
(post v1) there is no such thing as a destructor. In particular, there
is nothing which will automatically be called in C# at the end of the
scope of a variable.
Improperly, unconsciously applied hammer can be even more painful and
dangerous. Macros are code generators. Using them greatly reduces amount of
code (program redability).

You seem to take it for granted that reducing the amount of code
improves code readability. Quite often I'll find that the most readable
form of some code is *not* the shortest.
The alternative of not using them in C is loads
of code. You can live without them in OOP languages because we have
exceptions supported at language level. Nevertheless, occasionally, the lack
of macros is observed. For instance, in logging
public void log (int severity, str message) {
if (severity >= debug_level)
print(message);
}

you have a lot of log function invocations. If the debug level is high
(normally, you log only errors), the function will do nothing. According to
Log4j project, the most logging time is spent on constructing the text
message. So, you construct a message to discard it. And the function is
public, so it cannot be inlined. In Delphi, which lacks ternary operators, I
also felt the lack of macros to implemement it. However in C, avoiding
macros is huge waste of labour and storage resourses.

Perhaps you haven't seen the Conditional attribute.

using System;
using System.Diagnostics;

class Test
{
static void Main()
{
PrintMe(ConstructMessage());
}

static string ConstructMessage()
{
Console.WriteLine ("Constructing message");
return "This could have taken a long time to build.";
}

[Conditional("TESTING")]
static void PrintMe(string message)
{
Console.WriteLine(message);
}
}

Compile it with the "TESTING" symbol defined, and it'll print the two
strings. Compile it without the "TESTING" symbol defined, and nothing
will be printed.
 
V

valentin tihomirov

But if the object itself were "uncreated" then that wouldn't make any
odds. The object is clearly still alive, contrary to your previous
statement.

Yes, I have overlooked the posibility to establish a reference to an object,
construction of which fails. However, I have never claimed there is a need
to "uncreate" an object. All what is realliy needed is to free allocated
resources. Both in destructor, which is called by user, and in constructor,
which destroys partially created object in case of exception.



I'm perfectly happy to use try/catch where appropriate. Using try/catch
and then rethrowing is another alternative to using try/finally.

So, now we have two different ways, neither of which require using
fallthrough/"goto" in a switch/case statement. So much for it being
indispensible.


I repeat third time: the catch/finally replaces C macros. It does not
replace the jumping to entry point of code.

In C I had:
void destroy(level) {
switch(level) {
last: free(last);
res3: free(res3);
res2: free(res2);
res1: free(res1);
}
}
void destroy() {
destroy(last);
}
void create() {
CHECK(resource1 = allocate1()); rollback_label = resource1;
CHECK(resource2 = allocate2()); rollback_label = resource2;
CHECK(resource3 = allocate3()); rollback_label = resource3;
CHECK(last = allocatelast()); rollback_label = last;
}



In OOP you have:

void destroy(level) {

switch(level) {
last: free(last);
res3: free(res3);
res2: free(res2);
res1: free(res1);
}
}
void destroy() {
destroy(last);
}
void create() {
allocate1();
try {
allocate2();
try {
allocate3();
try {
allocate_last();
} catch {
destroy(label3);
throw;
}
} catch {
destroy(label2);
throw;
}
} catch {
destroy(label1);
throw;
}


If you like, you may replace the switch by simulation of code execution as
recommended in another topic branch. But you cannot replace the 'switch' by
the 'catch'.


No, IDisposable is *not* a destructor. I believe that there's some
relationship in C++/CLI between IDisposable and destructors, but in C#
(post v1) there is no such thing as a destructor. In particular, there
is nothing which will automatically be called in C# at the end of the
scope of a variable.

I call a destructor a method which is needed to be called to free allocated
resources regardless of who makes the call.


You seem to take it for granted that reducing the amount of code
improves code readability. Quite often I'll find that the most readable
form of some code is *not* the shortest.

I agree that a bitmap in jpeg form is hard to read/edit but when you have a
common pattern which is repeated 1000 times in a text of program it is not
just easier to read when the pattern is packed in reusable routine, it is
easiter to mantain for reusability reason. I'm sure the redundant approach
based on quich and durty copy-and-paste is a bad practice.

You are free to write
if ((res1 = func1()) != OK) {
log (res1);
destroy(level);
return
}
level = level1;
if ((res2 = func2()) != OK) {
log (res2);
destroy(level);
return
}
level = level2;
....

istead of
CHECK(res1 = func1, level1);
CHECK(res2 = func2, level2);
....

You can even write the multiline monsters
if (func() == true)
{
return true;
}
else
{
return false;
}
As I see everywhere and I have seen "standards" that coerses producing this,
instead of brief and clear: return func();

There is a razor principle, put by Einstain: things must be done as simple
as possible. I know that the really beautiful things are those which have
nothing redundant. Overcomplication is bad design. I beleive the programmers
are undergraduated creatures vocated to produce loads of "sw".

Compile it with the "TESTING" symbol defined, and it'll print the two
strings. Compile it without the "TESTING" symbol defined, and nothing
will be printed.

I have heard of conditional compilation. The problem is however that the
debug level can be changed on the same executable. You cannot avoid code
generation to implement lazy evaluation. The macros check the condition
before passing to the message construction code execution.
 
V

valentin tihomirov

1. He went to home.
2. A gived individual of man sex consciously performed a process of foot
transportation with normal speed in past time towards an object, which
represents a place of permanent resedence of given subject.
 
A

Andre Kaufmann

valentin said:
[...]
I repeat third time: the catch/finally replaces C macros. It does not
replace the jumping to entry point of code.

IMHO C macros are what they are, a simple pattern / instruction replaced
by the preprocessor. As a C++ programmer I can only say macros are evil
(in C++), since they have effects on other source code and are the main
reason why C++ is so slow. Doesn't apply to C directly, however.
In C I had:
void destroy(level) {
switch(level) {
last: free(last);
res3: free(res3);
res2: free(res2);
res1: free(res1);
}
}
void destroy() {
destroy(last);
}
void create() {
CHECK(resource1 = allocate1()); rollback_label = resource1;
CHECK(resource2 = allocate2()); rollback_label = resource2;
CHECK(resource3 = allocate3()); rollback_label = resource3;
CHECK(last = allocatelast()); rollback_label = last;
}

Why not: (Sorry for errors, I'm used more to C++ than C) ?

void* p1 = 0;
void* p2 = 0;
void* p3 = 0;

void destroy()
{
free(p1);
free(p2);
free(p3);
}

bool Alloc(void** p, char* error);
bool create()
{
if (!Alloc(p1), "ALLOC 1") return false;
if (!Alloc(p2), "ALLOC 2") return false;
if (!Alloc(p3), "ALLOC 3") return false;
return true;
}

bool Alloc(void** p, char* error)
{
if (..... error ....)
{
printf("ERROR ALLOCATING: %s\r\n", error);
return false;
}
*p = malloc(100);
return true;
}

Also readable - IMHO, without using macros. Same applies to C#.

[...]
I call a destructor a method which is needed to be called to free allocated
resources regardless of who makes the call.

In C++ there is RAII, which IMHO is the best solution. In C# we have try
/ finally or the using statement.


[...]
You can even write the multiline monsters
if (func() == true)
{
return true;
}
else
{
return false;
}


You could also simply write:

return func();

or:

return DoSomethingOnTrueOrFalse(func());

Or since commonly in this case exceptions are used:

func1();
func2();
func3();

And the error is handled somewhere outside the function block.

As I see everywhere and I have seen "standards" that coerses producing this,
instead of brief and clear: return func();

Only if IMHO you are trying to map one coding style of a language to
another. Sometimes you can't simply map your coding style to another
language, and yes sometimes it's somewhat more complex to express the
same in another language.

Andre
 
V

valentin tihomirov

I repeat third time: the catch/finally replaces C macros. It does not
IMHO C macros are what they are, a simple pattern / instruction replaced
by the preprocessor. As a C++ programmer I can only say macros are evil
(in C++), since they have effects on other source code and are the main
reason why C++ is so slow. Doesn't apply to C directly, however.

Text including is really evelish heretage of asm. It not only makes
compilation slow -- it makes the compiler reports . However, the code
generators are there for a reason. You are free to copy and paste yourself
to "speed up your compilation times".


Also readable - IMHO, without using macros. Same applies to C#.

It is not surprising -- in case of error, you leave resources unreleased.
Furthermore, your allocate prints the message. It is ad-hoc created for your
application. Meantime, "allocating resources" normally means calling system
routine. Moreover, you omit that the macros can check return codes not only
in allocating functions, but also in using the resources:

if (!WriteFile(data1)) {
log(last error writing 1)
return;
}

if (!WriteFile(data1)) {
log(last error writing 2)
return;
}
...

The pattern is obvious and calls for reduction:
WIN32_CHECK(WriteFile(data1), "writing 1");
WIN32_CHECK(WriteFile(data2), "writing 2");


[...]
I call a destructor a method which is needed to be called to free
allocated resources regardless of who makes the call.

In C++ there is RAII, which IMHO is the best solution. In C# we have try /
finally or the using statement.

RAII is the feature allocating resources in the stack? The object you
construct will be destroyed automatically right after the constructor
completes. Happy constructing.


func1();
func2();
func3();

And the error is handled somewhere outside the function block.

Exceptions are not panacea. They do not aholish the normal function return
values. The example was intended to demonstrate "concise vs. inflated"
writing style.

Only if IMHO you are trying to map one coding style of a language to
another. Sometimes you can't simply map your coding style to another
language, and yes sometimes it's somewhat more complex to express the same
in another language.

There is nothing about style mapping. There are guidelines of a company. One
of them is we do not use ternary operators. Instead of
func(cond ? a : b, cond2 ? x : y)
we write
if (cond)
{
if (cond2)
{
func(a, x);
}
else
{
func(a, y);
}
}
else
{
if (cond2)
{
func(b, x);
}
else
{
func(b, y);
}
}

This is a perverse, redundant and thus moderen art.
 
J

Jon Skeet [C# MVP]

valentin tihomirov said:
Yes, I have overlooked the posibility to establish a reference to an object,
construction of which fails. However, I have never claimed there is a need
to "uncreate" an object. All what is realliy needed is to free allocated
resources. Both in destructor, which is called by user, and in constructor,
which destroys partially created object in case of exception.

Again, there's no such term as "destructor" in C#, but yes - the
constructor should clear up all resources if an exception is thrown
during construction. My point was just that the object itself is *not*
automatically "deleted" immediately.
I repeat third time: the catch/finally replaces C macros. It does not
replace the jumping to entry point of code.

Okay - so in the rare situation where I actually have more than one
resource I need to dispose of (heck, it's rare enough that my objects
have member state with *any* disposable resources) I would almost
always be able to tell whether or not the resource had been allocated
using "null". I can't immediately think of a situation where I wouldn't
be able to tell from the state itself whether or not I needed to
release that state.

At that point, it's very easy to write code which does a check-then-
release, check-then-release etc. It's also reasonably easy to make that
exception safe.

As I say though - this is incredibly rare for me.

I call a destructor a method which is needed to be called to free allocated
resources regardless of who makes the call.

Then you're reusing existing and quite specific terminology to cover
similar situations which aren't exactly the same. That's just a recipe
for miscommunication.
I agree that a bitmap in jpeg form is hard to read/edit but when you have a
common pattern which is repeated 1000 times in a text of program it is not
just easier to read when the pattern is packed in reusable routine, it is
easiter to mantain for reusability reason. I'm sure the redundant approach
based on quich and durty copy-and-paste is a bad practice.
You are free to write

<snip straw man>

Hey, I can come up with straw men too: you like short code? Better use
single letter variables everywhere and have all your code on one line,
right?

No, of course not.

There are times when the shortest code is the most readable. There are
plenty of times when it isn't.

Macros can introduce subtle bugs very easily, as well as often being a
nightmare to debug. I for one am glad that C# doesn't have them.
There is a razor principle, put by Einstain: things must be done as simple
as possible. I know that the really beautiful things are those which have
nothing redundant. Overcomplication is bad design. I beleive the programmers
are undergraduated creatures vocated to produce loads of "sw".

So you don't believe there's any situation where longer code can be
more readable than shorter code? We'll have to agree to disagree on
that one.

Here's an example: I don't want everyone who ever reads my code to have
to know all of the operator precedence of C#. I'll assume they know
that * binds tighter than + and basics like that, but nothing *very*
complicated - so if there's anything which might introduce confusion in
a reader's mind, I'll put brackets in to make it explicit.

Those brackets are redundant, in that the compiler certainly doesn't
need them - but they help readability.
I have heard of conditional compilation. The problem is however that the
debug level can be changed on the same executable. You cannot avoid code
generation to implement lazy evaluation. The macros check the condition
before passing to the message construction code execution.

I don't understand what you want to be able to do which I didn't just
demonstrate in the example. In my example the message construcvtion
code was not executed - isn't that exactly what you wanted?
 
J

Jon Skeet [C# MVP]

valentin tihomirov said:
1. He went to home.
2. A gived individual of man sex consciously performed a process of foot
transportation with normal speed in past time towards an object, which
represents a place of permanent resedence of given subject.

On the other hand:

Eschew obfuscation.
 
A

Andre Kaufmann

valentin said:
Text including is really evelish heretage of asm. It not only makes
compilation slow -- it makes the compiler reports . However, the code

Yes, but macros are often misused. If you look at some code

MyMacro(Function, "some text")

you won't know how this code will expand. If it would be a function one
would know that "Function" and "some text" are arguments.
Also if you are debugging you will see only the macro, not the expanded
code.

Also for most of external or internal IDE tools it's hard to parse (C
style) macros.
generators are there for a reason. You are free to copy and paste yourself
to "speed up your compilation times".

In C macros may be O.K. In C++ the compiler is forced to compile every
header file again and again, only because a macro could be redefined and
expand completely to different code. This has nothing to do with copy /
paste
It is not surprising -- in case of error, you leave resources unreleased.

Don't think so why should resources be unreleased ?
Furthermore, your allocate prints the message. It is ad-hoc created for your
application. Meantime, "allocating resources" normally means calling system
routine. Moreover, you omit that the macros can check return codes not only
in allocating functions, but also in using the resources:

if (!WriteFile(data1)) {
log(last error writing 1)
return;
}

if (!WriteFile(data1)) {
log(last error writing 2)
return;
}
...

The pattern is obvious and calls for reduction:
WIN32_CHECK(WriteFile(data1), "writing 1");
WIN32_CHECK(WriteFile(data2), "writing 2");

Yes, but what about a function: (in C)

void WIN32_CHECK(HRESULT value, char* log)
{
if (value != S_OK) ....
}

The code would be the same. The only difference would be that the macro
may expand to different code in release / debug versions. Which is
addressed in C# by conditional compilation, which IMHO is better, since
you can ship your application as both - debug and release in a single
executable.


[...]
RAII is the feature allocating resources in the stack? The object you
construct will be destroyed automatically right after the constructor
completes. Happy constructing.

Not only. It means (abstractly) that allocations and deallocations are
done in the destructor automatically.
If you embed objects in C++ in another object, they are destroyed too if
the parent object is destroyed.

You simply don't have to care about allocation / deallocation !!!

Exceptions are not panacea. They do not aholish the normal function return
values. The example was intended to demonstrate "concise vs. inflated"
writing style.


Yes. Exceptions cannot replace and shouldn't replace function return
values.
[...]
There is nothing about style mapping. There are guidelines of a company. One
of them is we do not use ternary operators. Instead of
func(cond ? a : b, cond2 ? x : y)
we write
if (cond)
{
if (cond2)
{
func(a, x);
}
else
{
func(a, y);
}

[....]
This is a perverse, redundant and thus moderen art.

It's not modern, but IMHO perhaps too much expanded.

The code above could be rewritten for example:

int v1, v2;
if (cond) v1 = a; else v1 = b;
if (cond2) v2 = x; else v2 = y;
func(v1, v2);

Andre
 
V

valentin tihomirov

In C macros may be O.K. In C++ the compiler is forced to compile every
header file again and again, only because a macro could be redefined and
expand completely to different code. This has nothing to do with copy /
paste

If you do not want the compiler to unwind the macros generating C code, you
can avoid using macros and generate the code by your hands.


Don't think so why should resources be unreleased ?

They should not be unreleased. They must be released. And in your example
you forget todo so leaving them allocated (leaked).


Yes, but what about a function: (in C)

void WIN32_CHECK(HRESULT value, char* log)
{
if (value != S_OK) ....
}
The code would be the same. The only difference would be that the macro
may expand to different code in release / debug versions. Which is
addressed in C# by conditional compilation, which IMHO is better, since
you can ship your application as both - debug and release in a single
executable.

Don't you understand that you need to exit the function in case of error.
And this is the function which invokes the checking routine rather than the
checking routine. You cannot raise an exception in C/C++ in the ellipsys.



[...]
RAII is the feature allocating resources in the stack? The object you
construct will be destroyed automatically right after the constructor
completes. Happy constructing.

Not only. It means (abstractly) that allocations and deallocations are
done in the destructor automatically.
If you embed objects in C++ in another object, they are destroyed too if
the parent object is destroyed.

You simply don't have to care about allocation / deallocation !!!

Abstragating from reality we can speak about anything. But the issue was
rolling back resourses in constructors in case of errors. The pattern

resourse = allocate();
try {
use(resourse);
} finally {
free(resourse);
}

where allocation and deallocation occurs in one routine is not applicable.

[...]
There is nothing about style mapping. There are guidelines of a company.
One of them is we do not use ternary operators. Instead of
func(cond ? a : b, cond2 ? x : y)
we write
if (cond)
{
if (cond2)
{
func(a, x);
}
else
{
func(a, y);
}
[....]
This is a perverse, redundant and thus moderen art.

It's not modern, but IMHO perhaps too much expanded.

The code above could be rewritten for example:

int v1, v2;
if (cond) v1 = a; else v1 = b;
if (cond2) v2 = x; else v2 = y;
func(v1, v2);

You have omited the braces -- one per line -- the authority demands :) The
important thing is that the code pile upers do not understand that the
ternary operator means you want to assign one or another value depending on
a codition. When you write the redundant code: "if (cond) v1 = a; else v1 =
b;" (variable to be assigned is specified twice), you may run into
inconsistency: "v1 = a; else v2 = b;". If you give a user a button telling
"never push it", they will one day. I suspect that the ternary op expands to
if-then-else at machine code level. However, the good design does not
exhibit any redundant parts.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top