Code-reivew/big-picture-how-to Dart questions

93 views
Skip to first unread message

Daniel Davidson

unread,
Apr 22, 2014, 10:34:53 AM4/22/14
to
I get my specific "How do I ..." questions answered on SO. I get my bug/feature related questions answered on Dart Misc/Dart Web. But, where is the best place to go to get more general purpose guidelines? I placed this question on codereview SE: How to provide core functionality orthogonal to business logic in Dart. It is my first question there, so I did not have the required rep to add [dart] as a new tag. 

Is that a good place to go for this type of question? Maybe not since [dart] has not been established there so there will likely not be many viewers :-)
Anyway would appreciate feedback on the question if any Dartisans have feedback.

Thanks,
Dan

Alex Tatumizer

unread,
Apr 22, 2014, 12:10:17 PM4/22/14
to mi...@dartlang.org
When you compute hashCode, e.g.
result = result*prime + date.hashCode;
you need to apply mask to prevent going beyond smi:
const MASK=(1<<31)-1;
result = ((result*prime)&MASK + date.hashCode)&MASK;

I think it would be a good idea for dart to provide some standard function to help compute hashCode.
There's an issue for this: https://code.google.com/p/dart/issues/detail?id=3597

Because hashCode is expensive, you better cache it in your Trade object.

What is overkill and what is not - depends on taste. To me, both TradeBuilder and TradeType look unnecessary.
For trade type, I would use just strings "buy" and "sell".
(There's a plan to introduce enum types in dart, then it will be easier. Right now, it's too much code for basically nothing)

Please note that for every advice, somebody else can give you the opposite advice :-)


Justin Fagnani

unread,
Apr 22, 2014, 1:33:23 PM4/22/14
to General Dart Discussion
On Tue, Apr 22, 2014 at 9:10 AM, Alex Tatumizer <tatu...@gmail.com> wrote:
When you compute hashCode, e.g.
result = result*prime + date.hashCode;
you need to apply mask to prevent going beyond smi:
const MASK=(1<<31)-1;
result = ((result*prime)&MASK + date.hashCode)&MASK;

I think it would be a good idea for dart to provide some standard function to help compute hashCode.
There's an issue for this: https://code.google.com/p/dart/issues/detail?id=3597

quiver.core has a nice Jenkins Hash implementation: http://google.github.io/quiver-dart/#quiver/quiver-core

Because hashCode is expensive, you better cache it in your Trade object.

What is overkill and what is not - depends on taste. To me, both TradeBuilder and TradeType look unnecessary.
For trade type, I would use just strings "buy" and "sell".
(There's a plan to introduce enum types in dart, then it will be easier. Right now, it's too much code for basically nothing)

Please note that for every advice, somebody else can give you the opposite advice :-)


--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.

Alex Tatumizer

unread,
Apr 22, 2014, 2:58:18 PM4/22/14
to mi...@dartlang.org
I looked into quiver, it's full of useful methods that were supposed to be part of dart core, but they are not.
Is the fine line separating the two defined somewhere?
Good luck googling for any of those methods. Is it a fault of JSON format used in dartdoc?


Daniel Davidson

unread,
Apr 22, 2014, 3:27:22 PM4/22/14
to mi...@dartlang.org


On Tuesday, April 22, 2014 11:10:17 AM UTC-5, Alex Tatumizer wrote:
When you compute hashCode, e.g.
result = result*prime + date.hashCode;
you need to apply mask to prevent going beyond smi:
const MASK=(1<<31)-1;
result = ((result*prime)&MASK + date.hashCode)&MASK;


Good catch. I will either add it like you suggest, or work to use the _combine function suggested by quiver. I believe they are very similar. Quick question regarding impact of this bug: Is leaving off the mask something that will cause *incorrect* results or just something that will reduce dispersion and therefore effectiveness of the hash? 
 
I think it would be a good idea for dart to provide some standard function to help compute hashCode. 
There's an issue for this: https://code.google.com/p/dart/issues/detail?id=3597

Because hashCode is expensive, you better cache it in your Trade object.

What is overkill and what is not - depends on taste. To me, both TradeBuilder and TradeType look unnecessary.
For trade type, I would use just strings "buy" and "sell".
(There's a plan to introduce enum types in dart, then it will be easier. Right now, it's too much code for basically nothing)


