• Forum
  • Lounge
  • Strongly-typed Duck-typed language, does

 
Strongly-typed Duck-typed language, does it exist?

Go by Google is looking pretty good, in fact it is 90% satisfactory for me, but it isn't really intended for making games, which is what I would want to do with it.

Any ideas?
C#?
Can you show me an example of Duck-typing in C#? I didn't know C# could do this.
Ah, it seems I misunderstood Duck-typing slightly - I would need to be able to add Duck capabilities to an existing type. Oh well. Thanks though, I can think of lots of uses for this :)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <ostream>

class Duck {
public:
    void quack() const {std::cout << "Quaaaaaack!" << std::endl;}
    void feathers() const {std::cout << "The duck has white and gray feathers." << std::endl;}
};

class Person {
public:
    void quack() const {std::cout << "The person imitates a duck." << std::endl;}
    void feathers() const {std::cout << "The person takes a feather from the ground and shows it." << std::endl;}
};

#define IN_THE_FOREST_OF_C(d) do {\
    d.quack();\
    d.feathers();\
} while (false)

template <typename Duck>
void in_the_forest_of_cpp(const Duck &d)
{
    d.quack();
    d.feathers();
}

int main()
{
    Duck donald;
    Person john;

    IN_THE_FOREST_OF_C(donald);
    IN_THE_FOREST_OF_C(john);
    in_the_forest_of_cpp(donald);
    in_the_forest_of_cpp(john);
}
Last edited on
@Catfish3
Duck typing doesn't work that way. Or are you just making fun?
Any ideas?

Objective-C
@Abramus doesn't it? That looks very much like the example on Wikipedia.
But where's dynamic? There's no duck typing without dynamic. In the code above all calls are resolved at compile time.

Spot the difference:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <map>

struct Any
{
   struct AnyData
   {
      virtual AnyData *clone() = 0;
      virtual ~AnyData(){}
   };

   template <typename T>
   struct ConcreteData : public AnyData
   {
      T data;
      ConcreteData(const T & val){ data = val; }
      virtual ConcreteData *clone() { return new ConcreteData(data); }
      virtual ~ConcreteData(){}
   };

   AnyData *ptr;

   template <typename T> T & get(){ return static_cast<ConcreteData<T> *>(ptr)->data; }
   template <typename T> Any(const T & val){ ptr = new ConcreteData<T>(val); }

   Any(){ ptr = new ConcreteData<int>(0); }
   Any(const Any & other){ ptr = other.ptr->clone(); }
   Any &operator=(const Any & other){ delete ptr; ptr = other.ptr->clone(); }
   ~Any(){ delete ptr; }
};

struct Map
{
   std::map<const char *, Any> data;

   template <typename T> T & get(const char *key){ return data[key].get<T>(); }
   template <typename T> Map & put(const char *key, const T & val){ data[key] = Any(val); return *this; }
};

typedef Any (*Action)(Map & args);

struct Object
{
   Map data;

   Object(const Map & init){ data = init; }

   template <typename T> T & get(const char *name){ return data.get<T>(name); }

   Any call(const char *name, const Map & args = Map())
   {
      Action action = get<Action>(name);
      Map argsPlusSelf(args);
      argsPlusSelf.put("self", this);
      return (*action)(argsPlusSelf);
   }
};

////////////////////////////////////////////////////////////////////////////////

#include <cstdio>

Any goblinPrintHealth(Map & args)
{
   printf("Goblin's health: %d\n", args.get<Object*>("self")->get<int>("health"));
   return Any(0);
}

Any goblinAttack(Map & args)
{
   printf("Goblin: Don't kill me please! I'll be nice, promise!\n");
   return Any(0);
}

Any trollAttack(Map & args)
{
   printf("Troll: Aaaarrrrggghhhhhhhh!!!\n");
   args.get<Object*>("other")->get<int>("health") -= args.get<Object*>("self")->get<int>("power");
   return Any(0);
}

Object goblin(Map()
   .put("printHealth", &goblinPrintHealth)
   .put("attack", &goblinAttack)
   .put("health", 10));

Object troll(Map()
   .put("attack", &trollAttack)
   .put("health", 500)
   .put("power", 200));

int main()
{
   goblin.call("printHealth");
   goblin.call("attack", Map().put("other", &troll));
   troll.call("attack", Map().put("other", &goblin));
   goblin.call("printHealth");
   return 0;
}

Goblin's health: 10
Goblin: Don't kill me please! I'll be nice, promise!
Troll: Aaaarrrrggghhhhhhhh!!!
Goblin's health: -190

(I know it's unbelievably verbose, but C++ is statically typed language after all.)

EDIT: Real implementation should probably handle cases when an attribute is not found, and when its value is of unexpected type.
Last edited on
Well, at least you got the low-level details right.
I don't know if you heard this before, but 90% (or something) of communication is not verbal. This can be a problem if, for example, you can only communicate through text.

The reason I'm saying this is that I believe you need to work on your ability to write clear and understandable posts. Because I can only guess what you're trying to say. Is this an attempt to attack my argument? My code? You're trying to be funny? Sarcastic? Or you seriously believe that the difference I pointed out is not important?

Anyway, when I comes to the code: When I read this topic I thought it could be fun to try real duck typing in a language completely not suitable for this technique. So I produced my first C++ snippet since July (or something). Enjoy!
Last edited on
I don't see how you're being offended by Catfish o_o

Anyway, Duck-typing actually isn't as suitable for my purposes as I originally thought; this relies on methods pre-existing to match interfaces, whereas I need to add new methods to fit interfaces at runtime.
Anyway, Duck-typing actually isn't as suitable for my purposes as I originally thought; this relies on methods pre-existing to match interfaces, whereas I need to add new methods to fit interfaces at runtime.

Isn't Lisp code able to modify itself?

Anyway, so you want plugins that extend by logic and not just by content?
Then put the logic part in a plugin script, written in your own scripting language, no?

Otherwise, please explain again what you want to achieve.
Catfish3 wrote:
Isn't Lisp code able to modify itself?
I want to see a good 3D game in Lisp using object-oriented practices ;)

Catfish3 wrote:
Anyway, so you want plugins that extend by logic and not just by content?
I do not understand what you mean by this?

Catfish3 wrote:
Then put the logic part in a plugin script, written in your own scripting language, no?
I'm considering making the entire plugin (besides resources, etc.) be the script file(s).

Catfish3 wrote:
Otherwise, please explain again what you want to achieve.
That usually doesn't work.
Topic archived. No new replies allowed.