System.Console.WriteLine() vs printfn в F #
В чем разница между следующими двумя утверждениями в F #?
Являются ли они преимуществами или недостатками по сравнению друг с другом (исключая очевидные различия в синтаксисе)?
Я понимаю, что WriteLine() является частью .NET, но не понимаю, какие последствия это может иметь.
Пример кода:
printfn "This is an integer: %d" 5
System.Console.WriteLine("This is an integer: {0}" , 5)
Ответы
Ответ 1
printfn
и его различные кузены имеют несколько преимуществ:
- Они короче.
- Они могут выполнять проверку <статического типа ; т.е.
printfn "%d" "bad type"
не будет компилироваться.
- ... но вам не нужно проверять статический тип;
%O
печатает любой объект
- Они могут печатать "умные" представления для таких вещей, как массивы, кортежи и дискриминационные объединения с помощью
%A
- Они могут быть частично применены; т.е.
printfn "%d, %d" 3
является допустимым выражением. Это особенно примечательно, поскольку компилятор может проверить, что вы фактически применяете правильное количество аргументов, когда вы позже используете это подвыражение - в отличие от Console.WriteLine
, которое с радостью примет слишком много или слишком мало параметров.
На практике наиболее распространенное частичное приложение, скорее всего, будет включать только строку формата; например.
let printParticle = printfn "Particle at (%d, %d), state %A, p = %f"
printParticle 2 3 //compile time warning about ignored value
printParticle 3 4 someState 0.4 //fine
printParticle 5 6 someState 0.4 0.7 //compile-time error
Однако, до F # 3.1, он также медленный. Это достаточно быстро, чтобы не отставать от вас кодер, но если вы используете его в какой-то форме сериализации, это может стать узким местом. Объявление F # 3.1 (которое распространяется как часть Visual Studio 2013) утверждает, что оно значительно улучшает производительность, хотя я еще не подтвердил это.
Лично я обычно использую printfn для поискового кодирования, а затем я в основном придерживаюсь %A
со случайным другим спецификатором, который был добавлен. Однако собственное строковое форматирование .NET по-прежнему полезно в некоторых случаях для его детальной культуры и форматирования связанные варианты. Если вы хотите, чтобы прямая конкатенация максимальной скорости (или StringBuilder
) легко превзошла обоих, поскольку это позволяет избежать интерпретации строки формата.
Ответ 2
Вот некоторые плюсы и минусы printf
-подобных функций по сравнению с Console.WriteLine
.
Плюсы:
-
printfn
функции безопасны по типу:
printfn "This is an integer: %i" 5 // works
printfn "This is an integer: %i" "5" // doesn't compile
-
Легко выполнять частичное приложение с помощью printfn
, что не относится к Console.WriteLine
из-за чрезмерного количества перегрузок:
[1; 2; 3] |> List.iter (printfn "%i; ")
-
printfn
лучше поддерживать типы F # с помощью спецификатора %A
.
Минусы:
Помимо невозможности повторного использования параметров в качестве упомянутого @mydogisbox, printfn
-подобные функции намного медленнее, чем Console.WriteLine
(из-за использования отражения); вы не должны использовать первую для целей ведения журнала.
Ответ 3
Функция printfn может быть частично применена.
let printDouble = printfn "%f"
printDouble 2.0
Поскольку стандартные функции .NET принимают кортежи как параметры в F #, вы не можете использовать там частичное приложение.
Второе преимущество printfn состоит в том, что аргументы вводятся. Так что это не скомпилируется:
let printDouble = printfn "%d"
printDouble 2.0
Ответ 4
Помимо стиля, System.Console.WriteLine
имеет то преимущество, что он может повторно использовать параметры, т.е. System.Console.WriteLine("This is a integer twice: {0} {0}", 5)
Кроме того, как отмечено здесь, вы можете сделать довольно печатную работу над объектом F #, используя printfn
, который вы не можете сделать с System.Console.WriteLine
, и поскольку он не работает, t возьмите кортеж, вы можете сделать с ним частичное приложение.
Как отмечалось другими, printfn
использует отражение и, следовательно, значительно медленнее, чем PrintLine
, но также является типичным.