You have a very limited view of the techniques available.

On Aug 3, 10:39 am, Leigh McRae <leigh.mc...@lonedwarfgames.com>
wrote:
> On 8/2/2010 10:49 PM, Bob Kerns wrote:> First of all -- if you want to list 
> the faults of the C language, the
> > preprocessor is very near the top.
>
> Just your opinion.

False:
   "Preprocessor usage should be eliminated."
   -Bjarne Stroustrup, "An Overview of the C++ Programming Language",
page 3, under table "Language-technical rules:"

This concept carried over into the C++ standard committee. Hardly
"just my opinion". It's not removed, because C compatibility is a
higher-priority concern.

> > That's why C++ went to great lengths to mostly remove the need for
> > using it, with inline functions, constants, and the like.
>
> Now your just talking specifically about macros which still can be
> useful and there are somethings that can only be done using a macro.

No, I am not. I have nothing against macros -- on the contrary, I met
my wife teaching a class on macros.

Preprocessors are not the place for them. Lots of languages have
macros without preprocessors. Macros are great! I wish Java had them.

(They do have their drawbacks, but no on the scale of a preprocessor.
And the power of any macros I'd envision is substantially more than is
offered by the C/C++ preprocessor).

> MS tools destroy what Java has to offer IMHO.  Only the re-factoring is
> better for Java.  It's all opinion either way.

Are you comparing MS C++ tools to Java tools, or C# and friends?

Anyway, it's not all opinion. Such comparisons can be done quite
objectively. Which tools you prefer to USE is opinion.

> I think you have to realize that preprocesing is just a tool and isn't
> to be used to solve all problems.  Just because I want a hammer doesn't
> mean I regard every issue as being a nail.  It's very appropriate to
> handle cross platform issues, hardware issue, diagnostic code etc.  All
> of these issues are very relevant to Android.  Sure these issues might
> be handled differently for a desktop solution where resources aren't as
> big of an issue.

Nobody has shown me a case where you need a preprocessor because of
resource issues. "Can use", yes, but "need", no.

It is HIGHLY INAPPROPRIATE to handle platform issues and hardware
issues -- it makes porting to a new platform a royal nightmare. Your
best shot there is diagnostic code -- and there are better ways,
involving post-processors rather than preprocessors.

> Why force everyone to do it the so called right way?

Because of the cost to everyone else of the feature you are demanding.
Why not put in every hair-brained feature anyone thinks they'd like to
use?

Because LONG experience shows, that approach makes for major problems
with languages, and makes them harder to use. Trust me -- that
approach has had its day in the language-design world. Even a poorly-
designed API, not part of the language, can have a major adverse
impact on the maintainability of a product.

And in extreme cases (but only extreme cases), even personal code-
formatting idiosyncrasies can have a negative impact.

"Let people do whatever they want" has, after decades of experience,
been found to not be a good idea. A more careful balance must be
sought.

> Why does C# have conditional compile?

To accommodate the masses of C programmers that Microsoft wanted to
attract, of course!

>  Just because SUN chose not to support
> preprocessing in javac doesn't mean they aren't behind it.  Maybe they
> chose to support it through tools so that j2me code would still work
> with j2se?  That would make a lot of sense to me.  For something they
> aren't behind they sure put a lot of effort into it.

Or maybe they wanted to attract all those C programmers who are used
to "solving" every problem with a #ifdef, and aren't willing to update
their approach?

Or maybe because the J2ME people actually WERE former C programmers.

Language purity is not the only design constraint. Soustroup makes
that point himself. Sometimes you make compromises for acceptance.
Computer languages are partly human languages, and human languages are
a cultural artifact that change slowly.

> > It's also a major compilation performance hit. With a significant
> > amount of pain, you can get Visual Studio to avoid a lot of the
> > reparsing it requires, but the language basically says that to compile
> > any particular program file, you have to parse all the #includes,
> > recursively, processing the same file over and over and over again --
> > possibly differently each and every time, because INTEGER may mean int
> > in one case, unsigned int in another, and unsigned long long in yet
> > another.
>
> > And that's a problem for programmers, too. No, I don't mean a problem
> > for me, that a good C++ programmer knows how to avoid the problems. I
> > mean its a problem I've had to help MANY experienced C++ programmers
> > resolve time and time again -- often in vendor-supplied code, rather
> > than their own. Or when two different vendor's include files conflict
> > -- or one vendor's include files conflict with their own.
>
> > My long experience is that every time someone tells me they need a
> > preprocessor -- there turns out to be a better way. Sometimes you
> > replace that with code generation -- but most of the time, code
> > generation isn't the ultimate solution, either. Often, proper use of
> > introspection and metadata (the annotation facility, for example)
> > provide a superior (more robust, more compact, and more maintainable)
> > solution.
>
> Solve this one for me.  BlackBerry has a version of atan2 that is
> fixed-point and is much faster that the Math.atan2.  How can I take
> advantage of this without an interface or an extra function call?

