# ALL\_CAPS for macro parameter names?

**URL:** <https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119>\
**Category:** Core Development\
**Created:** [October 25, 2023, 2:38pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119 "2023-10-25T14:38:22Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [October 25, 2023, 2:38pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/1 "2023-10-25T14:38:22Z")

</div>

Macro names are usually written in ALL\_CAPS. It is an old tradition that predates Python, and PEP 7 only explicitly specifies that [public] macros should have the MixedCase prefix before ALL\_CAPS.

But what about macro parameter names? In all examples that I seen before, in PEP 7 examples, in the CPython code, parameter names are in lower case. Some styleguides recomend to add the underscore suffix or prefix, but CPython code does not always follow this.

@erlendaasland advocates for using ALL\_CAPS style for macro parameter names and says that it is already used by other core developers. I haven’t seen it yet, is it a new tendency? Should it be explicitly specified in PEP 7? Otherwise we will find that the half of the code uses the upper case and the other half uses the lowr case, and it will be difficult to read.

---

<div class="post-metadata">

**Author:** ![erlendaasland](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/erlendaasland/32/4378_2.png) [@erlendaasland](https://discuss.python.org/u/erlendaasland)\
**Post date:** [October 25, 2023, 2:45pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/2 "2023-10-25T14:45:14Z")

</div>

I learned the ALL\_CAPS style from the CPython code base. I don’t remember which extension module it was right now. I’ve come to prefer it since it visually separates the macro parameters from variables that are implicitly used in the macro body. A macro parameter is not a C variable; it is text that is being replaced by the C pre-processor. Visually making the macro parameters stand out makes a macro easier to understand and reason about, IMO.

I don’t think it is a problem with two styles. There are already different macro styles, for example when it comes to the placement of line continuation characters. (For those, I prefer to align them; IMO it makes the code less cluttered.)

---

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [October 25, 2023, 2:52pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/4 "2023-10-25T14:52:29Z")

</div>

I understand the reasons. But it is so unusual, it stands out so much. Until now, this meant that you had to look elsewhere for the definition of a name as a macro. Only names defined with `#define` used ALL\_CAPS.

We need to decide what style to use in the new macros and document it. This does not mean that existing macros should be rewritten right now. Style guides exist to avoid style debates.

---

<div class="post-metadata">

**Author:** ![eric.snow](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/eric.snow/32/31_2.png) [@eric.snow](https://discuss.python.org/u/eric.snow)\
**Post date:** [October 25, 2023, 3:20pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/5 "2023-10-25T15:20:32Z")

</div>

FWIW, I’ve done it both ways. IIRC, at first I’d always do it ALL\_CAPS, following the prior art I’d seen. However, when I ran into existing macros with lower-case parameters, I mostly started adjusting to match nearby macros.

I’m not sure it matters much, though I do think it’s a _little_ easier for readers to identify the ALL\_CAPS names in the macro body.

Regardless, clarity on a consistent pattern (i.e. a PEP 7 note) would be nice; it would be one less thing to think about.

---

<div class="post-metadata">

**Author:** ![guido](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/guido/32/21_2.png) [@guido](https://discuss.python.org/u/guido)\
**Post date:** [October 25, 2023, 3:23pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/6 "2023-10-25T15:23:46Z")

</div>

I prefer lowercase for macro args. The ALL\_CAPS style is used in a few places and I can’t get used to it.

---

<div class="post-metadata">

**Author:** ![brandtbucher](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/brandtbucher/32/22862_2.png) [@brandtbucher](https://discuss.python.org/u/brandtbucher)\
**Post date:** [October 25, 2023, 7:12pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/7 "2023-10-25T19:12:38Z")

</div>

Aligned with @erlendaasland on all points (including the pretty lined-up-slashes).

I use caps. My mental model is that macro parameters work just as macros do: using token replacement. It’s really a macro-within-a-macro, to me at least.

---

<div class="post-metadata">

**Author:** ![brandtbucher](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/brandtbucher/32/22862_2.png) [@brandtbucher](https://discuss.python.org/u/brandtbucher)\
**Post date:** [October 25, 2023, 8:13pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/8 "2023-10-25T20:13:13Z")

</div>

For comparison, here’s a macro from CPython’s specialization stats machinery:

```c
#define ADD_STAT_TO_DICT(res, field) \
    do { \
        PyObject *val = PyLong_FromUnsignedLongLong(stats->field); \
        if (val == NULL) { \
            Py_DECREF(res); \
            return NULL; \
        } \
        if (PyDict_SetItemString(res, #field, val) == -1) { \
            Py_DECREF(res); \
            Py_DECREF(val); \
            return NULL; \
        } \
        Py_DECREF(val); \
    } while(0);

```

`field` is purely a vehicle for macro magic, not actually a struct member. It’s also harder for me to notice that there is a code path where `res` is evaluated twice (especially when contrasted with `val`, which doesn’t have this concern).

I find this all much easier to reason about in my preferred rewriting:

```c
#define ADD_STAT_TO_DICT(RES, FIELD) \
    do { \
        PyObject *val = PyLong_FromUnsignedLongLong(stats->FIELD); \
        if (val == NULL) { \
            Py_DECREF((RES)); \
            return NULL; \
        } \
        if (PyDict_SetItemString((RES), #FIELD, val) == -1) { \
            Py_DECREF((RES)); \
            Py_DECREF(val); \
            return NULL; \
        } \
        Py_DECREF(val); \
    } while (0)

```

(I would say the lined-up slashes are preferred, but not required. They _can_ be a bit painful to write and maintain, and can clutter up diffs a bit.)

---

<div class="post-metadata">

**Author:** ![pitrou](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pitrou/32/28_2.png) [@pitrou](https://discuss.python.org/u/pitrou)\
**Post date:** [October 25, 2023, 8:56pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/9 "2023-10-25T20:56:00Z")

</div>

> [@brandtbucher](#):
>
> I find this all much easier to reason about in my preferred rewriting:

This is a rather compelling example indeed. The fact that `FIELD` is uppercase in `stats->FIELD` immediately hints that the struct field’s name is macro-expanded, while `stats->field` could leave the reader dumbfounded.

So, yes, +1 from me on uppercase macro parameter names.

---

<div class="post-metadata">

**Author:** ![guido](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/guido/32/21_2.png) [@guido](https://discuss.python.org/u/guido)\
**Post date:** [October 25, 2023, 9:30pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/10 "2023-10-25T21:30:16Z")

</div>

Agreed, as long as we’re not encouraging folks to make all macros “consistent”.

---

<div class="post-metadata">

**Author:** ![encukou](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/encukou/32/2461_2.png) [@encukou](https://discuss.python.org/u/encukou)\
**Post date:** [October 26, 2023, 6:25am UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/11 "2023-10-26T06:25:57Z")

</div>

> [@brandtbucher](#):
>
> ```python
> Py_DECREF((RES)); \
> 
> ```

There’s another style suggestion hiding here: if the macro argument is a variable/expression, it should be enclosed in parentheses.  
IMO, that’s a good rule of thumb. Kind of like redundant braces on single-line if/loop bodies.

---

<div class="post-metadata">

**Author:** ![vstinner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/vstinner/32/15130_2.png) [@vstinner](https://discuss.python.org/u/vstinner)\
**Post date:** [October 28, 2023, 6:11am UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/12 "2023-10-28T06:11:53Z")

</div>

On `Py_DECREF((RES))`, double parenthesis are redundant since there are outter parenthesis for `Py_DECREF(...)` call.

---

<div class="post-metadata">

**Author:** ![erlendaasland](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/erlendaasland/32/4378_2.png) [@erlendaasland](https://discuss.python.org/u/erlendaasland)\
**Post date:** [October 30, 2023, 9:28am UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/13 "2023-10-30T09:28:18Z")

</div>

> [@encukou](#):
>
> There’s another style suggestion hiding here: if the macro argument is a variable/expression, it should be enclosed in parentheses.

Expanding a little bit on this digression\[1\]; for `do...while(0)` macros, I prefer to add the `do {` on the first line, because it saves an indent and a line.

> **Example**
>
> ```c
> #define ADD_STAT_TO_DICT(res, field) \
> do { \
> PyObject *val = PyLong_FromUnsignedLongLong(stats->field); \
> if (val == NULL) { \
> Py_DECREF(res); \
> return NULL; \
> } \
> if (PyDict_SetItemString(res, #field, val) == -1) { \
> Py_DECREF(res); \
> Py_DECREF(val); \
> return NULL; \
> } \
> Py_DECREF(val); \
> } while(0);
> 
> ```

> **My preferences applied**
>
> ```c
> #define ADD_STAT_TO_DICT(RES, FIELD) do { \
> PyObject *val = PyLong_FromUnsignedLongLong(stats->FIELD); \
> if (val == NULL) { \
> Py_DECREF((RES)); \
> return NULL; \
> } \
> if (PyDict_SetItemString((RES), #FIELD, val) == -1) { \
> Py_DECREF((RES)); \
> Py_DECREF(val); \
> return NULL; \
> } \
> Py_DECREF(val); \
> } while (0)
> 
> ```

* * *

1. “other style suggestions”

---

<div class="post-metadata">

**Author:** ![erlendaasland](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/erlendaasland/32/4378_2.png) [@erlendaasland](https://discuss.python.org/u/erlendaasland)\
**Post date:** [October 30, 2023, 9:53am UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/14 "2023-10-30T09:53:05Z")

</div>

Based on the reactions on Brandt, Antoine and Guido’s posts, there seems to be a consensus here. I created [a PR](https://github.com/python/peps/pull/3516) in the PEP repo. Let the nitpicking begin 🙂

---

<div class="post-metadata">

**Author:** ![storchaka](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/storchaka/32/217_2.png) [@storchaka](https://discuss.python.org/u/storchaka)\
**Post date:** [October 30, 2023, 4:50pm UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/15 "2023-10-30T16:50:02Z")

</div>

I don’t mind, but it surprises me that this is the first time I encounter such a style.

---

<div class="post-metadata">

**Author:** ![encukou](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/encukou/32/2461_2.png) [@encukou](https://discuss.python.org/u/encukou)\
**Post date:** [May 23, 2025, 7:42am UTC](https://discuss.python.org/t/all-caps-for-macro-parameter-names/37119/16 "2025-05-23T07:42:53Z")

</div>

(Replying a year later. Please expand Brandt’s quoted post for context.)

> [@brandtbucher](#):
>
> I would say the lined-up slashes are preferred, but not required. They _can_ be a bit painful to write and maintain, and can clutter up diffs a bit.

I wrote some longer macros this way, and I must say I like how the lined-up backslashes make it clear I that didn’t miss one. (Especially since syntax-highligting must choose between indicating that it’s a macro vs. highlighting the code in the macro.)  
But, there’s a downside: it’s harder to tell where the line of bacskslashes _ends_, especially if the last few lines of the macro are short.

So, I [drew another line](https://github.com/python/cpython/blob/b8f55266bf873bc101c3aab7aa868b909ecbcb99/Modules/_ctypes/cfield.c#L610):

```c
#define ADD_STAT_TO_DICT(RES, FIELD) \
    do { \
        PyObject *val = PyLong_FromUnsignedLongLong(stats->FIELD); \
        if (val == NULL) { \
            Py_DECREF((RES)); \
            return NULL; \
        } \
        if (PyDict_SetItemString((RES), #FIELD, val) == -1) { \
            Py_DECREF((RES)); \
            Py_DECREF(val); \
            return NULL; \
        } \
        Py_DECREF(val); \
    } while (0) \
    ////////////////////////////////////////////////////////////////

```

It might be ugly (especially if you’re not used to it), but IMO, it’s functional.  
Don’t be surprised if you see this. I won’t push to add it to PEP 7 unless more people adopt it.
