Конкретные (кодовые) примеры преимуществ динамических языков программирования

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

Я не ищу другого "который лучше"- спорьте здесь, так как на эту тему достаточно дискуссий (например, языки с динамическим типом или языки со статическим типом или что люди находят настолько привлекательным в динамических языках?). Я также задал тот же вопрос на LtU, который закончился в другом обсуждении.:-)

Во всех этих обсуждениях упоминаются некоторые хорошие моменты, но почти во всех отсутствует какой-то конкретный код (!)- примеры, подтверждающие их точку зрения.

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

Заранее спасибо.

2 ответа

По определению: утка печатающая. но вы хотите более конкретный пример, скажем так: строительные объекты. в статически типизированных языках вам нужно объявить тип или использовать встроенные методы для генерации кода во время выполнения. в динамических языках вы можете просто создавать объекты ad hoc. Например, чтобы создать макет в groovy, вы можете просто написать один метод, который вам нужен, и передать его как объект: http://groovy.codehaus.org/Developer+Testing+using+Closures+instead+of+Mocks

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

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

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

А? Куда? Как?

Такие языки, как Haskell, ML, Scala, Rust и некоторые из семейства.NET, сочетают строгую типизацию с выводом типов, так что вы получаете лучшее из обоих: все имеет строгий принудительный тип, но вам не нужно его писать. вниз, если компилятор не может понять это, что он обычно может.

Не игнорируйте их за академичность. Времена изменились. В последние несколько лет такие языки с мощными системами ввода текста неуклонно набирают популярность. (2) И я нахожу все реже слышать о совершенно новом языке, который не сочетает строгую типизацию для безопасности с выводом типа для удобства, по крайней мере, до некоторой степени. Сегодняшние совершенно новые эзотерические языки являются "стандартами предприятия" следующего десятилетия, поэтому я думаю, что в конечном итоге все будут использовать этот подход, основанный на лучших принципах и способностях обоих миров.

Даже старик Ява медленно движется в этом направлении! (примеры: оператор Diamond; вывод функционального интерфейса для лямбда-выражений)

Впервые изучать динамические языки уже слишком поздно, это похоже на то, что если в 90-е годы вы откладывали замену магнитофона на проигрыватель компакт-дисков, а затем, примерно в 2002 году, у вас появилась возможность купить проигрыватель компакт-дисков.

РЕДАКТИРОВАТЬ: Я перечитал ваш вопрос. Я сочувствую вашему желанию конкретного кода. Вот Розеттский камень. Общая процедура, чтобы проверить, отсортирован ли список или нет, и код, который его вызывает. Код, который вызывает его, делает правильные вещи каждый день, а неправильные - в високосные дни, как пример того, как ошибки времени компиляции выигрывают больше, чем ошибки времени выполнения, когда у вас есть ошибка в редко исполняемом коде. Код не проверен, просто набросок. В частности, я все еще изучаю Haskell (отсюда и рвение новообращенного...:P), и я не использовал Python так интенсивно, как раньше, так что, прости

Традиционная статическая типизация:

// Java 7 - strong typing but no type inference
// Notice that you get safety, because the wrong usage is caught at compile time
// But you have to type a lot :-(
  static interface Comparable { boolean compare(Comparable other); }
  ...
  boolean isListSorted( List<T extends Comparable> xs ) {
    T prev = null; for( T x: xs ) {
        if( prev!=null && !prev.compare(xs) ) return false;
        prev = x; 
    } 
    return true;
  }
  ...
  public final class String implement Comparable { ... }
  public final class Animal /* definitely does not implement Comparable! :-) */ { ... }

  ...
  // proper usage
  List<String> names = Lists.newArrayListOf("Red", "Spinelli", "Ankh", "Morporkh", "Sam");
  boolean areTheNamesSorted = isListSorted(names);
  if(todayIsALeapDay()) {
     // bad usage -- the compiler catches it, so you don't have to worry about this happening 
     // in production when a user enters data that send your app down a rarely-touched codepath
     List<Animal> pets = Lists.newArrayListOf( Animal.getCat(), Animal.getDog(), Animal.getBird() );
     boolean areTheNamesSorted = isListSorted(pets);
  }

Динамическая типизация:

class Animal:
   ...

# Python 2.6 -- dynamic typing
# notice how little keystrokes are needed
# but the bug is now
def isListSorted(xs):
  # to keep it more similar to the Java7 version, zip is avoied
  prev = None
  for x in xs:
    if prev is not None and not prev.compare(x): return False
    prev = x
  return True
...
# usage -- beautiful, isn't it?
names = ["Raph", "Argh", "Marge"]
areNamesSorted = isListSorted(names)

if isLeapDayToday():
   # ...but here comes trouble in paradise!
   animals = [Animal.getCat(), Animal.getDog()]
   # raises a runtime exception. I hope your unit tests catch it, but unlike type 
   # systems it's hard to make absolutely sure you'll be alerted if you forget a test
   # besides, then you've just traded the Evil of Having to Write Lots of Type Signatures
   # for the Evil of Having to Write Lots of Unit Tests. What kind of terrible deal is that?
   areAnimalsSorted = isListSorted(animals)

Мощный набор текста:

-- Haskell - full safety of strong typing, but easy on the fingers and eyes
class Comparable a where
  compare :: a -> a -> Bool
end
instance Comparable String where
   ...
end
data Animal = ...

isListSorted [] = True
isListSorted x:[] = True
isListSorted x1:x2:xs = (compare x1 x2) && (isListSorted xs)

names = ["Raplph", "Argh", "Blarge"]
areNamesSorted = isListSorted names



animals = [Cat, Dog, Parrot]

-- compile time error because [Animal] is not compatible with Comparable a => [a] since
-- Animal is not an instance of comparable

areAnimalsSorted = isListSorted animals

Многословная мощная типизация:

-- Same Haskell program as before, but we explicitly write down the types 
-- Just for educational purposes. Like comments, you can omit them if you don't think
-- the reader needs them because it's obvious. Unlike comments, the compiler verifies their truth!


class Comparable a where
  compare :: a -> a -> Bool
end
instance Comparable String where
   ...
end
data Animal = Cat | Dog | Parrot


isListSorted :: Ord a => [a] -> Bool
isListSorted [] = True
isListSorted x:[] = True
isListSorted x1:x2:xs = (compare x1 x2) && (isListSorted xs)

names :: [String]
names = ["Raplph", "Argh", "Blarge"]

areNamesSorted = isListSorted names


-- compile time error because [Animal] is not compatible with Comparable a => [a] since
-- Animal is not an instance of comparable

animals :: [Animal]
animals = [Cat, Dog, Parrot]

areAnimalsSorted = isListSorted animals
Другие вопросы по тегам