Well, first, "without an interface or an extra function call" is a
completely artificial constraint. If I were managing your project, you
would first have to prove to me that the cost of the interface or
extra function call is worth the cost -- including the ongoing
maintenance cost, of finding EVERY DAMNED PLACE you pull this kind of
stunt, to upgrade to the next platform on our list.

But lets assume you've done that. You're calling it often enough (and
you picked a plausible case).

My response: Do it with a post-processor. Not only will you pick up
this case you chose manually, but you will also apply the policy at
every other point that would benefit that you may not have picked up
on.

That's my big hammer. Here's my little one;

In Jar MyMath.jar

public abstract class MyMath {
      public static final float VecToHeading( float x, float y )
      {
          float    fAngle = ((float)Fixed32.atand2( (int)(x *
65536.0f), (int)(y * 65536.0f) )) / 65536.0f;
          if ( fAngle<  0.0f )
              return fAngle + 360.0f;
          return fAngle;
      }
}

In jar file MyMathBlackberry.jar

public abstract class MyMath {
      public static final float VecToHeading( float x, float y )
      {
        float    fAngle = ((float)Math.atan2( x, y )) *
57.295779513082320876798154814105f;
        if ( fAngle<  0.0f )
              return fAngle + 360.0f;
          return fAngle;
      }
}

If you're clever, you'll see that you can start to undermine this
approach if you make the methods more complicated with only a trivial
difference.  But you also undermine your own "no extra function call"
criterion at the same time. But if you're really that wedded to "no
extra function call" -- that is, you're trying to do something that
the hardware BARELY is capable of, and even a tiny bit of extra
overhead will be significant (rare but possible -- but often falsely
assumed), then the bigger hammer is definitely what you want.

You can even do global optimizations like eliminating all calls to
functions smaller than a certain size, provided they expand the total
code size by no more than X amount, or if they occur within designated
critical code paths -- and avoid the need for manually (and
inaccurately) maintaining those policies within that code.

> Here is another one. The math function is in two different packages.
>
> //#if PLATFORM_BLACKBERRY
>         omega = (float)net.rim.device.api.util.MathUtilities.acos( cosom );
> //#else              
> //@     omega = (float)java.lang.Math.acos( cosom );
> //#endif

My first thought (10 seconds of thought) would be to define a common
method, with two versions, and let ProGuard (post-processor) inline
it.

> Actually laying down some surgical preprocess strikes within my code has
> allowed me to finish the project without having to create more code that
> I would have to manage and pay for at run-time.

Unnecessary surgery is a major cause of unnecessary mortality. Note
that none of the techniques I'e outlined here carry a runtime penalty.
They have their downsides, but runtime performance is not among them.

I have spent HUGE amounts of time dealing with problems introduced by
C macros. I wrote my first C program in 1972, on a PDP-11. Your
typical small handset is huge by comparison. I don't think you're
going to find it very easy to throw something at me that I've not seen
before.

Hell, before that, I was writing ASSEMBLER macros. With a better macro
environment than C provides, I might add.

I've used source code generation I think 3 other times for Java.
(HUGELY more than that in other languages). I've used dynamic class
generation a lot -- your problems may be too simple to need that, but
it's very powerful, and can give you highly optimized code tuned for
the specific case at hand. The runtime version of that approach even
allows you to optimize for information that is not available until
runtime -- something no preprocessor can do.

I WILL grant you this: YOU (or anybody, even me) may, under project
pressures, be able to come up with a solution to a pressing problem
fastest with a bit of pre-processing. I don't recall the details any
longer, but I believe I've done it once with Java, then later replaced
it with code generation, and later with some clever introspection.
That last wouldn't fly in your environment, I'm sure, but code
generation would, and so would post-processing.

I absolutely do understand the need to Get It Done. But I also
understand the tendency to continue to rely on the toolset one is most
familiar with, and assume that it's necessary to do it that way.
Eventually -- often regretfully late -- there comes an 'Aha!' moment.

---
Did you know that HPUX originally tried to enable threading by
defining a preprocessor macro for every potentially blocking call,
redirecting it to a non-blocking wrapper? Can you imagine the time I
spent sorting out the namespace collisions this resulted in for a
decade-old multi-million-line project -- including within their own
headers?

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to