Structural comments

Idea

Add syntax for structural comments to Python.
This does not need to cover all structures initially, and can be contributed to iteratively.

What are structural comments?

A structural comment will mark a structure as a comment to the interpreter/compiler.

For example:

def vec_add(x, y):
  z = []
  for i in range(0, min(len(x), len(y)):
    z.append(x[i] + y[i])
  return z

In this function, we have some example structures:

  1. The function scope itself; def ...
  2. Parameters for the function x, and y,
  3. Assignment of z; z = []
  4. A for loop for ...
  5. A function invocation; len(x)
  6. A method invocation; `z.append(…)

Supposing that we wanted to comment out this code, today it would be done line-wise.

# def vec_add(x, y):
#   z = []
#   for i in range(0, min(len(x), len(y)):
#    z.append(x[i] + y[i])
#  return z

With structural comments, we could comment out structures (using example syntax of #_):

Comments out the entire function…

#_def vec_add(x, y):
  z = []
  for i in range(0, min(len(x), len(y)):
    z.append(x[i] + y[i])
  return z

Comments out the entire parameter…

def vec_add(#_x, y):
  z = []
  for i in range(0, min(len(x), len(y)):
    z.append(x[i] + y[i])
  return z

Comments out the entire for loop…

def vec_add(x, y):
  z = []
  #_for i in range(0, min(len(x), len(y)):
    z.append(x[i] + y[i])
  return z

There are cases where this is equivalent to a line comment. There are cases where it is not.

How is this done now?

Usually, support from an editor providing a hotkey or an interaction menu, where each line is commented.

Commenting out a parameter of a function is not supported, though, unless that parameter is on its own line.

Indistinguishable Cases

I’m not aware of any cases where the compiler cannot distinguish the structure being commented out, hopefully they can be uncovered during discussion

Proposed Syntax

No syntax is currently being proposed for this change, though #_ is an example provided for illustrative purposes.

Benefit to Programmers

Many programmers frequently use comments during prototyping, especially during debugging or when code is particularly complex.

EDIT: was writing this on my phone and prematurely submitted.

2 Likes

Use if 0:#.

2 Likes

This syntax is far to hard to read I’m -1 pn the idea because of that.
Also using comments to remove unwanted code is only a very temporary measure at best.
Better to actually delete the unwanted code and use source control to retrieve an old version if required.

2 Likes

It would be much easier to generalize it right away.

Your use of the term “structure” seems a bit non-standard, but it seems that you are talking about commenting out a block of the code, according to the indentation of the code.

In order to understand such comments, the parser would just have to consider the indentation, without looking very much at the actual code. In Python syntax, a line that ends with a :, that is not inside of unbalanced brackets, marks that an indented block will follow. It wouldn’t even be necessary to make the parser check for that: it could have a simpler rule that, if the line starts with the block comment marker (whatever is chosen), everything is a comment until the next line at the same level of indentation.

Coincidentally, the language design I’ve been working on (no public details yet) includes this feature. The block-comment marker is processed after the block structure of the code has been determined, but before individual lines are parsed. Therefore, indented “code” inside the commented-out block is permitted to be syntactically invalid, as long as the indentation is valid. (This allows using the feature to create block comments where the lines start with indentation rather than a comment character, something that if 0:# cannot do. Of course, that’s probably not very useful, and only an incidental consequence of my design.)

1 Like

I’m generally in support of this proposal for quicker debugging.

That would still require the developer to take the time to indent the entire block.

Not if this proposal is made official and hence gets support from all IDEs and syntax highlighters.

The point of this proposal is to allow developers to make very temporary edits to test and revert changes as quickly as possible. Involving source control would make the development unnecessarily slower.

The OP is clear on whom this proposal benefits:

One difference between commenting a block, and commenting a structure, is that a function invocation which receives a variable number of parameters occurs entirely on one line, but a structural comment applied to one parameter should (ideally) only comment out that parameter from the invocation.

For example:

many_args(a, b, c, d, e, f)

commenting out c:

many_args(a, b, #_c, d, e, f)

It’s a generalization over comments which is language-aware, orthogonal to lines and blocks.

No, it would not, since the block is already indented:

if 0:#def vec_add(x, y):
  z = []
  for i in range(0, min(len(x), len(y)):
    z.append(x[i] + y[i])
  return z
def vec_add(x, y):
  z = []
  if 0:#for i in range(0, min(len(x), len(y)):
    z.append(x[i] + y[i])
  return z
6 Likes

Oops you’re absolutely correct. Consider me generally against the proposal now since I don’t often have a real use case for temporarily commenting out individual parameters.

1 Like

Hmm I commented too fast. The proposal may still have value for a multiline statement, where the if 0:# trick would fail:

if 0:#def vec_add(
    x,
    y
):
    ...
1 Like

This feels like something that is better served by IDE features like undo/redo and a nice history viewer. I am just in the habit of deleting a code block, and undoing after tests/other changes, or going back in history to find it again. Also multiline comment/uncomment that IDEs can provide reduces the usefulness of this feature.

Also, I am a complete loss when I would ever use the ability to uncomment some arguments passed to a function in this specific way. Except maybe passing something like debug flags, I don’t think I ever encountered a use for it.

(also ofcourse: The current syntax is a no-go since it’s already valid python. Probably anything starting with a # is offlimits, so understandable syntax could be quite the challenge, even if the idea is accepted.)

4 Likes

True. With PyCharm one can comment out an entire block by first collapsing a block with Ctrl-- and then comment out the “line” with Ctrl-/. PyCharm can even recognize valid code blocks within comments so one can uncomment an entire block with the same steps too.

We can borrow existing comment syntaxes from other languages such as // (from C++ and derivatives) and -- (from SQL), etc., and make it valid only in front of a statement keyword to avoid ambiguity with floor division or double negatives. But at this point the benefit that this proposal can bring may be too marginal indeed.

I’m against the syngax to comment out a block of code. You already have the text editor to do that, why does it have to be part of the language? In other words, how many developers do not have access to an editor that can comment out a block of code, thus will benefit from this proposal? I reckon very few.

However, the syntax to comment out a part of code on the same line, like foo(a, b, #_c, d) which comments out the argument c, is interesting. A text editor can’t do that, neither can you delete it and later restore it with git because git only works with lines. So this has some potential utility. It would be cool to have it, I’m just not sure if it’s worth adding complexity to the language (probably not).

Are there any real-world use cases?

Not really sure how often I’d want to do this, but you could use the fact that non-empty strings are truthy:

many_args(a, b, """c, """ or d, e, f)

Start a comment with """ and end it with """ or.

This strikes me as a clever language feature (“look what this language can do!”) that would be very bad for code readability overall.

I’m also curious how one would implement it–as I understand it, comments are stored in the tokenizer but are stripped from the AST (except for type comments). It seems like you’d need the AST to interpret these comments correctly, although I might be mistaken.

How should (#_a, b) be interpreted? As (b)?

Yes, I think this is right.

This only works if the function definition uses *args . It doesn’t work with positional arguments.

I temporarily remove part of a line by copying it and commenting out one of the two alternatives. This is generic and makes it easy to switch back and forth.

5 Likes

You can adjust the trick slightly for multiline statements.

if 0 and ( #def vec_add(
    x,
    y
):
    ...