Hacker News new | ask | show | jobs
by jshen 6290 days ago
dealing with the type system in scala can be a pain and is a hit to productivity in the early stages. The question is if the hit in the early stages leads to more productivity in the later stages. I'm not convinced that it does.

I've done a lot of ruby, and I've had monkey patching bite me a few times. However, fixing the problem was never that hard (two days max) and is clearly overshadowed by the productivity gained from the power ruby gave my teams.

3 comments

How can one effectively argue against an entirely subjective judgment of difficulty in terms of dealing with a type system?

Anecdotally, I find that leveraging functional language programming features coupled with type inference and polymorphism leads to considerable productivity gains as code correctness can be ensured through judicious use of types -- without requiring extensive testing or programmer effort -- while excess verbosity can be eliminated through the use of FP features such as type-safe anonymous functions, currying, etc.

How do you deal with excess verbosity in C#? I know this is a separate argument from the monkey patching issue but for me the conciseness and elegance of the Ruby syntax versus C# is the primary reason to choose Ruby.
Hopefully a user of C# will chime in -- I've spent very little time with it, and only recently evaluated C#'s extension mechanism for the purpose of comparing it against other language's implementations.

That said, elegant and concise syntax does not require eschewing an internally consistent, fully specified type system -- the two are not incompatible, as demonstrated (subjectively) -- by many existing FP languages. I argue that elegance/conciseness requires either FP language features and advanced type system, or abandonment of rigorous typing.

Which version of C# are you thinking of?

In C# 3, the verbosity level is much less than in C# 2, where it's slightly less than C# 1.

I don't see where Ruby syntax is particularly more concise than C# 3's.

Well, let me clarify "particularly". I don't find myself feeling like I'm suffering under C#'s syntax, relative to Haskell's. It has about the same amount of syntactic overhead: writing types for method parameters, and when defining data structures. Occasionally I have to explicitly write a type parameter to a function.

"I don't see where Ruby syntax is particularly more concise than C# 3's."

1.upto(10).each{|x| print x}

I'm curious - how would you print 1 through 10 in C# 3 by comparison?

C# 3:

  (1).UpTo(10).ForEach(x => Console.WriteLine(x));
Of course, "UpTo" requires first extending int, which is trivial:

  public static class IntExtensions {
      public static List<int> UpTo(this int start, int end) {
          var range = new List<int>();
          for(int i = start; i < end; i++) {
              range.Add(i);
          }
          return range;
      }
  }
That's cool and all, but I think being able to do this natively in Ruby wins:

  p *1..10
Edit: you may need to do a "require 'pp'" first.
One way to do this in Scala:

  def print[T] (value:T) = System.out.println(value)
  1.until(10).foreach(x => print x)
This is a fairly uninteresting example, however. Something more interesting would be, for instance, the use of structural types to implement type-checked duck typing.

Scala example:

  // Declare a structural type for any class implementing close()
  type Closable = {def close(): Any}
  
  // Executes the provided function with the given
  // closable generator, creating a new instance which
  // will then be closed on completion. The provided
  // function's value will be returned.
  def withClosable[T, C <: Closable] (c: => C) (f: (C) => T) = {
    val closable = c
    try {
      f(closable)
    } finally {
      closable.close
    }
  }
  
  // Example usage
  def usage = {
    val updated = withClosable(db.openConnection) { conn =>
      conn.update("INSERT INTO example VALUES (...")
    }
    System.out.println("Rows updated: " + updated)
  }
This could be compared with Python's new 'with' syntax.
Since there's plenty of shitting on Scala going on, I'd like to point out that the Scala equivalent of that is:

    1 to 10 foreach println
Which seems more concise than the equivalent Ruby to me. Feh.
in Python:

    for i in range(1,11): print i
Python FTW? ;)
I still find this clearer:

  for x in range(1, 10): print x
I'm nitpicking, but your range should be range(1,11).
Not so different in Ruby:

for x in 1..10; print x end

I find monkeypatching happens because the framework doesn't utilize proper baseline OO techniques. By "baseline" I'm excluding mixins. I have rarely found a case where mixins do a better job over well factored inheritance. I don't think mixins are "evil". Just over utilized and inheritance heavily underutilized in Ruby.
You're lucky that in those cases you were able to recover in only two days. The time it takes to get back on track can be proportional to the size of the project so imagine if you were dealing with an enterprise system written in and monkey patched in Ruby and you had a similar problem. Depending on your luck, you might get back on track or you might end up having a lot of extra time to work on your resume.
I do work for a very large enterprise. Monkeypatching isn't something that is used liberally, but it's the right thing in certain circumstances.

It's not luck, simply put, it's not hard to fix well written software.