Is there any way to assign multiple variable at once with Dlang? - d

With using Ruby, we can do this.
s = "split by space"
A,B,C = s.split(" ").map(&:to_i)
With using D-lang, it's compile error.
string s = "split by space";
int A,B,C = s.split(" ").map!(x => x.to!int);

Jonathan is mostly right, but there is in fact a way to split a tuple into
its constituent parts, albeit more verbose than in Ruby, and without any handy
type inference:
import std.meta : AliasSeq;
import std.typecons : tuple;
auto foo() { return tuple(42, 29, "hello"); }
unittest {
int a, b;
string c;
AliasSeq!(a, b, c) = foo(); // Look ma, magic!
assert(a == 42);
assert(b == 29);
assert(c == "hello");
}
While there's no built-in way to do this with ranges like your example, it's
possible to implement in a library:
import std.meta : AliasSeq, Repeat;
import std.typecons : Tuple, tuple;
import std.algorithm : map;
import std.conv : to;
import std.string : split;
import std.range : isInputRange, ElementType;
unittest {
string s = "1 2 3";
int A,B,C;
AliasSeq!(A,B,C) = s.split(" ").map!(x => x.to!int).tuplify!3;
assert(A == 1);
assert(B == 2);
assert(C == 3);
}
auto tuplify(size_t n, R)(R r) if (isInputRange!R) {
Tuple!(Repeat!(n, ElementType!R)) result;
static foreach (i; 0..n) {
result[i] = r.front;
r.popFront();
}
assert(r.empty);
return result;
}

No, there is no way to do that. There has been talk off-and-on about possibly adding tuple support to the language such that you could something like
int a;
int b;
string c;
(a, b, c) = foo();
and maybe that will happen someday, but it's not possible right now. The closest would be using something like std.typecons.Tuple/tuple so that you can do something like
Tuple!(int, int, string) foo() { return tuple(42, 29, "hello"); }
Tuple!(int, int, string) result = foo();
or more likely
auto foo() { return tuple(42, 29, "hello"); }
auto result = foo();
but Tuple is ultimately just a struct, and you can't magically split it out at the other end. You have to access its members via indices such as result[0] or result[1], or if you declare Tuple with names - e.g. Tuple!(int, "x", int, "y", string, "str") - then you can access the members by name - e.g. result.x. So, Tuple/tuple allows you to return multiple values without explicitly declaring a struct type just for that, but it's still creating a struct type just for that, and while it allows you to easily pack values to return, it does not allow you to automatically unpack them on the other end. That would require compiler support of some kind that we don't have.
However, even if we had better tuple support in the language so that something like
(a, b, c) = foo();
worked, I doubt that what you're trying to do would work, since map specifically returns a range. So, it's an object with member functions, not a tuple of any kind to be split up. It just so happens to represent a list of values that can be extracted with the right set of function calls. And the number of values that it has is not known at compile time, so even if you assume that the compiler understands the range primitives well enough to get a list out of them for you, it can't guarantee at compile time that there are enough values to put into the variables you're trying to assign to, let alone that there are exactly that number of values. So, while it wouldn't be impossible to make something like that work (e.g. if it threw an Error at compile time if there weren't enough values in the range), I'd be surprised if that were implemented. D is a statically typed language and that would effectively be making a piece of it dynamic, so it would be pretty out-of-character for it to be in the language. Ruby is a dynamic language, so it's a very different beast.
Regardless, any improvements with tuples would be improvements to the language and would have to go through the DIP process and get approved, and nothing like that has happened yet.

Related

Elegant way to write multiple If statements

I have the following Multiple 'if' statements.
Animals and Humans are two enums.
Var a, b;
int c, d, e = 0;
if (a == Humans ::Men) {
c = 1;
}
if (b == Animals ::Cat) {
d= 1;
e= 1;
}
if (b == Animals ::Dog) {
d = 1;
}
if (b == Animals ::Elephant) {
e = 1;
}
How can I write everything in one statement, so that the meaning is still the same.
Thanks in Advance.
You can set up your enum with specific values such that masking is possible. (Men, Cat, Dog, Element have exactly one, but unique, bit set). Bitwise enumerators with masking values are common.
Then you could write
if (b & Animals::d_applies){
d = 1;
}
where, at the very least, d_applies is Animals::Cat | Animals::Dog
Whenever possible, I find that some sort of tabulation based method is the most easily extendable. I'll demonstrate with std::map, but you can use other sorts of bookkeeping data structures. It's simply a matter of defining a mapping from the pairs of possible enumerations values to the triplets of values you intend to assign onto the variables:
using from_type = std::tuple<Humans, Animals>;
using to_type = std::tuple<int, int, int>;
std::map<from_type, to_type> value_getter {
{ from_type{Humans::Men, Animals::Cat}, to_type{0, 1, 1} },
// etc.
};
int c, d, e;
std::tie(c, d, e) = value_getter[from_type{a, b}];
Or, if you feel fancy and your compiler is up to supporting C++17 properly already, you can use the same map with structured bindings:
auto [c, d, e] = value_getter[from_type{a, b}];
So now initialization is part of the declaration, and is good wholesome C++.
You can arrange a container that contains pairs like "predicate, handler". Then you can iterate the container and call the handler if corresponding predicate do matches. std::for_each would be nice one-liner here after all setup code being done.
P.S. Not sure it's worth a bullet, however.