Looking forward to enum addition. I'll keep the TradeType since I'll add ShortSale type in future. Plus this paradigm as outlined on SO gives errors in checked mode if incorrect values used.
 
Thanks
Dan

Alex Tatumizer

unread,
Apr 22, 2014, 3:37:01 PM4/22/14
to mi...@dartlang.org
> Is leaving off the mask something that will cause *incorrect* results or just something that will reduce dispersion and > therefore effectiveness of the hash?

in dart VM, the only impact is performance degradation (but it can be harsh).
If you compile to js (without &MASK), then least significant bits can be lost (that is, you get a not so good hashCode, which may (or may not) cause performance degradation (depends) but program is supposed to work anyway.

Daniel Davidson

unread,
Apr 22, 2014, 3:59:46 PM4/22/14
to mi...@dartlang.org

I think it would be a good idea for dart to provide some standard function to help compute hashCode.
There's an issue for this: https://code.google.com/p/dart/issues/detail?id=3597

quiver.core has a nice Jenkins Hash implementation: http://google.github.io/quiver-dart/#quiver/quiver-core

Ok - I am using quiver but was at 0.13.0. If I understand correctly I could implement my hash as below and the mask issue would be solved.

  int get hashCode =>
    hashObjects([ date, symbol, tradeType, quantity, price ]);

Why would _combine and _finish be hidden - just to prevent misuse or concern over common names? If they were public, I imagine I could do this - since I'm using code generation anyway - and avoid multiple unneeded list creations. Is even thinking this way premature optimization?

  int get hashCode =>
    finishHash(
    combineHash(date,
    combineHash(symbol,
    combineHash(tradeType,
    combineHash(quantity,
    combineHash(0, price))))));
 
Thanks
Dan

Alex Tatumizer

unread,
Apr 22, 2014, 4:13:37 PM4/22/14
to mi...@dartlang.org
Exposing this function won't be a good idea because there are algorithms (e.g. based on CRC32 instruction) capable of quickly computing hashcode for long chunks of data. In this case, combining 2 at a time would not be as efficient.
I can't speak for quiver's authors though, but this reason alone would be enough.
See http://code.google.com/p/cityhash/

Daniel Davidson

unread,
Apr 22, 2014, 4:41:41 PM4/22/14
to mi...@dartlang.org
I'm not seeing the relationship between cityhash and this case. Here we are just combining hashes of fields in a class - which I think is a good use for the quiver functions. Not sure how one would misuse those, other than forgetting to finish.

Alan Knight

unread,
Apr 22, 2014, 4:58:57 PM4/22/14
to General Dart Discussion
Do you expect to have different instances of trades that you want to be treated as equal? If you do, it seems like a good idea to give them an id so that they're unambiguous, and then the hashCode and equality could just compare those. If you don't, you could just leave hashCode and equality as the default.


Daniel Davidson

unread,
Apr 22, 2014, 5:07:07 PM4/22/14
to mi...@dartlang.org
I think I addressed that in the original question. I think you are correct - but I have no id or id generator and am fine assuming trades with all the same fields are the same. So in the context of a given set of trades the same trade can not happen twice (not exactly reality). Part of my questioning is to try to identify the Dart patterns and trade-offs.

Can you really accept hashCode and equality as default if you want them as a key in a hash? I was under impression that would not work.

Alex Tatumizer

unread,
Apr 22, 2014, 5:26:25 PM4/22/14
to mi...@dartlang.org
> I'm not seeing the relationship between cityhash and this case
Simple example: you have 4 hashcodes for individual fields, and want to compute hashCode of this 4-tuple.
Put it in array and call city. It will do the job efficiently in one call. It may result in better hash code, plus will run faster (especially if it utilizes fast processor instructions). Doing the same in 5 or 6 calls will not be as good/fast.
The issue is of purely academic interest in your case, but in general, it might matter.

Alan Knight

unread,
Apr 22, 2014, 8:19:04 PM4/22/14
to General Dart Discussion
They will work if what you want is identity semantics. So if you write

var a = new Trade(<some stuff>);
var b = new Trade(<some stuff>);
print(a == b);

If you want the answer to be true, assuming that <some stuff> is the same, then you need to implement equality, and if you want to use them as keys in a map or in a set, then you need to implement hashCode. If you're ok with the answer being false, then you don't. So if you expect to copy instances, or read them from a file and then compare them to others, you need to implement those.



Reply all
Reply to author
Forward
0 new messages