That's not an operator, that's a lambda. The end result is the same, but semantically it's very different. Passing around an operator means you don't need to know the types involved - you can have a function that operates on any two values and applies an operator to them. That's not something you can do with lambdas in C#.
No, there's no difference whatsoever. .NET has no concept of "operators" that are different from functions.
F# is statically typed, just like C#, and the only reason you can pass + in this case is because the type of the stack is Stack<int>, so the compiler can statically infer that "+" means "the + operator on ints." At every usage, + has to refer to a specific function, or it wouldn't compile. For example, if it was a Stack<object> that happened to contain ints, it wouldn't compile.
(You could use .NET's "dynamic" type to make it dynamically resolve which function at runtime, but you could use it equally well in the C# example with a lambda.)
Non-overloadable operators (short-circuiting operators (|| and &&), ternaries and its ilk, field access and (of course) the assignment operator) are probably compiled straight to bytecode, but they're pretty special and (especially in a strict language) need special runtime support anyway[0].
To sum up: mquander is completely right, the CLR does not know anything about operators, language compilers will take whatever operator they have at a high level and compile them to method calls (usually). For more details, see http://www.amazon.com/dp/0735627045/
Interesting. However, operators and functions present very differently when writing c# code.
It's easy to put a lambda or a named function in a variable, pass it to a function, etc. However, if you want to do that to an operator such as "+", the first thing to do is to wrap it in a lambda - e.g.
// invalid
// Func<int, int, int> plus = + ;
// works in a wrapper fn
Func<int, int, int> plusFn = (a, b) => a + b;
Related, if you have a function which is generic for some type T, you can call functions of type Func<T> on the values in it, but you can't use operators like + - c# just isn't generic on operators, though it can be on functions.
public T ApplySomeFunc<T>(Func<T, T> func, T value)
{
// this works
return func(value);
// this does not
//return value + value;
}
I know that the language has no way to specify that the type T has a "+" operator so that's not going to work; but this catches people out regularly, when they try and fail to make math functions that are generic over all numeric types. However, you can do something similar with the "dynamic" type, at the cost or run-time-dispatch.
> Interesting. However, operators and functions present very differently when writing c# code.
Aye, but that's more of a limitation of C#'s syntax
> However, if you want to do that to an operator such as "+", the first thing to do is to wrap it in a lambda - e.g.
That's pretty much what a section (the parens around the operators) does in F# or Haskell.
> I know that the language has no way to specify that the type T has a "+" operator so that's not going to work
Well it's not so much that "operators and functions present very differently when writing C# code" but that "methods and functions present very differently when writing C# code" and that operators are (static) methods more than functions in C#.
Also that C# has no numeric tower[0] so there's indeed no way to say a type is a generic number (whether that number's an int, a double or a decimal). If there was a root `Number` type you could write something along the lines of:
public T AddNumbers<T> where T:Number(T value)
{
// works because all numbers have a `+`
return value + value;
}
which is exactly what you write in Haskell:
addNumbers :: (Num a) => a -> a -> a
addNumbers a b = a + b
[0] Haskell has a pretty complete/complex one, starting from Num[1] which implements only a few basic operations: (+), (-), (*), negation and conversion from integer.
> That's not an operator, that's a lambda. The end result is the same, but semantically it's very different.
It's not, actually. In most functional languages — including F# — operators are just a special case of functions. Haskell will let you both use operators as (prefix) functions (via sections):
Prelude> (/) 42 2
21.0
or use functions as (infix, binary) operators:
Prelude> even `filter` [0..20]
[0,2,4,6,8,10,12,14,16,18,20]
and operators are defined exactly the same way you'd define functions:
Prelude> let (><) a b = a * b in 3 >< 4
12
although you can define them infix if you prefer:
Prelude> let a >< b = a * b in 3 >< 4
12
then again, you can also define functions using infix syntax:
Prelude> let a `add` b = a + b in add 3 4
7
You can also partially apply operators (again, via sections):
Prelude> :t (1 +)
(1 +) :: Num a => a -> a
in roughly the same way you'd partially apply functions:
Prelude> :t map (+ 1)
map (+ 1) :: Num b => [b] -> [b]
> Passing around an operator means you don't need to know the types involved
Uh? You need to know them in exactly the same way you do for functions.
> you can have a function that operates on any two values and applies an operator to them.
No, you most definitely can't, both operators and functions are typed. They work the exact same way but for the syntactic difference that operators are infix and may have precedence junk on top. But that's parsing, aside from that, a functional language will treat functions and operators the same way (outside of the odd builtin)