2013-06-12 3 views
15

В чем разница между следующими двумя утверждениями в F #? Существуют ли они какие-либо преимущества или недостатки по сравнению друг с другом (исключая очевидные различия в синтаксисе)?System.Console.WriteLine() vs printfn в F #

Я понимаю, что WriteLine() является частью .NET, но не понимает, какие последствия это может иметь.

Проба Код:

printfn "This is an integer: %d" 5 
System.Console.WriteLine("This is an integer: {0}" , 5) 
+2

Mono использует System.IO.TextWriter https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/printf.fsi –

+0

Спасибо за дополнительную информацию :) – OMGtechy

ответ

27

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 release announcement (который распространяется как часть Visual Studio 2013) утверждает, что он значительно улучшает производительность, хотя я еще не подтвердил это.

Лично я обычно использую printfn для поискового кодирования, а затем я в основном придерживаюсь %A со случайным другим спецификатором, который был добавлен. Однако собственное строковое форматирование .NET по-прежнему полезно в некоторых случаях для его детальной культуры и форматирования, . Если вы хотите, чтобы прямая конкатенация максимальной скорости (или StringBuilder) легко превзошла обоих, так как это позволяет избежать интерпретации строки формата.

+0

Благодарим вас за очень четкий и полезный ответ. Если бы вы могли подробно остановиться на частичном применении, это было бы еще лучше! – OMGtechy

+1

Я согласен, что вместо 'Console.WriteLine()' обычно следует использовать 'printfn' и связанные с ним функции, но стоит упомянуть, что они также относительно медленны (что может иметь значение для некоторых случаев использования). –

+0

Я этого не знал, спасибо за обновление - думаю, я никогда не пытался использовать его для огромного количества данных :-) обновлено! –

3

Помимо стиля, System.Console.WriteLine имеет преимущество в возможности повторного использования параметров, т.е. System.Console.WriteLine("This is a integer twice: {0} {0}", 5)

Кроме того, как отметил here, вы можете сделать симпатичную печать F #, используя printfn, который вы не можете сделать с System.Console.WriteLine, и так как он не берет кортеж, вы можете сделать с ним частичное приложение.

Как отмечают другие, printfn использует отражение и, следовательно, значительно медленнее, чем PrintLine, но также является типичным.

+0

Спасибо! :) Подождите еще несколько ответов перед тем, как пометить решение (если вы можете придумать что-нибудь еще, обратите внимание на это здесь). – OMGtechy

+0

@JoshuaGerrard Просто чтобы вы знали, вы можете переместить «зеленую метку», когда захотите. –

+0

@RamonSnir это правда, но люди с меньшей вероятностью могут ответить (или даже посмотреть), если есть ответ, который уже отмечен как правильный. – mydogisbox

4

Функция printfn может быть частично применена.

let printDouble = printfn "%f" 
printDouble 2.0 

Поскольку стандартные функции .NET принимают кортежи как параметры в F #, вы не можете использовать там частичное приложение.

Второе преимущество printfn заключается в том, что аргументы печатаются. Так что это не будет компилироваться:

let printDouble = printfn "%d" 
printDouble 2.0 
5

Вот некоторые плюсы и минусы 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-like functions are much slower, чем Console.WriteLine (в связи с помощью отражения); вы не должны использовать первую для ведения журнала.

Смежные вопросы