www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - C++ to D

reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
Hi.
How to rewrite this in D to the handler method for the input 
parameter was determined on average in O(1)?

#include <string>
#include <iostream>
#include <functional>
#include <unordered_map>

class A
{
public:
     void foo(const std::string &s);

protected:
     void foo1(const std::string &s);
     void foo2(const std::string &s);
     void foo3(const std::string &s);

     std::string m_buf;
};

int main()
{
     A a;
     a.foo("first");
     a.foo("second");
     a.foo("third");
}

void A::foo(const std::string &s)
{
     using func = std::function < void(A &, const std::string &) >;
     static const std::unordered_map<std::string, func> handlers =
     {
         { "first",  std::mem_fn(&A::foo1) },
         { "second", std::mem_fn(&A::foo2) },
         { "third",  std::mem_fn(&A::foo3) }
     };

     const auto cit = handlers.find(s);
     if (cit != handlers.cend())
         cit->second(*this, s);

     m_buf += s + ' ';
}

void A::foo1(const std::string &s)
{
     std::cout << s << std::endl;    // prints first
}

void A::foo2(const std::string &s)
{
     std::cout << std::string(s.rbegin(), s.rend()) << std::endl;  
   // prints dnoces
}

void A::foo3(const std::string &s)
{
     std::cout << s << ", " << m_buf << std::endl;    // prints 
third, first second
}
Mar 11 2015
next sibling parent reply "Kagamin" <spam here.lot> writes:
A hash table? See http://dlang.org/hash-map.html
Mar 11 2015
parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Wednesday, 11 March 2015 at 16:08:22 UTC, Kagamin wrote:
 A hash table? See http://dlang.org/hash-map.html
That is, the input is a string and, depending on what word it contains, is called one of the three methods of the class that this line handles. And this happens in average constant time (for hash). An associative array where the key is a string and value is a function.
Mar 11 2015
next sibling parent reply "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
The same without classes in Lisp:

(define (foo)
   (let ((foo1 (lambda (s) s))
         (foo2 (lambda (s) (list->string (reverse (string->list 
s)))))
         (foo3 (lambda (s) (string-append s ", " s " "))))
     (lambda (in)
       (match in
         ("first" foo1)
         ("second" foo2)
         ("third" foo3)
         (_ void)))))

(define (main)
   (define bar (foo))

   (for/list ([i '("first" "second" "third")])
     ((bar i) "poor c++")))
Mar 11 2015
parent reply FG <home fgda.pl> writes:
On 2015-03-11 at 18:27, Dennis Ritchie wrote:
 The same without classes in Lisp:
 [...]
And your point was...? I take it, "poor c++" is a hint. Don't compare apples to oranges.
Mar 11 2015
next sibling parent "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
Thank you very much, Ali Çehreli and FG.
Mar 11 2015
prev sibling parent "Dennis Ritchie" <dennis.ritchie mail.ru> writes:
On Wednesday, 11 March 2015 at 18:10:55 UTC, FG wrote:
 And your point was...?  I take it, "poor c++" is a hint.
 Don't compare apples to oranges.
No, I forgot to remove from the foreign code.
Mar 11 2015
prev sibling parent FG <home fgda.pl> writes:
On 2015-03-11 at 17:42, Dennis Ritchie wrote:
 On Wednesday, 11 March 2015 at 16:08:22 UTC, Kagamin wrote:
 A hash table? See http://dlang.org/hash-map.html
That is, the input is a string and, depending on what word it contains, is called one of the three methods of the class that this line handles. And this happens in average constant time (for hash). An associative array where the key is a string and value is a function.
Yeah, lookup in D's associative arrays is generally O(1). Here's the D version of your C++ code. A bit modified, to be more practical, i.e. you can register hooks yourself and not have them hard-coded into the class. import std.stdio, std.range; class A { alias Hook = void function(ref A, string); string m_buf; Hook[string] handlers; void foo(string s) { if (auto p = s in handlers) (*p)(this, s); m_buf ~= s ~ " "; } void register(string name, Hook hook) { handlers[name] = hook; } } void foo1(ref A a, string s) { writeln(s); } void foo2(ref A a, string s) { writeln(s.retro); } void foo3(ref A a, string s) { writeln(s, ", ", a.m_buf); } void main() { A a = new A; a.register("first", &foo1); a.register("second", &foo2); a.register("third", &foo3); a.foo("first"); a.foo("second"); a.foo("third"); }
Mar 11 2015
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/11/2015 07:33 AM, Dennis Ritchie wrote:

 How to rewrite this in D to the handler method for the input parameter
 was determined on average in O(1)?
D's associative arrays are hash tables. The following program is as similar to the C++ one as possible: import std.stdio; import std.range; class A { public: alias Func = void delegate(A, string); static const Func[string] handlers; static this() { handlers = [ "first" : (A a, string b) => a.foo1(b), "second" : (A a, string b) => a.foo2(b), "third" : (A a, string b) => a.foo3(b) ]; } void foo(string s) { const handler = s in handlers; if (handler) { (*handler)(this, s); } m_buf ~= s ~ ' '; } protected: void foo1(string s) { writeln(s); } void foo2(string s) { writeln(s.retro); } void foo3(string s) { writefln("%s, %s", s, m_buf); } string m_buf; } void main() { auto a = new A(); a.foo("first"); a.foo("second"); a.foo("third"); } Ali
Mar 11 2015