Hacker News new | past | comments | ask | show | jobs | submit login

C# also infers method type parameters, and will implicitly convert a lambda to a matching interface. Fluent code in C# is also very clean. They're great features in both languages.



You're right, c# does to some extent. On balance I do agree with you, and prefer the set of c# features. Just to clarify - I was thinking of things like this

  class Example 
  {
    public static void Main() 
    {
      Predicate<String> foo = Foo<String>(s => s.Contains("foo"));
    }

    static Predicate<T> Foo<T>(Predicate<T> p) 
    {
      return p;
    }
  }
I can't replace Foo<String> with just Foo on the right hand side on the 3rd line. I could, however, replace the left hand side with just "var". (n.b. I am using mono, with langver=5. It's possible this is improved in a newer version)

Java will infer the RHS

  class Example {
    public static void main(String... args) {
      Predicate<String> foo = foo(s -> s.contains("foo"));
    }
  
    static <T> Predicate<T> foo(Predicate<T> p) {
      return p;
    }
  }
The structural typing of lambdas in c# I believe works with delegates? I at least don't know how I'd do the following in c# (I suspect I'd have to define an override of the implicit type conversion operator from a delegate type to a class, or define an extension method called hello on a suitable type)

  public class Example {
    interface MyPredicate<T> {
      boolean test(T t);
      default void hello() {
        System.out.println("Hello");  
      }
    }
  
    public static void main(String... args) {
      MyPredicate<String> foo = s -> s.contains("foo");
      foo.hello();
    }
  }
The structural typing here is really powerful, e.g. for working around things like type erasure ;) http://benjiweber.co.uk/blog/2015/02/20/work-around-java-sam... or more consise builder pattern http://benjiweber.co.uk/blog/2014/11/02/builder-pattern-with...


Awesome examples, thank you. I apologize if you already know all of this stuff. You seem much more knowledgeable about this than me.

As for type inference, C# will sometimes infer the RHS from the LHS, lambdas are one example. Also sometimes it can figure out the types from a lambda. Here is an example where the type information for inference comes from the literal int zero:

  public void Main()
  {
    var i = 0;
    var list = MakeThree(() => i++);
    //[0, 1, 2]
  }

  private IList<T> MakeThree<T>(Func<T> generator)
  {
    return new List<T>{ generator(), generator(), generator() };
  }
C# will infer method type parameters from arguments. In your example, there wasn't a type on the parameter to use as a source of inference. You could write it instead as (contrived example):

  Predicate<string> p = s => s.Contains("foo");
  var foo = Foo(p);
The type parameter on Foo is inferred, as well as the variable type on the LHS. The only time I write a type on the LHS is when I am assigning a lambda to a variable. And that is not super often. More realistically though, you would be passing a collection or something else that already has a type. For example in LINQ's IEnumerable<T> extension methods, the IEnumerable<T> is the source of the type information as the first parameter to the extension method, so everything is inferred from there. It's extremely rare for me to type a method type parameter. I cannot remember the last time I did. I do write the types for constructors often, though. new List<int>(), new Dictionary<string, Foo>() etc. I guess the tradeoff is that in java you can infer a lambda's type by writing it on the LHS, while in C# you are going to have to get that type from somewhere else. Either write it on the RHS, or it will be written on some other variable or method.

Also I use Func and Action every day, but I basically never use other delegate types.

Your example of structure typing of lambdas looks weird to me. It's the same feeling I get when I see a downcast. I mean no criticism; I suspect this is a Blub reaction in me. I am not used to looking at the left-hand side to figure out the type for the right-hand side. Lambdas will implicitly convert to a Func or Action. A reference to a method with a matching signature will also convert. As a silly example: Select takes a Func<T, U>, and will implicitly convert a method that accepts the same T as its only parameter.

  public ShortTons ConvertTons(LongTons t) { ... }

  public void Main()
  {
    var readings = GetReadings();
    var exportWeights = readings.Select(x => x.Weight).Select(ConvertTons);
  }
In this example, there are elided, inferred type parameters everywhere. The source of the type is in the missing GetReadings method, and the Weight property on the reading type. That's pretty typical.

That builder pattern is pretty cool. In C# you have object initialization syntax, which is similar in being more readable as to which members are getting set. However, that's pretty much incompatible with immutability afaik. It only lets you set public properties with public setters. Normally you would make something immutable by making your setters private, or leaving them off entirely. Public fields (even readonly ones) are strongly discouraged in C#. Either way, that prohibits object initialization.

Thanks for responding, I learned a lot about Java.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: