Generic programming question

Edit: Added a simpler example towards the end.
Edit: Added a C++ example for clarity towards the end.

Hey all,

Just started looking at SkookumScript recently. It seems like a cool language and I have high hopes for it reducing the amount of blueprints and C++ I might need to do.

Having said that, I’m a bit puzzled as to how I might go about this task I’ve set myself on.

I want to implement something akin to the c# event functionality. If I don’t care about type safety, this seems fairly straightforward, it would be something along these lines (pseudocode):

// Event class members:

@handlers List{ItemClass_}

! () Object
[
@handlers : {}
]

add_assign (ItemClass_ handler) List{ItemClass_}
[
  @handlers.append(handler)
  @handlers
]

// This should work fine so far as ItemClass is always just a single object.
// While not my main concern here, it would be nice to not have that restriction.
// For instance, to allow using handlers with signatures like (Integer i, String s).
// I am curious if there's a nice way to handle that?
invoke (ItemClass_ i)
[
  @handlers.do[item(i)]
]

subtract_assign (ItemClass_ handler) List{ItemClass_}
[
  @handlers.remove_same(handler)
  @handlers
]

So I could instantiate an Event, add some handlers to it, invoke it with some input.

The problem I have with this approach, though, is that the interface to the Event class hides the type.
Actually, it basically doesn’t care at all about the type.
That is to say, the below would compile despite the erroneous manner in which the types are used:

// In some method using an Event:
!e : Event!

e += (Actor a)[println("Actor name is: " a.name)]
e += (Integer i)[println("Integer value is: " i)]

// Though even if one of Actor or Integer were used, one of the added handlers would not work correctly,
// they really can't coexist.
e.invoke("oh look a string")

Ideally, I’d be able to instead do something like this and have type safety enforced. I’d like the below code to fail to compile when the wrong types are used:

// Specify that the Actor is the type to operate on.
!e : Event!(Actor)

// Ok because e is aware it should use Actor for its ItemClass_
e += (Actor a)[println("Actor name is: " a.name)]

// Fails to compile because e is aware it should use Actor for its ItemClass_
e += (Integer i)[println("Integer value is: " i)]

// Likewise fails to compile because again, not an Actor
e.invoke("oh look a string")

For a simpler example:

// Methods of a class "GenericClass"

// Specify a type to act on somehow...
!(<Object> type) Object
[
]

// The typed_print method should (somehow) determine its signature requires
// thing_to_print to be of the type specified in the constructor.

typed_print(type.class thing_to_print)
[
  println(thing_to_print)
]

// Usage:

// Create an instance of GenericClass that requires the type to be String, somehow...
!generic_class : GenericClass!(String)

// Should compile because the passed argument is of the correct type.
generic_class.typed_print("a string is fine")

// Should fail to compile because the passed argument is not of the correct type.
generic_class.typed_print(12345)

In C++

#include <iostream>
#include <string>

template <class T>
class GenericClass
{
  public GenericClass() {}

  public void typed_print(T thing_to_print)
  {
    std::cout << thing_to_print << std::endl;
  }
}


int main(int argc, char** argv)
{
  // Create an instance of GenericClass with std::string as its template parameter.
  GenericClass<std::string> generic_class;

  // Compiles because the passed argument is of the correct type, a std::string.
  generic_class.typed_print("A string is fine");

  // Fails to compile because the passed argument is not of the correct type.
  generic_class.typed_print(12345);
}

Is it possible to do something like this in SkookumScript?

Thank you for reading.