Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QUESTION] cpp2 for loops #1063

Closed
dutkalex opened this issue May 11, 2024 · 5 comments
Closed

[QUESTION] cpp2 for loops #1063

dutkalex opened this issue May 11, 2024 · 5 comments

Comments

@dutkalex
Copy link
Contributor

Hi! My question is rather simple, but I could not find the answer in the documentation nor in other issues. What is the cpp2 equivalent for:

for ( int i = a; i < b; ++i ){
  // loop body
}

All the examples in the documentation seem to be range-based for loops, and the closest I could find (which is obviously not the right answer) is:

for std::views::iota{ a, b } do ( i ){
  // loop body
}

Thanks for the amazing work!
Best regards,
Alex

@hsutter
Copy link
Owner

hsutter commented May 11, 2024

That's a good question I should cover somewhere. Here's the quick answer:

auto cpp1() {
    //  Prints: 0123456789
    for ( int i = 0; i < 10; ++i ){
        std::cout << i;
    }
    std::cout << "\n";
}

main: () = {
    cpp2();

    //  Prints: 0123456789
    (copy i := 0) while i < 10 next i++ {
        std::cout << i;
    }
    std::cout << "\n";

    // Same, just my personal whitespace style
    (copy i := 0)
    while i < 10
    next  i++ {
        std::cout << i;
    }
    std::cout << "\n";
}

Line by line (and why I like being able to write the parts on individual lines):

  • (copy i := 0): Any statement can have statement-local parameters, so this is just declaring i as an int that's local to the loop. Parameters by default are const (and for not-cheap-to-copy types bind to the original value), so because I want to modify it I use copy to explicitly declare this is my own mutable scratch variable. (I find that statement-local parameters initially take getting used to the first couple of times, then are easy to remember and use because they work with any statement including blocks.)
  • while i < 10: The termination condition.
  • next i++: The end-of-loop-iteration statement. Note ++ is always postfix in Cpp2.

I should add an example to the docs... I'll keep this open until I do that. Thanks!

@hsutter
Copy link
Owner

hsutter commented May 11, 2024

@dutkalex
Copy link
Contributor Author

dutkalex commented May 12, 2024

@hsutter You closed this thread but it turns out that your answer left me with more questions! 😅

  1. I understand that one of the goals of cpp2 is simplification of the language through generalization and an overall reduction of the number of concepts. But in this case, having to revert to a while loop is a net loss in expressivity of the language. I we were to follow this principle dogmatically, all for loops would have to be eliminated because every for loop is just a special case of the more general and powerful while loop concept. However, the while loop is much-more error-prone, and I am sure you will agree that we don't want this kind of concept count reduction because having for loops in our toolbox enables us to better express our intent as programmers. For scientific computing purposes (I take this example because this is where I come from as a C++ programmer), not being able to express in a simple way index-based iteration patterns would be a deal-breaker. However, I do not advocate for the error-prone C-syntax either, but IMO having a concise syntax such as for idx_range(a,b) do (i){ ... } available is important to make cpp2 code safer. What do you think of it?
  2. I understand how the for loop syntax is built as for <range> do <lambda_expr>, which is actually very familiar to me as a HPC fellow, because we are used to writing thinks like hpc_framework::parallel_for( exec_policy, range, [&]( int idx ){ ... } ); in cpp1 syntax. However, the absence of the prefix : from the cpp2 lambda syntax in the cpp2 for loop syntax, combined with the fact that the cpp2 for loop syntax does not read left to right is a sign that this generalization is not very natural. I would also add on a personal note that I really don't like the do token, because it does not convey much meaning as a keyword, and is confusing because it connotes a do ... while loop. IMHO it is like having a then keyword after an if statement: it makes the syntax more verbose and does not provide any additional meaning. On top of that, having a do token justifies diverging the syntax from the if and while syntax which both require the body to be enclosed by curly braces. I would argue that having a coherent syntax among these 3 control flow structures should be a higher-priority goal than seeking unification with the function syntax. With this in mind, my question is therefore: why not opt for a more intuitive syntax for the cpp2 for loop? For example, Python's for i in range(N) is very natural and reads like english (they did a really great job on this one IMHO), and something like <optional label :> for <optional in(default), out, inout or move> <elm> : <range> { /* body with mandatory {} */ } would be simpler, more familiar, easier to read and more coherent with the rest of the cpp2 syntax? What do you think of it?

Anyway, thanks for the quick answer and the amazing work overall
Best regards,
Alex

@dutkalex
Copy link
Contributor Author

dutkalex commented May 13, 2024

Other related threads for reference: #432 #834 #386

@dutkalex
Copy link
Contributor Author

Moving this to discussions (see #1073), as it seems more appropriate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants