6 ms·
In C++23 with zip it looks something like: for (const auto& [x, y] = std::views::zip(a, b)) { /* ... */ } A notable difference is that the ranges don'
by planede 4y ago
In C++23 with zip it looks something like:
for (const auto& [x, y] = std::views::zip(a, b)) {
/* ... */
}
A notable difference is that the ranges don't have to match in size, the loop will run until the end of the shorter range is reached.
If it is required for optimization to not check for reaching the end of one of the ranges then it can be achieved with something like:
for (const auto& [x, y] = std::views::zip(a, std::ranges::subrange(std::ranges::begin(b), std::unreachable_sentinel))) {
/*...*/
}
I guess it's hard enough to bump into this by accident.
- edflsafoiewq 4y agoIn Common Lisp it's (loop for x in a ; on each iteration, steps x to next element of a for y in b ; same thing do ...) This is like the Zig in that it's a hard-coded feature of the looping construct instead of being a general combinator like C++/Rust, but I think it's neat that by allowing multiple clauses, zipping falls out completely for free.
- Someone 4y ago> This is like the Zig in that it's a hard-coded feature of the looping construct I think lisp’s loop isn’t hard-coded in the language, but defined in the standard library. See for example the loop implementation at https://github.com/sbcl/sbcl/blob/master/src/code/loop.lisp https://github.com/sbcl/sbcl/blob/master/src/code/loop.lisp (about 2,000 lines because loop is a monster/very flexible (pick whatever you prefer. I would pick both))
- edflsafoiewq 4y agoLOOP isn't hard-coded into the language, but the possible clauses are hard-coded into LOOP. This is in contrast to ITERATE, which is an extensible CL looping macro, or the generator/iterator style popular in C++/Rust/Python/etc.
- kazinator 4y agoIn less than 400 lines of C99 preprocessing (not counting some utilities included), I made a loop macro for Awk which supports parallel and nested (cross-product) iteration, and user-definable clauses. https://www.kylheku.com/cgit/cppawk/tree/share/cppawk/include/iter.h https://www.kylheku.com/cgit/cppawk/tree/share/cppawk/includ... The bulk of the file is defining the clauses, each of which requires six lines: six simple macros have to be defined. (Kind of reminiscent of the five SETF expanders in Common Lisp for defining a new place.) This is thoroughly documented by a man page, including user-defined clauses. An complete example is given how to make a cause which iterates over alphanumeric strings, as in: BEGIN { loop (alpha_range (x, "aa0", "cc9")) print x } where x is stepped over "aa0", "aa1", ..., "aa9", ... "ab0", ..., "cc9".
- Jach 4y agoI'm a fan of Norvig's LOOP implementation from PAIP: http://www.norvig.com/paip/loop.lisp http://www.norvig.com/paip/loop.lisp It's missing some things from the full ANSI CL loop but it's just 223 code lines, and importantly not particularly clever code lines so that it serves as great instruction material for a method on how one could write one's own macro as complex as loop is.
- kazinator 4y agoIt's just a macro around mapc ;; the exprs evaluate to lists, and the vars step over them (mapc-loop (expr1 expr2 ...) (var1 var2 ...) body) We want this translation: (mapc (lambda (var1 var2 ...) body) expr1 expr2 ...) If we leave all matters of error checking to the generated code, it's just: (defmacro mapc-loop (exprs vars &rest body) `(mapc (lambda ,vars ,@body) ,@exprs)) It boggles the mind what that passes for a blog-worthy invention in some backwaters.
- noobermin 4y agoGod, C++ even today is still horribly verbose. I get that being "explicit" is being "better" but there are limits. Even after auto removed a lot of verbosity there still is a lot there just to get it to do exactly what you want.
- nikbackm 4y agoWhat is verbose about that? (The first case, not the second, special case) Seems hard to make it any shorter. Well, I guess you could remove "const" if you want.
- jeroenhd 4y agoHere's how it looks when you write readable C++: for (const auto &[x, y]: zip(a, subrange(begin(b), unreachable_sentinel))) { /* Do something with x and y */ } I'm not sure why C++ programmers don't like using `using`, it's as if Java programmers insist on typing out java.util.ArrayList every time because you may have an ArrayList of your own in the future. So much C++ code can become readable by adding `using namespace std::something`.
- cmovq 4y agoThe reason is header files. If you do `using namespace std::something` in one file and it gets included in another, the other file now has std::something in the global namespace which it may not have excepted. Other languages like Java have imports scoped a to a single file, so this is not a problem.
- netr0ute 4y agoAs someone who is using a lot of C++20, I can't wait to use this feature when C++23 is finally ready :)
- WalterBright 4y agoD has std.zip: https://dlang.org/phobos/std_range.html#zip https://dlang.org/phobos/std_range.html#zip Sorting two arrays in parallel: import std.algorithm.sorting : sort; int[] a = [ 1, 2, 3 ]; string[] b = [ "a", "c", "b" ]; zip(a, b).sort!((t1, t2) => t1[0] > t2[0]); writeln(a); // [3, 2, 1] // b is sorted according to a's sorting writeln(b); // ["b", "c", "a"]