Программист Scala - “должен там быть одним очевидным способом сделать это” или “больше чем один способ сделать это”?

Я делал Java в течение долгого времени и запустил Scala приблизительно 6 месяцев назад. Я люблю язык. Одна вещь, которую я обнаружил, состоит в том, что существует несколько способов сделать вещи. Я не знаю, ли это из-за природы языка или потому что это все еще молодо и развивается и идиомы, и лучшие практики не появились.

То, что удивляет меня, я всегда был Python по человеку жемчуга где:

"Должны быть один - и предпочтительно только один - очевидный способ сделать это".

имеет больше смысла мне, чем

"Существует больше чем один способ сделать это".

Мне интересно знать, где Вы думаете соответствие Scala в этом масштабе и почему?


Кавычки: Python PEP20 и кавычка Perl

15
задан 2 revs, 2 users 100% 5 February 2010 в 15:42
поделиться

6 ответов

Мой опыт работы со Скалой заключается в том, что существует более чем один способ делать вещи, но относительно мало «лучших» способов делать вещи. Библиотека имеет очень мало безвозмездных вариантов для разных способов действий; когда он делает это, это обычно для обеспечения дополнительной выразительности, компактности или эффективности в подмножестве случаев.

Например, если вы хотите суммировать массив целых чисел, вы могли бы быть полностью процедурными, которые могли бы генерировать код, который был бы как можно быстрее, за счет того, чтобы быть немного кланов- но если это действительно критический по времени код, это уникальный лучший способ решения проблемы:

val array = Array(1,2,3,4,5)
var sum = 0
var index = 0
while (index < array.length) {
  sum += array(index)
  index += 1
}
sum

Существуют не менее общие функциональные подходы, которые медленнее при работе с примитивами (это может измениться с @ specialized в 2,8), но оставляют вам меньше тедиума:

var sum = 0
Array(1,2,3,4,5).foreach(x => sum += x)
sum

И тогда есть несколько менее общие функциональные конструкции, которые разработаны как раз для такого рода проблем (так как это приходит много) и это «лучше», если вы хотите чистый, компактный код:

Array(1,2,3,4,5).reduceLeft( _ + _ )

И иногда существуют очень необщественные конструкции, чтобы делать именно то, что вы хотите; в Scala 2.8, например:

Array(1,2,3,4,5).sum

Таким образом, вы получаете континуум вариантов с компромиссами в общей мощности, компактности, ясности и скорости. Если вы можете предположить, что код должен быть доступен только людям, которые хорошо знакомы со Scala, и вы знаете, нужна ли вам абсолютная наилучшая производительность или нет, хороший выбор обычно довольно ограничен. Но, из-за выразительной силы языка и библиотеки, обычно существует много возможных, если неоптимальных способов делать вещи.

19
ответ дан 1 December 2019 в 01:53
поделиться

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

  • объектно-ориентированное
  • функциональное программирование
  • подходы, специфичные для Java
  • языково-ориентированное программирование (расширение синтаксиса, метапрограммирование)

. Это позволяет программисту решать проблемы с разных точек зрения поэтому по-разному. Как вы и подозревали, это заложено в самой природе языка (как и в других универсальных / мультипарадигмальных языках).

Какой из них использовать, во многом зависит от программиста, хотя я могу дать некоторые общие правила / мысли:

  • Scala - в конце концов - функциональный язык . Поэтому я считаю хорошей практикой следовать функциональному стилю программирования (который также приведет к очень кратким и элегантным решениям)

  • Будьте последовательны! В конце концов, у вас должен быть один путь , но вы можете выбрать какой . Избегайте смешивания побочных эффектов и чистых функций, понимания списков и библиотечных функций (карта, фильтр) или функционального мышления против Java. Вместо этого используйте разные парадигмы ортогонально там, где они лучше всего подходят.

  • Используйте замечательные возможности, которые Scala предоставляет вам (а не просто используйте его как Java с красивым синтаксисом): сопоставление с образцом, продолжения, обобщения и чрезвычайно мощную систему типов, функции высшего порядка.

5
ответ дан 1 December 2019 в 01:53
поделиться

Наиболее очевидное место, где скала предлагает совершенно разные способы достижения одного и того же, находится в области для понимания:

val ls = List(1, 2, 3, 4)
for (l <- ls) println(l) //for comprehension
ls.foreach(println(_))   //underlying form 

