This post is a language comparison coming out of this great article on list comprehension. D does not have List comprehension.
Article No Longer Available
Since D can generally operate on ranges rather than allocated arrays, if you need an array just add .array
for more on arrays review
My explanation will be limited to D specific differences, but please ask for further details if something is not clear.
List
import std;
void main()
{
// arr = [i for i in range(10)]
writeln(iota(10));
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
Iota is uncommon, but is the equivalent of range in Python.
Dictionary
// y = {i:v for i,v in enumerate(x)}
auto x = [2,45,21,45];
auto y = enumerate(x).assocArray;
writeln(y);
// [0:2, 3:45, 2:21, 1:45]
As mentioned D prefers unallocated range manipulation, this tends to mean no index, enumerate creates a tuple with a count and value, and assocArray
takes a range of tuple to build an associative array (dictionary)
Conditionals
// arr = [i for i in range(10) if i % 2 == 0]
auto arr = iota(10)
.filter!(i => i % 2 == 0);
writeln(arr);
// [0, 2, 4, 6, 8]
// arr = ["Even" if i % 2 == 0 else "Odd" for i in range(10)]
auto arr2 = iota(10)
.map!(x => x % 2 ? "Odd" : "Even");
writeln(arr2);
//["Even", "Odd", "Even", "Odd", "Even", "Odd", "Even", "Odd", "Even", "Odd"]
Nested for loop
// arr = [[i for i in range(5)] for j in range(5)]
auto arr3 = iota(5)
.map!(j => iota(5));
writeln(arr3);
// [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
// arr = [(i,j) for j in range(2) for i in range(2)]
auto arr4 = iota(2).cartesianProduct(iota(2));
writeln(arr4);
//[Tuple!(int, int)(0, 0), Tuple!(int, int)(0, 1), Tuple!(int, int)(1, 0), Tuple!(int, int)(1, 1)]
I find that D makes this behavior very clear.
Tuples being a library provided type, their string representation is a little more verbose.
Flatten 2D Array
// arr = [i for j in x for i in j]
auto x2 = [[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]];
auto arr5 = x2.joiner;
writeln(arr5);
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Conclusion
D is a typed language, since I did not convert everything back into an array a unique arr variable was needed for each.
Personally I think D represents the behavior more clearly than Python's list comprehension. Even the conditional output selection, which was more consice in D was represented reasonably.
This does not touch on the other algorithms D provides and can be applied to the ranges.
Python is praised on its clear syntax and readability, well I must be spoiled because it makes me cringe on most everything I see.
Top comments (5)
Just stumbled acrossed this
medium.com/better-programming/how-...
The issue I see with this is chaining multiple operations. In the example he stores the result before the next operation.
Let's look at an alternative way to make it readable.
The language isn't the driving force for readability here.
If you look closely D does provide usage challenges since I introduced the use of alias. Explaining its need would be more technical than
lambda :
is that a bad thing? I don't know.Possibly, do you have examples?
What is the Pythonic way? I showed D idioms.
@byrro , in response to dev.to/byrro/comment/j0om
Are you seriously going to stop at iota? I rarely utilize this in real world code, it is generally used in examples as a quick way to get a range.
Note that terminology here is different in D. Python uses 'range' as a sequence of numbers, D uses "a set of different things of the same general type."
Is 'Cartesian product' easy to read for someone who has never crossed path with this operation? No, but it does give terminology to read about what it does. Whereas
[(i,j) for j in range(2) for i in range(2)]
Don't get me wrong, you could easily provide a library function in Python, name it and do this under the hood, it is not like the library implementation is some kind of English statement about the desired outcome.
I'm not saying these are the things which make or break Python's readability, but it does contribute to it not being able to have the throne of readability.
You seem to love Dlang and that's totally fine.
But the way you're expressing yourself is not helping to convince others about Dlang, if that's your goal. It's not just me.
I'm a fierce defender of freedom of private initiative and expression. But we've got to think about what is our goal and how to better get there.
If I may suggest an idea, why not approach the issue like: "if you love Python XYZ feature, then you'll love Dlang even more"? That would be more appealing for people to try Dlang.