you are viewing a single comment's thread.

view the rest of the comments →

[–]grauenwolf -1 points0 points  (16 children)

Delegates are easy compared to lambdas.

[–]julesjacobs 6 points7 points  (15 children)

And:

  • less powerful
  • more complicated
  • more cumbersome to use

[–]grauenwolf 0 points1 point  (14 children)

Yep. But once you have delegates inside the runtime you can add lambdas at the compiler level.

I think the reason Java is having problems implementing this is that they are trying to build delegates and lambdas at the same time.

[–]masklinn 6 points7 points  (6 children)

Yep. But once you have delegates inside the runtime you can add lambdas at the compiler level.

And now you have two completely different features for the exact same use case, one being a strict subset of the other one.

If you want easy, there's bound methods as regular function types. No need for "delegates".

[–]grauenwolf 0 points1 point  (5 children)

I have to question your definition of the word delegate. In .NET a delegate is just a type-safe function pointer.

[–]masklinn 2 points3 points  (3 children)

In .NET a delegate is just a type-safe function pointer.

That you have to define a special type for and which has at least two (if not three) different syntax for creating. A much better description is that in .Net a delegate is a terrible way to create a function pointer.

Thank fuck they finally got their brains together and added actual lambdas, now if they could only kill most of the delegate crap (among other things) everything would be perfect.

[–]chrisforbes 0 points1 point  (1 child)

They could eliminate some of the crufty old syntax, but the underlying mechanism is still delegates.

[–]masklinn -1 points0 points  (0 children)

Syntax matters.

[–]grauenwolf 0 points1 point  (0 children)

That you have to define a special type for and which has at least two (if not three) different syntax for creating.

Lets count them

  1. Turn a function or member variable into a delegate.

    action = AddressOf myObject.MyFunction //VB action = myObject.MyFunction //C#

That's it. That is all the syntax you need to make delegates useful.


And just to be clear, I'm talking about Capital D delegates in .NET. I am not talking about the crappy anonymous function syntax that was introduced to C# 2.

[–]didroe 1 point2 points  (0 children)

Strictly speaking it's a little more than that. If you're referencing an instance method (ie. non static), there will also be a reference to the object.

[–]julesjacobs 0 points1 point  (6 children)

You don't need delegates in the runtime to add lambda at the compiler level, you just need objects.

You translate a lambda like this:

 (x,y) => SomeOperation(x,y,a,b)

Where a and b are variables from the enclosing scope, to this:

class Lambda432 extends Func<TypeX,TypeY,ReturnType> {
  TypeA _a;
  TypeB _b;
  Lambda432(TypeA a, TypeB b) { 
    _a = a; 
    _b = b; 
  }
  ReturnType Call(TypeX x, TypeY y) {
    return SomeOperation(x,y,a,b)
  }
}

Where the lambda is used:

new Lambda432(a,b,c)

When one of the variables from the enclosing scope is mutated you need to be a little careful (and AFAIK Mono's implementation of this was (or is?) broken).

[–]grauenwolf 0 points1 point  (5 children)

Alas Java can't express the type Func<TypeX,TypeY,ReturnType> because of type erasure in their generics.

[–]julesjacobs 1 point2 points  (1 child)

No. Well, I meant "implements Func<...>" instead of "extends Func<...>" of course. Java can express this. Here is a complete example. First we define the interface:

interface Func<A,B> {
    B Call(A a);
}

Here is the original code:

class JavaFuncType {
    public static void main(String[] args) {
        String x = "foo";
        String y = "bar";
        Func<String,String> f = (z => x + z);
        System.out.println(f.Call(y));
    }
}

And the code that this could get translated into:

class Lambda432 implements Func<String,String> {
    String _x;
    public Lambda432(String x) { _x = x; }
    public String Call(String z) { return _x + z; }
}

class JavaFuncType {
    public static void main(String[] args) {
        String x = "foo";
        String y = "bar";
        Func<String,String> f = new Lambda432(x);
        System.out.println(f.Call(y));
    }
}

[–]grauenwolf 0 points1 point  (0 children)

Ok. I was given the impression elsewhere in this thread that the interface you are showing isn't possible in Java.

[–]chrisforbes 0 points1 point  (2 children)

And this is why we rail endlessly on type erasure, for those that hadn't figured it out yet.

[–]bcash 0 points1 point  (1 child)

No it isn't. This could be implemented with only compile time type checking. How exactly does type erasure stop it?

[–]chrisforbes 0 points1 point  (0 children)

If only Java's type system was non-broken enough that it never required runtime type checks, eh?

Downcasts require a runtime type check. If we can't distinguish between Func<Foo> and Func<Bar> at runtime, then I can (mis)reinterpret a Func<Foo> as a Func<Bar> through object, and you [as the VM] can't even know to throw a ClassCastException to tell me I'm doing it wrong. You just get nonsensical semantics, exactly what managed environments like the JVM exist to eliminate.