Это распространяется на flatMap , фильтр и др. Мой личный выбор - придерживаться вызовов методов, хотя в более сложных примерах, таких как:

for (i <- 1 to 10;
     j <- 1 to 20 if (j % 2 == 0)) ...

я вижу, что они проще и интуитивно понятнее в форме для . Для меня важна возможность выбора стиля, потому что люди из разных слоев общества предпочитают разные вещи.

Добавление конструкций управления к 2.8, таких как Исключения является примером: исходя из Java фона, я сначала не получил силу, стоящую за этими абстракциями, но если бы я начинал в функциональной области, то, вероятно, понял бы это сразу.

Мой главный жупел в Scala - отсутствие разумных предикатных представлений о классе опций. Несмотря на то, что для некоторых предикатов p:

opt.isEmptyOr( p ) //does not exist
opt.forall( p )

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

opt.notEmptyAnd( p ) //does not exist       
opt.map(p).getOrElse(false)

На мой взгляд, 2-я форма неоправданно нечитаема! Дублирование для достижения читабельности, несомненно, является положительным моментом!

2
ответ дан 1 December 2019 в 01:53
поделиться

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

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

Немногочисленные исключения в основном являются следствием высокой ортогональности. Вещи в Scala не запрещены, потому что они не имеют смысла (с точки зрения дизайнера) или неоптимальны.

И, наконец, упор на библиотеки. В Scala нет списков или карт. А массивы указываются только потому, что этого требует совместимость с Java. В этом смысле он очень похож на C, в отличие от BASIC. В C почти все, что вы делаете, кроме математики, делалось с помощью библиотек, написанных либо на самом C, либо на ассемблере. В BASIC даже такие команды, как открытие файлов или отображение текста на экране, являются частью самого языка.

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

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

Например, Список имеет оператор добавления (в Scala 2.8), хотя это неоптимально для списков. Он есть, потому что List является Seq , и это обычная операция, которую можно проделать с ними.

В заключение отметим, что более чем односторонняя характеристика языка проявляется в самом объединении функционального и объектно-ориентированного программирования.

4
ответ дан 1 December 2019 в 01:53
поделиться

Этот подход имеет проблему, состоящую в том, что вам в основном приходится ждать неопределенное время, и если вы отправляете вызов из основного потока, вы блокируете обработку событий и, таким образом, сигнализируете как loadFinished .

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

-121--2964719-

Размер консоли можно задать с помощью команды методов :

mode con lines=50 cols=200

Изменение будет сохраняться только до закрытия окна консоли.

-121--3702210-

Это понятие настолько расплывчато, что является практически бессмысленным. Но я подозреваю, что если бы вы работали с языком, в котором действительно был только один способ сделать какую-либо вещь, вы бы ругались и зубы по крайней мере 50% времени.

Мое (расплывчатое) чувство заключается в том, что в любом приличном языке программирования общего назначения всегда будет много способов выполнить большинство вещей.

1
ответ дан 1 December 2019 в 01:53
поделиться

Размер консоли можно задать с помощью команды методов

mode con lines=50 cols=200

. Изменение будет сохраняться только до закрытия окна консоли.

-121--3702210-

Если я правильно помню IsReusable указывает ASP.NET, что обработчик не должен быть уничтожен после обработки запроса и тот же экземпляр может быть использован для обработки последующих запросов. То есть один экземпляр объекта обработчика не обрабатывает несколько запросов одновременно.

-121--4407471-

Отказ от ответственности: Я понятия не имею, что авторы Scala думают об этом, я просто выражаю свое мнение как разработчик scala (и питона и рубина).

Пройдя через Scala API, вы не видите много способов сделать то же самое. Например, изменяемые и неизменяемые версии объектов имеют одинаковый интерфейс. Такие вещи дают Скале некоторую согласованность.

Будучи гибридным языком, обычно существует два способа решения проблемы: функциональный и процедурный путь (foreach vs for). Конечно, если бы вы хотели использовать процедурный способ, вы бы просто использовали Java.

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

Наконец, я считаю, что любой код должен быть очевиден для чтения. И очевидно писать. Вы можете быть либо очень гибкими (perl/ruby) или строгими (python). Scala является гибким хорошо (подумайте синтаксис использования «». и скобки в вызовах метода, но вы можете сделать его настолько строгим, насколько вы хотите. Лично мне нравятся строгие вещи, поэтому я напишу свой собственный код, то, что я думаю, это очевидный способ.

1
ответ дан 1 December 2019 в 01:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: