Skip to content

Instantly share code, notes, and snippets.

@uucidl
Last active December 22, 2020 13:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uucidl/725a3f7604e044a591bf3d1e7371b497 to your computer and use it in GitHub Desktop.
Save uucidl/725a3f7604e044a591bf3d1e7371b497 to your computer and use it in GitHub Desktop.
Language Specific Pitfalls And Things Not To Do Again

Python2

Don’t create generators with side effects:

import contextlib

@contextlib.contextmanager
def my_nice_context():
    try:
        print '    Before'
        yield
    finally:
        print '    Afterwards'


def my_nice_contextualized_generator():
    for x in ['a', 'b', 'c']:
        with my_nice_context():
            yield x

print "\nIterating my list as a generator, contextualizes the inner loop:"

for x in my_nice_contextualized_generator():
    print '        X is %s' % x

print "\nBut this pattern is easy to break! Add list around it:"

for x in list(my_nice_contextualized_generator()):
    print '        X is %s' % x

print "\nGenerators should not have side effects when they return values"

C++

Because namespaces are implicit (consequence of ADL) using namespace should be in general be avoided, unless necessary such as to invoke ADL in a template function. (Niklaus Wirth took similar conclusion with module imports in Oberon07 and forced them to be explicit)

C language

macros taking a body

Defining a macro taking a body of code is a bad idea generally, as the compiler will eat away all the newlines and syntax errors will be emitted imprecisely as if they had happened in the initial line rather than precisely.

typedef for aggregates

typedef struct Foo { } Foo;

People do this in C all the time because C otherwise requires you to always mention the type struct Foo rather than Foo, however getting into that habit means forward declarations have to be written:

typedef struct Foo Foo;

rather than simply struct Foo

Enums are not type-checked, contrary to C++

I.e. the following is warning-free and valid:

enum AnEnum {
  AnEnumValue,
};

enum AnotherEnum {
  AnotherEnumValue,
};

int main(void) {
  enum AnotherEnum value = AnEnumValue;
}

Beware that `int foo()` isn’t a function taking no-argument

`int foo(void)` is what you want

Enums are an issue for ABI stability

Enums are of undefined signedness and size, and should not be used in library interfaces that aim for binary interface stability.

zero-initialize with minimum warnings

struct A
{
  int a;
};

struct B
{
  struct A super;
  int b;
};

int main(int argc, char** argv)
{
  (void)argc;
  (void)argv;
  // We want to zero-initialize without explicitely saying memset:
  struct B test0 = {0};    // -wmissing-brace in -Wall
  struct B test1 = {{0}};  // -wmissing-field-initializers in -Weverything
  struct B test2 = {.b=0}; // only one that works without warning
  return test0.super.a + test0.b +
    test1.super.a + test1.b +
    test2.super.a + test2.b;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment