Both languages can be difficult to decipher. I do find that Scala's syntax is much more flexible, which can lead to more stumbling when trying to read code.
And this is of course ignoring the fact you copied that from the documentation witch shows all interfaces the class implements. IDictionary also implements ICollection & IEnumerable so you wouldn't need to include them. So to actually implement this class it would more likely be
[SerializableAttribute]
[ComVisibleAttribute(false)]
public class Dictionary<TKey, TValue> :
IDictionary<TKey, TValue>,
IDictionary,
IReadOnlyDictionary<TKey, TValue>,
ISerializable,
IDeserializationCallback
{
...
}
> A talented C# dev will need to know co/contravariance as well as implicits considering they also exist in C#.
True for co/contravariance. For implicits, that depends on which implicits you are talking about.
Scala has:
* implicit conversion operators (these have existed in C# for some time, under the same name)
* implicit parameters (C# doesn't have an analog to these that I can think of)
* implicit classes (C# has an analog in classes providing extension methods, though the classes themselves are distinguished by a keywords as they are in Scala; in Scala, these are essentially syntactic sugar for creating a normal class and an implicit conversion from the extended class.)
> implicit parameters (C# doesn't have an analog to these that I can think of)
C# allows default values for parameters, but it's not quite the same.
Example of C# default value for parameter:
static void Addition(int a, int b = 42)
{
Console.WriteLine(a + b);
}
Addition(4); // Prints 46
Addition(4, 5); // Prints 9
In Scala, the default (implicit) value has more complex rules.
Like C#, implicit parameters must come after non-implicit parameters (if any).
Unlike C#, the implicit value does not need to be defined in the signature. Also unlike C#, if you provide the value for one implicit parameter, you must provide the value for all implicit parameters.
using System;
public class Program
{
public class Person
{
private string _name;
private int _age;
public Person(string name, int age)
{
_name = name;
_age = age;
}
public static implicit operator int(Person p)
{
return 42;
}
}
public static void Main()
{
var person = new Person("Jim", 51);
var number = 100;
AdditionPrinter(person, number); // Prints 142
}
public static void AdditionPrinter(int a, int b)
{
Console.WriteLine(a + b);
}
}
Though implicits I feel are so much simpler than many people fear.
From a Ruby perspective: Just think of them as operating similarly to Refinements, except not completely insane because there is no global scope at compilation. You only have to worry about your own package, imports and inheritance.
Tracking down an implicit generally takes all of 10 seconds, and never more than a few minutes. Even moderately brain-bendy ones like akka.patterns.ask (where does the implicit "?" come from? "ask" is actually an implicit conversion to a class that defines it: https://github.com/akka/akka/blob/master/akka-actor/src/main...).
I'm a fan of C#, although I prefer F#; however I have to agree, I think the choice of < > for generic definitions was a real mistake, it can be so hard to parse. The side effect of this is that first-class functions (Func<>) are chronically underused by C# programmers.
Annoyingly F# brought them along for the ride too, although you rarely have to explicitly write them.
I haven't tried out many alternatives, but there's something about nested <> that seems to throw me off each time.
I wrote a library of monads for C# [1], and implementing the SelectMany method is a good example of how messy it can be:
public static RWS<R, W, S, V> SelectMany<R, W, S, T, U, V>( this RWS<R, W, S, T> self, Func<T, RWS<R, W, S, U>> bind, Func<T, U, V> project)
{
}
I quite like F#'s alternative syntax for single type generics:
Option<int>
Can be written:
int option
Obviously it's a personal thing, so I doubt I would be able to suggest anything that would change your mind; I just had a quick go at an alternative, and I quite like this:
public static SelectMany R W S T U V ( this self : RWS R W S T, bind : Func T (RWS R W S U), project : Func T U V) : RWS R W S V
{
}
class Thing int
{
}
class Thing T : BaseThing T
{
}
It's moot anyway really, it is what it is. I've just found it cognitively challenging over the years.
Given proper indentation, ifall to see what is difficult to understand here. You have acouple of attributes, a generic you're declaration (with easy to understand syntax), and an inheritance list.
Yeah, and not knowing Scala myself, I can't say that the OP didn't purposely use a contrived example. That said, I still don't think a class definition which is little more than a bunch of interfaces being implemented is confusing to anyone who got through chapter 4 of "Learn C# in 21 days".
Both languages can be difficult to decipher. I do find that Scala's syntax is much more flexible, which can lead to more stumbling when trying to read code.