Re: T[][T] - [(k1, v1), ..., (k1, vn), ..., (kn, v1), ..., (kn, vn)]
On Thursday, 13 February 2014 at 11:00:17 UTC, Tobias Pankrath wrote: I've got a hash map T[][T] with keys of T and values of T[]. For some reason, I'll need a range of tuples (t1, t2), where t1 is a key and t2 is an element of the array t1 maps to. To have them in order would be great, but is not necessary. I just wrote my own range type and it works. But I wonder how would I do it with phobos utilities? A byPair range has been proposed long ago: https://d.puremagic.com/issues/show_bug.cgi?id=5466 I came up with this: int[][int] hash = [1 :[1,2,3,4], 2:[3,1,2,3], 4:[2,3,1,3]]; auto x = hash.keys.map!(x = tuple(x, hash[x])) .map!(x = zip(repeat(x[0]), x[1])); Is there any other way to create a range of simple (key,value) pairs for the array, but needs to allocate (hash.keys return an array of keys) and then again look up every key. import std.algorithm : zip; import std.traits: isAssociativeArray; auto byKeyValuePair(AA)(AA aa) if (isAssociativeArray!AA) { return zip(aa.byKey, aa.byValue); }
Re: T[][T] - [(k1, v1), ..., (k1, vn), ..., (kn, v1), ..., (kn, vn)]
Is there any other way to create a range of simple (key,value) pairs for the array, but needs to allocate (hash.keys return an array of keys) and then again look up every key. import std.algorithm : zip; import std.traits: isAssociativeArray; auto byKeyValuePair(AA)(AA aa) if (isAssociativeArray!AA) { return zip(aa.byKey, aa.byValue); } That byKey and byValue adhere to the same order is not backed up by the documenation, I suppose?
Re: T[][T] - [(k1, v1), ..., (k1, vn), ..., (kn, v1), ..., (kn, vn)]
Tobias Pankrath: That byKey and byValue adhere to the same order is not backed up by the documenation, I suppose? Right. It's a bet (unlike in Python, that has this rule in the docs). Bye, bearophile
Re: T[][T] - [(k1, v1), ..., (k1, vn), ..., (kn, v1), ..., (kn, vn)]
On Thursday, 13 February 2014 at 12:30:29 UTC, bearophile wrote: Tobias Pankrath: That byKey and byValue adhere to the same order is not backed up by the documenation, I suppose? Right. It's a bet (unlike in Python, that has this rule in the docs). Yup. And given how Walter and Andrei don't like breaking code, we should just previde enough usage so it would become a rule too :D
Re: T[][T] - [(k1, v1), ..., (k1, vn), ..., (kn, v1), ..., (kn, vn)]
Stanislav Blinov: Yup. And given how Walter and Andrei don't like breaking code, we should just previde enough usage so it would become a rule too :D That's not the rational way a language should be designed. Tester Driven Development (http://en.wikipedia.org/wiki/Tester_driven_development ) is bad enough already. Bye, bearophile
Re: T[][T] - [(k1, v1), ..., (k1, vn), ..., (kn, v1), ..., (kn, vn)]
On Thursday, 13 February 2014 at 12:43:00 UTC, bearophile wrote: Stanislav Blinov: Yup. And given how Walter and Andrei don't like breaking code, we should just previde enough usage so it would become a rule too :D That's not the rational way a language should be designed. Tester Driven Development (http://en.wikipedia.org/wiki/Tester_driven_development ) is bad enough already. I did put a smiley in there, right? My comment was a joke ;) It's just that often the desire to not break code adheres to that very pattern :(
Re: T : T*
On 13/04/2012 19:47, Jonathan M Davis wrote: I'd just like to verify that my understanding of T : T* in this template is correct: struct S(T : T*) snip it appears that the compiler is instead taking this to mean that the pointer part of the type should be stripped from the template argument's type. snip Yes. It's more or less syntactic saccharin for struct S(U : T*, T) { T t; } Stewart.
Re: T : T*
On Friday, April 13, 2012 14:47:45 Jonathan M Davis wrote: I'd just like to verify that my understanding of T : T* in this template is correct: struct S(T : T*) { T t; } It's my understanding that it's requiring that the template argument be implicitly convertible to a pointer to that type. However, as this stackoverflow question shows: http://stackoverflow.com/questions/10145779/why-this-template-parameters- constraint-doesnt-work it appears that the compiler is instead taking this to mean that the pointer part of the type should be stripped from the template argument's type. Given some of the bizarre stuff that happens with is expressions and the like, it's not out of the question that I'm just misunderstanding what the compiler is supposed to do with T : T* in this case (though I don't think so), so I'd like to verify it. Okay. Clearly, I'm misunderstanding this, because std.traits.pointerTarget uses this idiom: template pointerTarget(T : T*) { alias T pointerTarget; } Anyone know _why_ it works this way? - Jonathan M Davis
Re: T : T*
On Friday, 13 April 2012 at 18:47:55 UTC, Jonathan M Davis wrote: I'd just like to verify that my understanding of T : T* in this template is correct: struct S(T : T*) { T t; } It's my understanding that it's requiring that the template argument be implicitly convertible to a pointer to that type. However, as this stackoverflow question shows: http://stackoverflow.com/questions/10145779/why-this-template-parameters- constraint-doesnt-work it appears that the compiler is instead taking this to mean that the pointer part of the type should be stripped from the template argument's type. Given some of the bizarre stuff that happens with is expressions and the like, it's not out of the question that I'm just misunderstanding what the compiler is supposed to do with T : T* in this case (though I don't think so), so I'd like to verify it. - Jonathan M Davis First, the argument type must match the form T*. The T can be any type; there is only one constraint here, the pointer head. So obviously, the argument type must be a pointer to anything to match T*, e.g. void*, shared(int)**, immutable(int)* etc. If it doesn't match, the template is dropped from the overload set. If it does match, the newly created symbol T refers to the role of T in the parameter specialization. For arguments void*, shared(int)** and immutable(int)*, that would be void, shared(int)* and immutable(int) respectively. Most forms of the `is` primary expression (IsExpression) are dedicated to allowing the same type inspection abilities (and some more) outside of template parameter lists, hence reading the documentation of IsExpression is a good idea [1]. In particular, it reveals that when the type specialization is dependent on the symbol identifier (e.g. there's a T in the T specialization) the resulting symbol refers to the deduced type; otherwise it is an alias of the type specialization, which explains the two uses you mention. [1] http://dlang.org/expression.html#IsExpression
Re: T : T*
On Friday, April 13, 2012 21:04:07 Jakob Ovrum wrote: First, the argument type must match the form T*. The T can be any type; there is only one constraint here, the pointer head. So obviously, the argument type must be a pointer to anything to match T*, e.g. void*, shared(int)**, immutable(int)* etc. If it doesn't match, the template is dropped from the overload set. If it does match, the newly created symbol T refers to the role of T in the parameter specialization. For arguments void*, shared(int)** and immutable(int)*, that would be void, shared(int)* and immutable(int) respectively. Most forms of the `is` primary expression (IsExpression) are dedicated to allowing the same type inspection abilities (and some more) outside of template parameter lists, hence reading the documentation of IsExpression is a good idea [1]. In particular, it reveals that when the type specialization is dependent on the symbol identifier (e.g. there's a T in the T specialization) the resulting symbol refers to the deduced type; otherwise it is an alias of the type specialization, which explains the two uses you mention. [1] http://dlang.org/expression.html#IsExpression Thanks for the info. Clearly, : does not mean quite the same thing in all cases (in particular, when the same template parameter is on both sides of it). - Jonathan M Davis