On Sat, 18 Apr 2009 21:43:15 +0400, Steven Schveighoffer <schvei...@yahoo.com> 
wrote:

On Fri, 17 Apr 2009 23:43:22 -0400, Steven Schveighoffer <schvei...@yahoo.com> wrote:

On Fri, 17 Apr 2009 21:54:52 -0400, Steven Schveighoffer <schvei...@yahoo.com> wrote:

Andrei wrote:
We are discussing a language extension. That language extension will allow a type to choose flexibility in defining methods dynamically, while being otherwise integrated syntactically with the current values. This has advantages, but also alters the expectations.

As long as it identifies what can be dynamic and what cannot. I can't imagine Walter will go for this with his strict view of hijacking.

Let me add that if there was a way for syntax to easily allow for unintentional calls to be translated to compile-time errors, I think this would be a workable solution.

For example, I don't have any problem with your Pascalize example, because you have not removed any static typing from the code (i.e. no unexpected noops or exceptions are built in). If there were some way to enforce this, then I think it would be a usable idea. For instance, if you only allow CTFE to specify a function that is called when certain strings are passed in, I don't have a problem with that, because you are simply dispatching the data to strongly typed functions at compile time, which provide compile-time errors when you mess up.

I gave this a lot of thought, and I think here is a possible solution:

the main reason I'm hesitant on this idea is because of code like this:

class X
{
   auto opDotExp(string fname, T...)(T args)
   {
      if(fname == "blah")
        return foo(args);
      else if(fname == "blither")
        return bar(args);
      // else, nothing happens
   }
}

Which leaves code open to lots of compiled code that doesn't do the right thing (or throws some runtime exception). What would be nice is if the default behavior is what statically bound functions do, that is, compile error, and only let the cases be handled which the author expects to handle.

For that, I think if we make the following rule, we will see much less code that is poorly written, and I think dynamic functions will be feasible:

If the compiler can determine during compilation of an opDotExp instance that the resulting function is empty, then it is a compiler error, just like if you tried to call a function that doesn't exist. This behavior can be overridden by putting a return statement in an otherwise empty function.

So for example, the above can be statically determined to compile to nothing if fname is not "blah" or "blither", and therefore would be a compiler error. Of course, if you call functions that are not statically evaluable, then you are back to the danger of truly dynamic bindings, but that would make sense for things that cannot be evaluated at compile time.

What do you think?

-Steve

Here is an example of a more sophisticated opDotExp use case that relies on its 
templated version:

A Wrapper struct is a simple wrapper around any arbitrary data. It fully 
encapsulates the underlying object and never gives it away.
A simple example is a reference-counter. You want this object to allow any 
operations on it, but you want to disallow raw object access.
"alias this" is very unsafe in this respect.

struct Wrapper(T)
{
  private T t;

  this(ref T obj) {
      _obj = obj; // capture. I believe there must be a better way to transfer 
ownership, but I don't know how
  }

  auto opDotExp(string fname, T...)(T args)
  {
      return t.opDotExp!(fname, T)(args); // how do you forward a call? Do all types have 
an implicit opDotExp method, i.e. for any given type T, T.bar == 
T.opDotExp("bar")?
  }
}

class Foo
{
   int bar() { return 42; }
   void baz(int n) { ... }
   // ...
}

auto o = Wrapper(new Foo());
int x = o.bar();
o.baz = -1;

Foo f = o; // disallowed!

It works by referring all the methods to an underlying object. You'll get a 
compile-time error if it doesn't have such method or property:

o.call(); // Error: no such method

That's a great functionality, and you can't do it if opDotExp was a runtime 
method.


Reply via email to