Я много раз читал, что
Сборки, сгенерированные из F # или любого другого языка .NET (почти) неразличимы.
Затем я экспериментировал с взаимодействием F # и C # в .NET 4 (бета 2). Я создал новое решение и проект на C # со следующим классом:
public class MyClass {
public static int Add(int a, int b) { return a + b; }
}
Затем в проекте F #, после ссылки на проект C #, я попытался:
MyClsas.Add(4, 5) |> printfn "%d" // prints 9 (no kidding!)
Пока все хорошо. Затем мне пришло в голову другое предложение, которое я читал много раз (возможно, в разных книгах):
При передаче аргументов в функции из других библиотек .NET вы используете синтаксис, такой как ".MethodName (parm1, parm2)", то есть параметры передаются как кортеж.
Добавьте это к чему-то, что я когда-то читал здесь на SO (но не смог найти его для ссылки), на вопрос, где OP пытался создать использование типа [ 4, 5, 6 ]
(когда он имел в виду [4; 5; 6]
):
"Запятая - это оператор создания кортежа, для всего остального используйте точку с запятой."
Затем я изменил свой класс следующим образом:
public class MyClass {
public static int Add(int a, int b) { return a + b; }
public static int Add(Tuple<int, int> a) { return a.Item1; }
}
Теперь я попытался использовать его на F #:
MyClass.Add(4, 5) |> printf "%d" // prints ... (keep reading!)
Итак, сложив три цитаты выше, можно сделать вывод, что:
- F # создаст кортеж, когда увидит
(4, 5)
- Тогда это вызовет перегрузку
Add(Tuple<int, int>)
- Так будет напечатано 4
К моему удивлению, напечатано 9 . Разве это не интересно?
Что на самом деле здесь происходит? Приведенные выше цитаты и это практические наблюдения, похоже, противоречат друг другу. Можете ли вы обосновать «рассуждения» F # и, если возможно, указать на некоторые документы MSDN?
Спасибо!
EDIT
(чтобы добавить больше информации (из ответа Блинди))
Если вы делаете:
MyClass.Add((4, 5)) |> printfn "%d" // prints 9
F # вызывает перегрузку Add(Tuple<int, int>)
.
Однако, если вы создадите еще один проект F # (таким образом, другую сборку) с этим:
namespace MyFSharpNamespace
type MyFShapClass = class
static member Add x y = x + y
end
Вы можете использовать его на C #, как это
public static void Main(string[] args) {
MyFSharpNamespace.MyFSharpClass.Add(4, 5);
}
Пока все хорошо. Теперь, когда вы пытаетесь использовать его из F # (из другого проекта, другой сборки), вы должны сделать:
MyFSharpNamespace.MyFSharpClass.Add 4 5 |> printfn "%d"
Если вы передадите аргументы как (4, 5)
F # не будет компилироваться, потому что Add
это int -> int -> int
, а не (int * int) -> int
.
Что происходит?!?