2010-07-25 1 views
7

Я новичок в Scala и просто читал Scala By Example. В главе 2 автор имеет две разные версии Quicksort.Scala Performance: императив против функционального стиля

Одним из них является обязательным стиль:

def sort(xs: Array[Int]) { 
    def swap(i: Int, j: Int) { 
     val t = xs(i); xs(i) = xs(j); xs(j) = t 
    } 
    def sort1(l: Int, r: Int) { 
     val pivot = xs((l + r)/2) 
     var i = l; var j = r 
     while (i <= j) { 
      while (xs(i) < pivot) i += 1 
      while (xs(j) > pivot) j -= 1 
      if (i <= j) { 
       swap(i, j) 
       i += 1 
       j -= 1 
      } 
     } 
     if (l < j) sort1(l, j) 
     if (j < r) sort1(i, r) 
    } 
    sort1(0, xs.length - 1) 
} 

Один функциональный стиль:

def sort(xs: Array[Int]): Array[Int] = { 
    if (xs.length <= 1) xs 
    else { 
    val pivot = xs(xs.length/2) 
    Array.concat(
     sort(xs filter (pivot >)), 
      xs filter (pivot ==), 
     sort(xs filter (pivot <))) 
    } 
} 

Очевидное преимущество функциональный стиль имеет более императивный стиль является краткость. Но как насчет производительности? Поскольку он использует рекурсию, мы платим за штраф за производительность, как и в других императивных языках, таких как C? Или, Scala является гибридным языком, предпочтительнее «Scala way» (функциональный), тем самым более эффективным.

Примечание: автор упомянул, что функциональный стиль использует больше памяти.

+2

Возможный дубликат [Функциональное программирование scala медленнее, чем традиционное кодирование?] (Http://stackoverflow.com/questions/2794823/is-scala-functional-programming-slower-than-traditional-coding) – missingfaktor

+2

«Краткий» это не то же самое, что «читаемый». Доказательства: [язык программирования J] (http://en.wikipedia.org/wiki/J_ (programming_language)) –

+1

Думаю, теперь я понимаю, что автор Scala By Example пытается показать еще один способ решить проблему, которая намного более кратким. Подводя итог: вы программируете как можно более краткими во всех частях вашего кода, поэтому вы получите максимальную лаконичность, производительность. Затем запустите приложение, и если оно слишком медленное, профилируйте его и оптимизируйте узлы узких мест. – sivabudh

ответ

11

зависит от цели. Если вы посмотрите в источниках Scala, часто используется императивный стиль, используемый «под капотом» для того, чтобы быть исполнительным, но во многих случаях именно эти настройки позволяют вы написать письмо исполнителя functional код. Поэтому обычно вы можете найти функциональное решение, которое достаточно быстро, но вы должны быть осторожны и знать, что вы делаете (особенно в отношении ваших структур данных). Например. массив concat во втором примере не очень приятный, но, вероятно, не так уж плохо, но использование списков здесь и конкатение с ::: было бы излишним.

Но это не более чем образованное предположение, если вы на самом деле не Измерение производительность. В сложных проектах действительно сложно предсказать производительность, особенно, поскольку такие вещи, как создание объектов и вызовы методов, становятся все более оптимизированными компилятором и JVM.

Я предлагаю начать с функционального стиля. Если он слишком медленный, профилируйте его. Обычно есть лучшее функциональное решение. Если нет, вы можете использовать императивный стиль (или сочетание обоих) в качестве крайней меры.

+0

Но это как-то поражает цель правильно? Я имею в виду, Scala приветствуется как первый язык, который объединяет функциональное и объектное программирование. Но, если вы не можете быть уверены, что программирование функционального способа будет эффективным, тогда люди, которые заботятся о производительности, в конечном итоге сделают Scala «Java» способом? – sivabudh

+5

Посмотрите на примеры. Какой из них легче понять? Функциональный стиль на самом деле говорит вам, что делает алгоритм: «выберите элемент поворота, сортируйте меньшие элементы, сортируйте более крупные элементы и соберите все вместе». Это огромное преимущество над императивным примером, который в основном касается переменных цикла и индексов массива. Поэтому, если функциональный стиль работает хорошо, мы, как правило, золотистые, но у нас все еще есть императивный стиль в качестве решения для решения проблемы. Однако не устанавливайте объектно-ориентированный императив. Классы и объекты могут отлично работать в функциональном контексте. – Landei

+9

В любом крупном проекте вы обнаружите, что очень мало кода действительно должно быть критически эффективным. В этих случаях верно, что вам часто приходится возвращаться к императивным конструкциям. Scala поддерживает это.В остальное время вам лучше кодировать таким образом, чтобы ваш дизайн был как можно более ясен в вашем коде. Это может быть либо функциональным, процедурным, объектно-ориентированным, либо некоторым его сочетанием. Scala поддерживает все эти функции. –