Не так давно было время, когда мы должны были сделать такой выбор: хочу ли я, чтобы программа была быстрой и простой, но иногда возникало больше ошибок во время выполнения? Или я хочу быть защищенным от большего количества этих ошибок во время компиляции, но за счет того, что мне придется тратить больше времени на написание большего количества шаблонов?
Теперь все кончено. Динамические языки были чрезвычайно захватывающими, когда они были единственным способом избежать дополнительной бюрократии в вашем коде, но теперь динамическая типизация устарела путем вывода типов. Итак, вы на самом деле правы - динамическая типизация больше не добавляет ценности, теперь, когда набирают популярность более мощные системы строгого типа.
Хм? Где? Как?
Такие языки, как 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