0

After playing around a bit with C preprocessors, I thought of a way to have something similar to a Pythonian with control structure, defined like this:

#define with(var) for(int i##__LINE__=0;i##__LINE__<1;)for(var;i##__LINE__<1;++i##__LINE__)

Sample usage:

#include <cstdio>
#include "FileClass.hpp"
#include "with.hpp"

int main(){
    with(FileClass file("test.txt")){
        printf("%s\n",file.readlines().c_str());}
    return 0;}

The idea is that a doubly-nested for loop has an outer obfuscated iteration variable which is incremented once in the inner loop to break it. This causes the following code to be executed once with var in its scope.

Are there any downsides to this? If I obfuscate the iteration variable enough, there would be almost no chance of having a name clash, it uses only standard preprocessor features in a way that doesn't seem to have any possibility of backfiring, and it's very easy to understand.

It almost seems too good to be true - is there any reason this isn't used everywhere?

JJJ
  • 32,902
  • 20
  • 89
  • 102
ConsciousCode
  • 563
  • 4
  • 18
  • 8
    If you want to write Python, do so. – Xeo Dec 17 '11 at 03:26
  • Everybody is working on ENTIRELY removing need for preprocessor and you're trying to use it extensively, well done :) ( I think i saw something like this in Obfuscated C contest. ) – ScarletAmaranth Dec 17 '11 at 03:29

5 Answers5

6

is there any reason this isn't used everywhere?

Yes, C++ is not Python, and if I understood your code correctly, this does exactly the same:

{
  FileClass file("test.txt");
  printf("%s\n", file.readlines().c_str());
}

So, what are the downsides? Unnatural syntax, usage of the preprocessor for code obfuscation, achieving the same thing as above with much more boilerplate code, and unidiomatic use of C++. Enough?

C++ has the very important concept of value types and scope-based deterministic destruction of stack variables. This leads to very important idioms like SBRM (scope-bound resource management, also called RAII).

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • Using a with control statement makes the fact that file is the thing being operated on more explicit. Also, a try statement could be added to the macro and catch statements added to make a prettified short hand. – ConsciousCode Dec 17 '11 at 03:44
  • 2
    @PiMaster: You know, saying `file.do_something()` is enough of an indicator for me that `file` is being operated on. Also, what if you suddenly do not want any try-catch block around that? Or if you forget that one is included? It's best to be explicit about such stuff, which you are hiding behind obscure macros. – Xeo Dec 17 '11 at 03:49
4

It's similar in spirit to the macros used in the original Bourne shell, which was written in C. They were intended to provide a syntax similar to Algol 68, which apparently was Bourne's preferred language.

A small sample from http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h :

#define IF    if(
#define THEN  ){
#define ELSE  } else {
#define ELIF  } else if ( 
#define FI    ;}

The result tends to be code that's difficult to read either for C programmers (who have to familiarize themselves with your macros as well as the syntax of C itself), or for Algol 68, or in your case Python programmers.

If I read a C++ program that uses your with() macro, I can't really understand what it's doing without (a) realizing that with() is a macro (macros are conventionally given all-caps names), (b) tracking down the macro definition, and (c) deciphering the rather odd C code that results from expanding the macro. That's assuming I don't fall into the trap of thinking that it's a compiler-specific extension, or that C has a with statement that I didn't know about.

Or, if I happen to understand Python with statements, then I still need to (a) realize that your with() macro is intended to mimic a Python with statement, and (b) trust you to get it right.

Years ago, I thought that this:

#define ever ;;
...

for (ever) { ... }

was very clever. I still do think it's clever; but I no longer think that cleverness is such a good thing.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
1

It almost seems too good to be true - is there any reason this isn't used everywhere?

Sure, that is a great structure that works well for you, but what about the rest of the people on the team? What about the future you - in six months - that can't remember the cute macro that you wrote?

In short, syntactic gymnastics like this are great exercises at home, but are terrible in a collaborative environment, or even for code that you alone will maintain in the future. Stick to the best practices and your code will be much easier to maintain and understand.

That isn't to say that you shouldn't do this kind of thing at home. Do what you enjoy, keep your brain limber. But don't use your warm-up exercises in production!

ObscureRobot
  • 7,306
  • 2
  • 27
  • 36
1

Is this really "with"? The big advantage of "with" in Python is that it works with context managers, which take care of automatically closing/releasing/unlocking/unallocating the variable in the "with" statement. In C++, there are standard methods for doing this. For instance, auto_ptr will take care of auto-deleting pointers that were allocated with new. Learn these standard idioms before reinventing them yourself.

Xeo
  • 129,499
  • 52
  • 291
  • 397
PaulMcG
  • 62,419
  • 16
  • 94
  • 130
  • That's a possibility, if you think about it. I could make the macro take two parameters, a type and a declaration, and write a sort of wrapper template class that generates a special type based on its template parameters, in this case a pointer. It could generate an auto pointer to deallocate the memory when the loop finishes. – ConsciousCode Dec 17 '11 at 03:51
  • 1
    Just on a sidenote, `auto_ptr` is deprecated in favor of `unique_ptr`. – Xeo Dec 17 '11 at 03:52
0

The obvious downside to this is that no one will be able to read your spaghetti bastardized-Python-in-C++ code. So good luck maintaining that code.

middus
  • 9,103
  • 1
  • 31
  • 33
  • It might be important to note that this is more of a fun, light-hearted thing I thought about. I don't actually plan on using it in any serious projects, though I might include it in my own code library for personal projects, or even just to have it. – ConsciousCode Dec 17 '11 at 04:00
  • 1
    In that case, this is exactly what you should be doing. Messing around with weird programming ideas. I'd bet that when you come back across this code in six months, you will say WTF and scratch your head. But that will be a lesson learned. – ObscureRobot Dec 17 '11 at 05:54