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

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

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

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

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

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


person Seb    schedule 28.01.2014    source источник


Ответы (2)


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

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

person piotrek    schedule 18.02.2014

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

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

Хм? Где? Как?

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

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

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

Изучать динамические языки впервые сейчас уже слишком поздно, это как если бы на протяжении 1990-х вы откладывали замену своей магнитофонной деки на проигрыватель компакт-дисков, а затем, наконец, примерно в 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
person Domingo Ignacio    schedule 10.04.2014