Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 31, 2016 Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Can someone please explain why the following assertion fails? import std.stdio; import std.conv; void main(string[] args) { auto x = 1; assert(hashOf(x.to!(string)) == hashOf(x.to!(string))); } Thanks. |
October 31, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On Monday, 31 October 2016 at 19:08:50 UTC, Gary Willoughby wrote:
> Can someone please explain why the following assertion fails?
>
> import std.stdio;
> import std.conv;
>
> void main(string[] args)
> {
> auto x = 1;
>
> assert(hashOf(x.to!(string)) == hashOf(x.to!(string)));
> }
>
> Thanks.
DMD64 D Compiler v2.072.0
Copyright (c) 1999-2016 by Digital Mars written by Walter Bright
Ubuntu 16.04
|
October 31, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On 10/31/2016 12:08 PM, Gary Willoughby wrote: > Can someone please explain why the following assertion fails? > > import std.stdio; > import std.conv; > > void main(string[] args) > { > auto x = 1; > > assert(hashOf(x.to!(string)) == hashOf(x.to!(string))); > } > > Thanks. Because it considers the .ptr property of arrays as well: https://github.com/dlang/druntime/blob/master/src/core/internal/hash.d#L61 //dynamic array hash size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStaticArray, T) && !is(T == struct) && !is(T == class) && !is(T == union)) { alias ElementType = typeof(val[0]); static if (is(ElementType == interface) || is(ElementType == class) || ((is(ElementType == struct) || is(ElementType == union)) && is(typeof(val[0].toHash()) == size_t))) //class or interface array or struct array with toHash(); CTFE depend on toHash() method { size_t hash = seed; foreach (o; val) { hash = hashOf(o, hash); } return hash; } else static if (is(typeof(toUbyte(val)) == const(ubyte)[])) //ubyteble array (arithmetic types and structs without toHash) CTFE ready for arithmetic types and structs without reference fields { auto bytes = toUbyte(val); return bytesHash(bytes.ptr, bytes.length, seed); // <-- HERE } else //Other types. CTFE unsupported { assert(!__ctfe, "unable to compute hash of "~T.stringof); return bytesHash(val.ptr, ElementType.sizeof*val.length, seed); } } Ali |
October 31, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 31 October 2016 at 19:24:13 UTC, Ali Çehreli wrote:
> On 10/31/2016 12:08 PM, Gary Willoughby wrote:
>> [...]
>
> Because it considers the .ptr property of arrays as well:
>
>
> https://github.com/dlang/druntime/blob/master/src/core/internal/hash.d#L61
>
> [...]
Ah right.
Is there an alternative built-in, generic, nogc hash function that would return the same values for Strings?
|
October 31, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On 10/31/2016 12:08 PM, Gary Willoughby wrote: > Can someone please explain why the following assertion fails? > > import std.stdio; > import std.conv; > > void main(string[] args) > { > auto x = 1; > > assert(hashOf(x.to!(string)) == hashOf(x.to!(string))); > } > > Thanks. I think you need TypeInfo.getHash. https://dlang.org/phobos/object.html#.TypeInfo.getHash import std.conv; auto myHashOf(T)(auto ref T value) { return typeid(T).getHash(&value); } void main() { auto x = 1; auto s = "1"; assert(myHashOf(x.to!string) == myHashOf(x.to!string)); assert(myHashOf(s) == myHashOf(s)); assert(myHashOf(s) == myHashOf(x.to!string)); } Ali |
November 01, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 31 October 2016 at 22:10:30 UTC, Ali Çehreli wrote:
> On 10/31/2016 12:08 PM, Gary Willoughby wrote:
>> Can someone please explain why the following assertion fails?
>>
>> import std.stdio;
>> import std.conv;
>>
>> void main(string[] args)
>> {
>> auto x = 1;
>>
>> assert(hashOf(x.to!(string)) == hashOf(x.to!(string)));
>> }
>>
>> Thanks.
>
> I think you need TypeInfo.getHash.
>
> https://dlang.org/phobos/object.html#.TypeInfo.getHash
>
> import std.conv;
>
> auto myHashOf(T)(auto ref T value) {
> return typeid(T).getHash(&value);
> }
>
> void main() {
> auto x = 1;
> auto s = "1";
> assert(myHashOf(x.to!string) == myHashOf(x.to!string));
> assert(myHashOf(s) == myHashOf(s));
> assert(myHashOf(s) == myHashOf(x.to!string));
> }
>
> Ali
Thanks but `TypeInfo.getHash` is not @nogc. Looks like I'll have to roll my own.
|
November 01, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On 10/31/16 3:08 PM, Gary Willoughby wrote:
> Can someone please explain why the following assertion fails?
>
> import std.stdio;
> import std.conv;
>
> void main(string[] args)
> {
> auto x = 1;
>
> assert(hashOf(x.to!(string)) == hashOf(x.to!(string)));
> }
>
> Thanks.
IMO, it shouldn't. A string's "value" has nothing to do with it's location.
-Steve
|
November 01, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 10/31/16 3:24 PM, Ali Çehreli wrote:
> On 10/31/2016 12:08 PM, Gary Willoughby wrote:
>> Can someone please explain why the following assertion fails?
>>
>> import std.stdio;
>> import std.conv;
>>
>> void main(string[] args)
>> {
>> auto x = 1;
>>
>> assert(hashOf(x.to!(string)) == hashOf(x.to!(string)));
>> }
>>
>> Thanks.
>
> Because it considers the .ptr property of arrays as well:
>
>
> https://github.com/dlang/druntime/blob/master/src/core/internal/hash.d#L61
>
> //dynamic array hash
> size_t hashOf(T)(auto ref T val, size_t seed = 0)
> if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) &&
> !__traits(isStaticArray, T)
> && !is(T == struct) && !is(T == class) && !is(T == union))
> {
> alias ElementType = typeof(val[0]);
> static if (is(ElementType == interface) || is(ElementType == class) ||
> ((is(ElementType == struct) || is(ElementType == union))
> && is(typeof(val[0].toHash()) == size_t)))
> //class or interface array or struct array with toHash(); CTFE
> depend on toHash() method
> {
> size_t hash = seed;
> foreach (o; val)
> {
> hash = hashOf(o, hash);
> }
> return hash;
> }
> else static if (is(typeof(toUbyte(val)) == const(ubyte)[]))
> //ubyteble array (arithmetic types and structs without toHash) CTFE
> ready for arithmetic types and structs without reference fields
> {
> auto bytes = toUbyte(val);
> return bytesHash(bytes.ptr, bytes.length, seed); // <-- HERE
bytesHash shouldn't use the pointer value in any way, it should just use the pointer to look at the bytes.
-Steve
|
November 01, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 1 November 2016 at 14:06:08 UTC, Steven Schveighoffer wrote: > On 10/31/16 3:08 PM, Gary Willoughby wrote: >> Can someone please explain why the following assertion fails? >> >> import std.stdio; >> import std.conv; >> >> void main(string[] args) >> { >> auto x = 1; >> >> assert(hashOf(x.to!(string)) == hashOf(x.to!(string))); >> } >> >> Thanks. > > IMO, it shouldn't. A string's "value" has nothing to do with it's location. > > -Steve It definitely is surprising. I'll raise an issue and see what others think. https://issues.dlang.org/show_bug.cgi?id=16654 |
November 01, 2016 Re: Can someone please explain why the following assertion fails? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 11/1/16 10:08 AM, Steven Schveighoffer wrote: > On 10/31/16 3:24 PM, Ali Çehreli wrote: >> Because it considers the .ptr property of arrays as well: >> >> [snip] >> return bytesHash(bytes.ptr, bytes.length, seed); // <-- HERE > > bytesHash shouldn't use the pointer value in any way, it should just use > the pointer to look at the bytes. And the issue is not there it is simpler than that. Here is the entire definition of hashOf (https://github.com/dlang/druntime/blob/master/src/object.d#L3176): size_t hashOf(T)(auto ref T arg, size_t seed = 0) { import core.internal.hash; return core.internal.hash.hashOf((cast(void*)&arg)[0 .. T.sizeof], seed); } Note that if arg is a string, then it's going to take the hash of the bytes that define the dynamic array pointer and length. Not at all what the user is expecting. Would be even more surprising for an object reference or pointer. I'm not sure what the bug is here. It's quite possible the intention is to provide a low-level primitive that avoids all hashing customization. However, to have it called hashOf, and then have another internal function called hashOf that does something different, is quite surprising and error prone. Indeed, I think Ali did not realize where the definition of hashOf was coming from. At the very least, the documentation needs updating. -Steve |
Copyright © 1999-2021 by the D Language Foundation