C#7 safeguard for deconstruction?

Is there a way to protect oneself from side effect to deconstruction when rearrenging elements' ordering in a tuple value?
For instance, the second console's writeline would output the wrong results.
public void Test()
{
var result = GetResult(10, 5);
Console.WriteLine($"sum: {result.sum}, substraction : {result.substraction}");
(int substraction, int sum) = result;
Console.WriteLine($"sum: {sum}, substraction : {substraction}");
}
//Old version
//private (int substraction, int sum) GetResult(int a, int b) => (a - b, a + b);
private (int sum, int substraction) GetResult(int a, int b) => (a + b, a - b);
"Element names are semantically insignificant except when used directly."
(From "C# Tuples. More about element names", by Vladimir Sadov who is a member of the C# language team).
Except in a few cases (as Vladimir explains in his post), the element names are ignored by the compiler unless explicitly accessed. This isn't just limited to deconstruction. The following code compiles just fine:
void Example()
{
(int a, int b) GetTuple() => (1, 2);
void PrintTuple((int b, int a) t) => Console.WriteLine($"a:{t.a}, b:{t.b}");
var t = GetTuple();
PrintTuple(t);
}
And the output is a:2, b:1.
So the compiler itself offers you no protection against mismatching names in tuples and deconstructions. That's not to say no protection is possible, it just needs someone (eg you) to write a Roslyn analyzer that detects name swaps like this and reports it as a warning.
This feature (warning for element names mismatches that are clearly accidental) did not make it into C# 7.0. You can voice your interest and follow the progress at https://github.com/dotnet/roslyn/issues/14217
It is also possible that some analyzers will fill this gap.
Note this sort of accident is not unique to tuples or deconstruction, you can accidentally pass arguments in the wrong order in invocations (in or out parameters).

Lambda closure vs simple argument?

For lambda expressions, I don't quite get the usefulness of closures in C++11.
auto f = [] (int n, int m) { return n + m };
std::cout << f(2,2);
versus.
int n = 2;
auto f = [n] (int m) { return n + m };
std::cout << f(2);
This is a very basic and primitive example. I'm guessing that closures play an important part in other kinds of statements, but my C++ book doesn't clarify this (so far).
Why not include the closure as a parameter?
OK, a simple example, remove all the x's from a string
char x = 'x';
std::string s = "Text to remove all 'x's from";
s.erase(std::remove_if(s.begin(), s.end(), [x](char c) {return x == c;}), s.end());
Borrowed and modifed from http://en.cppreference.com/w/cpp/algorithm/remove
In this example, remove_if() only takes a single parameter, but I need two values for the comparison.
Closures are not always called immediately. They are objects which can be stored and called later when the data necessary to successfully execute the lambda function may no longer be in scope or easily accessible from the call site.
It's possible to to store any necessary data along with the closure but it's so much simpler for the closure to grab anything it needs when it's created and use it when it's eventually called. It provides a form of encapsulation.
This also decreases code coupling because if you were to store the data along with the code then the caller could only work with the specific objects you decided to store. Since a closure carries its own data along with it, it can work with any data it needs.
Here's an greatly oversimplified real-life example. I built a database server which needed to support fields with multiple values. The problem was that when results were displayed, it was important to highlight which values actually caused a record to match the search criteria. So, the query parser would spit out a predicate in the form of a closure which would indicate whether or not it was a matching value.
It looked something like this:
std::function< bool(int value) > parser::match_int(int search_val) {
return [=](int value) { value == search_val; };
}
That closure got stored in a collection. When it was time to render the record, I could easily determine which values needed to be highlighted. Keep in mind that the parser and any associated data is now gone:
void render_values(std::function< bool(int value) > pred, std::vector<int> values) {
for (int value : values) {
if (pred(value))
render_highlight(value);
else
render_normal(value);
}
}

Tree in C++11 tuple with RTTI

I want to implement a simple tree in C++11 tuple with a Python fashion. In Python, we can use type(obj) to check run-time object type, and pass object with different type to one function, I have write pseudo code for calc(), how to do it in c++?
I try to print typeid(child1).name() and typeid(tree).name(), they are 'St5tupleIIciiEE' and 'St5tupleIIcS_IIciiEES0_EE'.
My environment is g++ 4.8.1. Thanks!
// pseudo code
int calc(tuple tree) {
symbol = type(get<0>(tree));
l_child = type(get<1>(tree));
r_child = type(get<2>(tree));
l = (type(l_child) == tuple) ? calc(l_child) : l_child;
r = (type(r_child) == tuple) ? calc(r_child) : r_child;
return l symbol r;
}
int main()
{
auto l_child = make_tuple('*', 1, 2);
auto r_child = make_tuple('-', 5, 1);
auto tree = make_tuple('+', l_child, r_child);
cout << calc(tree) << endl;
}
Python and C++ are very different languages. C++ is statically typed, Python is not. Transplanting Python techniques to C++ may or may not work. In this case it won't work.
In Python, there is only one tuple class, able to represent any tuple; in C++ there is an infinite number of tuple types, each one able to hold specific kinds of data. They are not interchangeable, as your experiment with typeid aptly demonstrates.
In C++, you cannot hold an arbitrary tree in a tuple. Write a tree class (or better, a class template).
Edit: technically, if you combine tuples with pointers and unions, you can get away with tuples. This is however not recommended. Your tree is going to be your central abstraction, exposing such low level details as pointers and unions is counterproductive and should be avoided. The C++ way is to write a class, stick to it.
It's unreal, since result of typeid().name is implementation-defined.
const char* name() const noexcept;
Returns: An implementation-defined ntbs.
However, here, you cannot use ternary operator, since calc(l_child) will be evaluated at compile-time, so if l_child is not tuple, compilation will be failed.
You can use some type-traits (or overloading), since tuple members are known at compile-time.
int calc(int value)
{
return value;
}
template<typename Left, typename Right>
int calc(const std::tuple<char, Left, Right>& tuple)
{
char symbol = std::get<0>(tuple);
Left l_child = std::get<1>(tuple);
Right r_child = std::get<2>(tuple);
int l = calc(l_child);
int r = calc(r_child);
return l /*symbol*/, r;
}
Live example

D2: std.algorithm.indexOf doesn't work anymore

I posted the following code on rosettacode.org for the task of converting Arabic and Roman numerals.
import std.regex, std.array, std.algorithm;
immutable {
int[] weights = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
string[] symbols = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX",
"V", "IV", "I"];
}
string toRoman(int n) {
auto app = appender!string;
foreach (i, w; weights) {
while (n >= w) {
app.put(symbols[i]);
n -= w;
}
if (n == 0) break;
}
return app.data;
}
int toArabic(string s) {
int arabic;
foreach (m; match(s, "CM|CD|XC|XL|IX|IV|[MDCLXVI]")) {
arabic += weights[symbols.indexOf(m.hit)];
}
return arabic;
}
It used to work just fine, but now I get a compiler error.
Error: template
std.algorithm.indexOf(alias pred = "a
== b",R1,R2) if (is(typeof(startsWith!(pred)(haystack,needl
e)))) does not match any function
template declaration
According to the documentation indexOf is deprecated, and countUntil should be used in stead, but it gives me the same error.
Long story but I'll try to keep it short:
std.algorithm.indexOf expects an input range, which is a structural type that must define front, popFront() and empty. For arrays, these methods are defined in std.array and work via uniform function call syntax, which allows fun(someArray) to work the same as someArray.fun().
immutable string[] is not an input range, since popFront removes the first element of the array, which cannot be done for an immutable type. The fact that this used to work was a bug.
I've updated the Rosetta Code entry to change symbols to an immutable(string)[]. Here, the elements of symbols are immutable, but the array may be sliced and reassigned. For example:
void main() {
immutable string[] s1 = ["a", "b", "c"];
immutable(string)[] s2 = ["d", "e", "f"];
s2 = s2[1..$]; // This is what std.array.popFront does under the hood.
assert(s2 == ["e", "f"]); // Passes.
s2[1] = "g"; // Error: Can't modify immutable data.
s1 = s1[1..$]; // Error: Can't modify immutable data.
s1[1] = "g"; // Error: Can't modify immutable data.
}
immutable string[] is implicitly convertible to immutable(string)[] but implicit function template instantiation (often denoted IFTI; this is what's used to instantiate the indexOf template) is not smart enough try this.
I believe this is a bug in std.algorithm. If you remove the immutable qualifier, the code works as is. I think indexOf/countUntil should work on immutable arrays, but at the moment it does not.
You can make them manifest constants (precede each declaration with enum) and it appears to work. Amusingly, this may also be a bug.
Apologies for the breakage; I introduced it. I concur with dsimcha's description and proposed fix.
We are considering a simple change to the language to account for this simple case. That would automatically peel off one level of qualifiers when passing a value of a qualified type into a function. By that (for now hypothetical) rule, qualifier(T[]) would become (when passed to a function) qualifier(T)[] and qualifier(T*) would become qualifier(T)*. This would allow your example to work. The disadvantage is that a function would not be able to distinguish the top-level qualifier but I believe that that does not harm any concrete use.