digitalmars.D - std.digest: can we get rid of start() functions?
- Piotr Szturmaj (17/17) Oct 10 2012 And replace them with global reset function:
- Marco Leise (15/37) Oct 10 2012 Unlike classes, structs don't mandate a ctor call, so in
- Piotr Szturmaj (5/12) Oct 10 2012 I know, but in case of digests their init data is always known at
- Johannes Pfau (20/52) Oct 10 2012 There's makeDigest which calls start for you, so you can write code
- Marco Leise (11/18) Oct 10 2012 Just this point, I think it adds mental bloat. It is
- H. S. Teoh (30/49) Oct 10 2012 [...]
- Piotr Szturmaj (2/8) Oct 10 2012 In my proposal reset() does exactly the same.
- H. S. Teoh (7/18) Oct 10 2012 My point was that there's no need to remember that there's a method
And replace them with global reset function: void reset(T)(ref T digest) if (isDigest!T) { digest = T.init; } Current usage: SHA1 sha1; sha1.start(); ... calculate hash sha1.start(); // start again ... calculate hash New usage: SHA1 sha1; ... calculate hash sha1.reset(); // start egain ... calculate hash
Oct 10 2012
Am Wed, 10 Oct 2012 12:55:59 +0200 schrieb Piotr Szturmaj <bncrbme jadamspam.pl>:And replace them with global reset function: void reset(T)(ref T digest) if (isDigest!T) { digest = T.init; } Current usage: SHA1 sha1; sha1.start(); ... calculate hash sha1.start(); // start again ... calculate hash New usage: SHA1 sha1; ... calculate hash sha1.reset(); // start egain ... calculate hashUnlike classes, structs don't mandate a ctor call, so in general you need to disguise the constructor as 'start()' 'Create()' or similar, where T.init is not sufficient. If on the other hand, you use a ".isInitialized = false" field instead of start(), then you'd have to unnecessarily check that every time data is added to the digest, instead of doing it once. (That might be personal taste though :) ) I think the constraints are: * no start() method ever takes arguments * no digest needs to allocate to start * no digest depends on global/static variables -- Marco
Oct 10 2012
Marco Leise wrote:Unlike classes, structs don't mandate a ctor call, so in general you need to disguise the constructor as 'start()' 'Create()' or similar, where T.init is not sufficient.I know, but in case of digests their init data is always known at compile time, hence no special "constructor" is needed.I think the constraints are: * no start() method ever takes arguments * no digest needs to allocate to start * no digest depends on global/static variablesYes, these constraints do not prevent digest structs to be correctly initialized after declaration.
Oct 10 2012
Am Wed, 10 Oct 2012 15:02:40 +0200 schrieb Marco Leise <Marco.Leise gmx.de>:Am Wed, 10 Oct 2012 12:55:59 +0200 schrieb Piotr Szturmaj <bncrbme jadamspam.pl>:There's makeDigest which calls start for you, so you can write code like this: auto sha1 = makeDigest!SHA1(); //calculate hash sha1.start(); //start again //calculate hash... But the digests still have to implement a start method, even if it's only a "this = typeof(this).init;". Maybe we could avoid the start method by introducing a fallback UFCS start method...And replace them with global reset function: void reset(T)(ref T digest) if (isDigest!T) { digest = T.init; } Current usage: SHA1 sha1; sha1.start(); ... calculate hash sha1.start(); // start again ... calculate hashUnlike classes, structs don't mandate a ctor call, so in general you need to disguise the constructor as 'start()' 'Create()' or similar, where T.init is not sufficient. If on the other hand, you use a ".isInitialized = false" field instead of start(), then you'd have to unnecessarily check that every time data is added to the digest, instead of doing it once. (That might be personal taste though :) ) I think the constraints are: * no start() method ever takes arguments * no digest needs to allocate to start * no digest depends on global/static variablesYes, that's the main reason why we have 'start', but it also must work as a reset function. The difficult question is whether there actually is a hash algorithm (or whether there will be one in the future) which needs such a complex start method. No-allocation often means no C wrapper (although a C API could allow to use stack objects, but often they just provide opaque structs), so this is a little controversial. But if we allowed allocation we'd have to worry about deallocation as well and then things get tricky. Reference counting is probably still the easiest solution for those cases.
Oct 10 2012
Am Wed, 10 Oct 2012 16:28:36 +0200 schrieb Johannes Pfau <nospam example.com>:There's makeDigest which calls start for you, so you can write code like this: auto sha1 = makeDigest!SHA1(); //calculate hash sha1.start(); //start again //calculate hash...Just this point, I think it adds mental bloat. It is still easier to remember and shorter to use: SHA1 sha1; sha1.start(); //calculate hash sha1.start(); //calculate hash... -- Marco
Oct 10 2012
On Wed, Oct 10, 2012 at 05:16:38PM +0200, Marco Leise wrote:Am Wed, 10 Oct 2012 16:28:36 +0200 schrieb Johannes Pfau <nospam example.com>:[...] What makes it so difficult that we cannot do this: struct MyHash { bool is_init = false; ... void init() { ... is_init = true; } void computeHash(...) { if (!is_init) init(); // Continue as usual ... } } Then you could just write: SHA1 sha1; // calculate hash sha1 = SHA1.init; // calculate hash ... Fits in better with the language, and no need to remember to call start(), which adds mental load 'cos you have to remember it's called "start" and not something else, and it's also is error-prone 'cos people will forget to do it. T -- Famous last words: I wonder what will happen if I do *this*...There's makeDigest which calls start for you, so you can write code like this: auto sha1 = makeDigest!SHA1(); //calculate hash sha1.start(); //start again //calculate hash...Just this point, I think it adds mental bloat. It is still easier to remember and shorter to use: SHA1 sha1; sha1.start(); //calculate hash sha1.start(); //calculate hash...
Oct 10 2012
H. S. Teoh wrote:Then you could just write: SHA1 sha1; // calculate hash sha1 = SHA1.init; // calculate hash ...In my proposal reset() does exactly the same.
Oct 10 2012
On Wed, Oct 10, 2012 at 06:21:10PM +0200, Piotr Szturmaj wrote:H. S. Teoh wrote:My point was that there's no need to remember that there's a method called "start" or "reset", etc., when we can just use .init which is common to all types in D. It reduces cognitive load. T -- EMACS = Extremely Massive And Cumbersome SystemThen you could just write: SHA1 sha1; // calculate hash sha1 = SHA1.init; // calculate hash ...In my proposal reset() does exactly the same.
Oct 10 2012