LINUX.ORG.RU

Зачем нужна статическая типизация?, или Вы всё врете!

 ,


1

4

В теме "Питонячьи радости " на последних страницах между мной и @rtxtxtrx внезапно разгорелся спор, из которого я понял, что есть еще люди, которые не считают динамическую типизацию (в том виде, в котором она представлена в Питоне, а именно строгая динамическая типизация) серьезным недостатком при работе с большим объемом кода, особенно при рефакторинге. Вообще изначально разговор завязался вокруг назначения type hints введенных в Питон 3: я утверждал, что они нужны для создания семантических связей в коде, которые будут препятствовать внесению деструктивных изменений в код в результате опечатки или иной ошибки кодера (изменил код, в результате которого какое-либо выражение получило некорректное значение, которое тем не менее обладает схожим с корректным значением типовым контрактом, поэтому при запуске код не «упадет» сразу, указав на проблему); оппонент заявил, что они нужны для (само)документации и не более того.
Но потом выяснилось, что и царь-то ненастоящий (читай, статическая типизация). Не нужна она, просто именуй сущности понятно и уповай на строгую типизацию. А если типизация не строгая, то сами виноваты, у нас в Питоне всё ОК.
Поскольку тема большая и вкусная, я предлагаю всем обсудить этот очень важный вопрос в меру скромных сил и познаний каждого желающего. Обсуждение вторичных вопросов, как-то «статическая типизация нужна для генерации эффективного кода», «при динамической типизации тип только один, object» etc. не предусмотрено — спорим только о том, дает ли статическая типизация выигрыш, если надо перекраивать несметные тыщи kloc. Если есть вообще о чем спорить 😅.

★★★★★
Ответ на: комментарий от den73

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

С точностью до наоборот:

"2" == 2  // true
"2" === 2 // false

В первом случае динамическая типизация сама приведет к одному типу и затем сравнит. Во втором случае сначала будет сравнение типов и только потом сравнение значений если сравнение типов прошло успешно. Динамическая типизация в современных языках идет по четко описанным правилам и все проблемы в ней только от незнания этих самых правил.

Статическая типизация это ОГРАНИЧЕНИЕ - защита от дурака, заодно - помощь компилятору.

Obezyan
()
Ответ на: комментарий от den73

Вот, кстати, в python «2» * 2 = «22». В нём нет знаменитого 2 + «2» = «22», но недалеко ушёл. Это тоже проблема типизации, но это не проблема её статичности или динамичности, это проблема перегрузки операций, которая и в плюсах, кстати, в полный рост.

Это проблема вашего незнания правил приведения типов и их очередности.

Obezyan
()
Ответ на: комментарий от rumgot

Вот собственно ты описал одни из способов как обходить проблемы/следствия отсутствия статической типизации. Т.е. в некотором смысле повторяем то, что мог бы сделать компилятор. А была бы статическая типизация, то и обходить ничего не нужно было.

Был бы ст, пришлось бы делать всё в парадигме ст. В ст больше издержки на написание всякого с key[valve] и прочим всяким динамическим и непонятным.

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

Проблема, которую можно решить - это расходы, а не проблема.

И с такой логикой можно и в отношении C/C++, с их утечками по причине забытого указателя, сказать: ну так не используй сырые, используй умные, применяй идиомы

Так в чём проблема не использовать? На любом яп можно себе член дверью прищемить.

crutch_master ★★★★★
()
Ответ на: комментарий от rumgot

Ой, правда? А при разработке на динамически типизированных ЯП ошибок в бизнес логике нету. Ну правильно динамичность все ошибки бизнес логики сама решает.

У тебя больше возможностей, ты можешь больше делать непосредственно в рантайме, в том числе проверять всякие ошибки и влазить в нестандартные ситуации. Представь на секудну, что для того, чтобы выполнить sql запрос тебе надо пересобрать субд. Вот вы всей своей тухлой стшной тусовкой тоже сейчас пытаетесь доказать, что пересобирать каждый раз субд - прикольно, прогрессивно и правильно. А на самом деле до вас всё придумали уже 50 лет как.

crutch_master ★★★★★
()
Ответ на: комментарий от Vic

Например, в языках со статической типизацией можно делать собственные типы, объединяющие нужные (union в Си) или использовать контейнеры (std::variant в С++), или есть встроенные в язык (тип variant в паскале). Таким образом получаешь нужный тип в рантайме с полным контролем над вариантами обработки

Да это не типы. Это всё ковыряние иголкой в жопе. Они ничего не решают. Тебе надо сделать типы вроде {int от 10 до 90}, чтобы он работал и всё вокруг работало. А твой ст это не умеет из коробки. И сделать ничего вменяемого ты не можешь. Потому что, например, сложение двух таких переменных даст тебе {int от 20 до 180} + любые типы входящие в этот диапазон. И я не представляю, как ты будешь выводить это на твоём ст язычке типа сисярп/жабки.

Или вот, например, элементарное uint8 sum(uint8 a, uint8 b) просто не работает в общем случае, не смотря на то, что ст язычок что-то там типа гарантирует. И про какую вы там типизацию рассказываете? Где она?

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 3)
Ответ на: комментарий от Obezyan

В первом случае динамическая типизация сама приведет к одному типу и затем сравнит

Да? В питоне у нас уже статическая типизация, раз он так не делает? Не нужно путать динамическую со слабой.

unC0Rr ★★★★★
()
Ответ на: комментарий от crutch_master

unC0Rr
Что ты там реакции свои тухлые ставишь и молчишь? Хоть один ваш «промышленный» ст недоязычёк умеет в такие типы с параметрами? Умеет выводить что-то из них? И что ты будешь делать, когда надо, а он не умеет? Или компилятор за тебя выведет диапазон допустимых значений по заданным правилам?

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

Был бы ст, пришлось бы делать всё в парадигме ст. В ст больше издержки на написание всякого с key[valve] и прочим всяким динамическим и непонятным.

Можно конкретный пример?

Проблема, которую можно решить - это расходы, а не проблема.

Как ты это называешь не суть.

Так в чём проблема не использовать? На любом яп можно себе член дверью прищемить.

Если яп позволяет сделать небезопасно, когда нибудь будет сделано.

rumgot ★★★★★
()
Ответ на: комментарий от unC0Rr

Да? В питоне у нас уже статическая типизация, раз он так не делает? Не нужно путать динамическую со слабой.

Разговор идет уже о типизации вообще. Лично я, как Обезъян, говорю о PHP, который своей динамической типизацией (и работой с ассоциативными массивами) внезапно уделывает практически всех кроме разве что lisp.

Конкретно в Python попытались нащупать золотую середину. Т.е. он вполне может складывать int с float, но не может складывать int с str, при этом умножать str на int - аж бегом. Насколько такая середина «золотая» каждый решает сам в силу своих прикладных задач.

Obezyan
()
Ответ на: комментарий от crutch_master

Или вот, например, элементарное uint8 sum(uint8 a, uint8 b) просто не работает в общем случае

А можешь рассказать, почему?

rumgot ★★★★★
()
Ответ на: комментарий от crutch_master

влазить в нестандартные ситуации

В какие? Можно получить данные, с которыми вообще хз, что делать?

rumgot ★★★★★
()
Ответ на: комментарий от crutch_master

для того, чтобы выполнить sql запрос тебе надо пересобрать субд

Что что? Это зачем субд пересобирать? Кто так делает? Ты сам?

rumgot ★★★★★
()
Ответ на: комментарий от rumgot

Что что? Это зачем субд пересобирать?

Я тоже не знаю, зачем вы постоянно пересобираете свой говнокод. Субдшники нормально живут как-то без этого и свою субд обновляют/перезапускают раз в 10 лет. А вы не можете.

В какие?

Хммм. Какие же могут быть нестандартные ситуации в разработке, что же может пойти не так, дайте подумать.

crutch_master ★★★★★
()
Ответ на: комментарий от rumgot

Можно конкретный пример?

Ruleset pattern, например. Который в ст виде будет мапой. А если не мапой, то вообще выглядит как дерьмо и из него хрен что потом выведешь. Ну ты посмотри на это позорище

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

Хоть один ваш «промышленный» ст недоязычёк умеет в такие типы с параметрами?

Agda, Idris и Coq умеют. Но почему-то адепты агитируют не за них, а за указания подсказок типов в питоне.

ugoday ★★★★★
()
Ответ на: комментарий от crutch_master

Я тоже не знаю, зачем вы постоянно пересобираете свой говнокод. Субдшники нормально живут как-то без этого и свою субд обновляют/перезапускают раз в 10 лет. А вы не можете.

Не шлангуй. Ты написал про постоянную пересборку субд, я тебе задал вопрос: кто так делает?

rumgot ★★★★★
()
Ответ на: комментарий от rumgot

Ты написал про постоянную пересборку субд, я тебе задал вопрос: кто так делает?

Я написал:

Представь на секудну, что для того, чтобы выполнить sql запрос тебе надо пересобрать субд. Вот вы всей своей тухлой стшной тусовкой тоже сейчас пытаетесь доказать, что пересобирать каждый раз субд - прикольно, прогрессивно и правильно.

Ответ: да, типичный ынтерпрайз жабка + орм делает именно это. Генерит/модифицирует по своим enitiy таблицы с полями и вперёд. Хз, зачем ты пытаешься отнекиваться.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Не фига не понял, зачем субд пересобирается? Что ты вообще под субд понимаешь?

Это какая то надстрока, которая прячет внутри себя sql запросы и выдает наружу сразу java типы?

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от rumgot

что не так?

А ты не видишь что не так?

Комбинации могут быть следующими:
1 X X X X — 100 очков
5 X X X X — 50 очков
1 1 1 X X — 1000 очков
2 2 2 X X — 200 очков
3 3 3 X X — 300 очков
4 4 4 X X — 400 очков
5 5 5 X X — 500 очков
6 6 6 X X — 600 очков
1 1 1 1 X — 2000
1 1 1 1 1 — 4000
1 2 3 4 5 — 8000
2 3 4 5 6 — 8000
A A B B X — 4000 
Пример говна. Максимально синтетический и стандартный ruleset и даже тут - рукалицо.
SingleDieRule
SetOfADieRule
TwoPairsRule
TripleDieRule
Это позор. Вопрос решается одной функцией, на сисяре херачат класс. Ну а чо нет. Копировал, вставил. Как выводить обратно из класса правила? В классах писать руками? Как таблицу вероятности выигрыша построить? Они же мне так казик разорят, кек.

И при том, что это - вообще не задача. ККИ бы какую-нибудь показал, где правила, типа, «следующий удар наносится в случайную карту на столе, а если её нет в лицо себе», или там систему бонусов/скидок где берешь 3 пива, самая дешевая закуска в чеке (не дороже бутылки самого дешевого пива) бесплатно/скидка 10% на закуску/10 рублей на телефон/вотка со скидкой 20% (от 4-х бутылок)/серт. на бесплатную поездку в наркологичку/лотерея: главный приз - пересадка печени.

Щас человеческое решение запилю с кубиками вместо оопэ-ынтерпрайз-кододрочерского.

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

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

rumgot ★★★★★
()
Ответ на: комментарий от Obezyan

Как выше правильно заметили самый тупизированный из скриптовых… внезапно Java с ее чудомашиной, которая не только опкоды может интерпретировать, но с житом asm-команды выполнять. Но какие претензии к пистону - пиши на своей джаве 42 + «foo» складывай, но она, наверное, не устраивает тем, что не позволяет:

MyClass.java:3: error: bad operand types for binary operator '=='
      System.out.println(42 == "42");
                            ^
  first type:  int
  second type: String
1 error

Питон не настолько «компилируемый» как джава, он компилирует только подключаемые модули, что ускоряет повторный запуск…

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

rtxtxtrx ★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 2)
Ответ на: комментарий от rumgot

Вот, вместо правил жоопэ говна делаешь свою нотацию и пошел херачить. Вместо дерьма с _ruleSet.Add(new SingleDieRule(1,100)); нормальная человекочитаемая структура. Можно было так на сисярпе? Да, но чел не думает такими категориями. Ему надо было показать какой он у мамы умный и знает паттерны, он показал. Задачу ему решать было не надо. Для людей сделать не надо. И в этом всё ваше fizzbizzenterprise-жоопэ со стат типизацией говна. Что мешало сделать систему как человек, а не как мартыхан? Кубики не в состоянии написать, чтобы не обосраться.
Где здесь *нужна* стат. типизация, где капец нельзя было бы положить болт? Таблица выигрышей проверяемая, функции проверяемые, всё остальное или строки или числа в зависимости от того ключ это или значение. И всё работает, пока входные данные везде валидны, а их проверять надо на любом языке, если они идут снаружи. И будешь делать это на стат оопэ недоязычке, всё тоже самое будет, только с одноразовой пачкой классов говна и хэшмапой хешмап, которую тащили бы из какого-нибудь xml, который тоже не для людей.

var rules = {
  "1XXXX" : 100,
  "5XXXX" : 50,
  "111XX" : 1000,
  "AAAXX" : ({A})=>A * 100,
  "1111X" : 2000,
  "11111" : 4000,
  "12345" : 8000,
  "23456" : 8000,
  "AABBX" : 4000
}
var token = new Set(["A","B"]); //возможные токены
var tokenAny = "X"; //токен любая кость
var diceValues = new Set(["1","2","3","4","5","6"]); //значения костей
//TODO ruleset validator

var dice = (d)=> Math.floor(Math.random() * d) + 1; //not used
var dices = (n, d)=> Array(n).fill().map(v=>dice(d)); //not used
var numSort = (a, b) => a - b; //сортировка чисел
var different = (arr) => { //все значения в массиве разные
  arr.sort(numSort);
  var res = true;
  arr.forEach((v,i)=>{
    if (!i) return;
    if (v == arr[i - 1]) res = false;
  });
  return res;
}
var arrCount = (arr, what)=>{ //возвращает число вхождений в массив
  return arr.reduce((s, v)=>(s + ((v === what) ? 1 : 0)), 0);
}
var arrRemove = (arr, what, count = 1) => { //убирает count what элементов из массива
  for (let n = 0; n < count; n++) {
    var i = arr.indexOf(what);
    if (i == -1) return false;
    arr.splice(i, 1);
  }
  return true;
}
var join = (arr, stack = [], i = 0)=>{ //декартово произведение массивов
  if (!arr[i]) return stack;
  return arr[i].map(v=>join(arr, [v, ...stack], i + 1))
}

var profit = function(rules, hand) { //подсчёт профита
  if (!hand.length || hand.length != 6 || !hand.every(v=>diceValues.has(String(v))) throw("Type error in profit");
  //var hand = [ 1, 3, 6, 2, 1]

  var profits = Object.entries(rules).map(([rule, value])=>{
    //var rule = "AABBX", value = 4000;
    //rule - AABBX, 123XX, AA1111, value - number | function
    var ruleDice = rule.split("").filter(v=>v != tokenAny); //AABB, 123, AA111
    var tokens = new Set(ruleDice.filter(v=>token.has(v))); //AB, , A
    var tokenCount = ruleDice.reduce((s, v)=>{ //{A : 2, B : 2}, {}, {A : 2}
      s[v] = (s[v] || 0) + 1;
      return s;
    }, {})
    var handSet = new Set(hand);
    var variants = 
      join([...tokens].map(T=>[...handSet].map(D=>({[T] : D})))). //[ [ [ {A : 1}, {B : 1} ], [ {A : 1, B : 2} ], ...
      flat(tokens.size - 1). //[ [ {A : 1}, {B : 1} ], [{A : 1}, {B : 2}] ...
      filter(arr=>different(arr.map(v=>Object.values(v)[0]))). //[ [ {A : 1}, {B : 2} ], [{A : 1}, {B : 3}] ...
      map(rec=>rec.reduce((s, v)=>({...s, ...v}), {})). // [ {A : 1, B : 2}, {A : 1, B : 3} ...
      filter(v=>Object.entries(v).every(([T, D])=>tokenCount[T] <= arrCount(hand, D))) //[ { A : 1, B : 2 }, { A : 2, B : 1} ]
    var func = (typeof value == "function") ? value : ()=>value; //приведение к функции

    if (!variants.length && !tokens.size) {
      variants = [{}]; //в случае если в правиле нет токенов A/B добавить заглушку
    }

    var ret = variants.map(variant=>{
        var checkHand = [...hand];
        var ok = true;
        Object.values(variant).forEach(D=>{ //наличие нужного количества костей по токену правила
          if (!ok) return;
          var ok = arrRemove(checkHand, D, tokenConut[D]); //убираем из руки, если нашли что надо
        })
        if (!ok) return null;
        ok = ruleDice.filter(v=>diceValues.has(v)).every(D=>{
          var i = checkHand.indexOf(+D); //убираем кости по номеру в правилах
          if (i == -1) return false;
          checkHand.splice(i, 1);
          return true;
        });
        if (!ok) return null;
        return { hand, rule, variant, profit : func(variant) }
      }).filter(v=>v);
    return ret.reduce((max, v)=>{ //оставляем самый выигрышный вариант
      if (max.profit < v.profit) max = v;
      return max;
    }, {hand, rule, profit : 0})
  });
  var maxProfit = profits.reduce((max, v)=>{ //еще раз
      if (max.profit < v.profit) max = v;
      return max;
  }, { profit : 0 });
  return maxProfit;
}
profit(rules, [1, 3, 6, 2, 1]) //100 - 1XXXX
profit(rules, [1, 5, 6, 2, 1]) //100 - 1XXXX
profit(rules, [3, 5, 6, 2, 6]) //50  - 5XXXX
profit(rules, [1, 1, 1, 2, 6]) //1000 - 111XX
profit(rules, [2, 2, 2, 3, 6]) //200 - AAAXX
profit(rules, [3, 3, 3, 1, 6]) //300 - AAAXX
profit(rules, [4, 4, 4, 3, 6]) //400 - AAAXX
profit(rules, [5, 5, 5, 3, 6]) //500 - AAAXX
profit(rules, [1, 1, 1, 1, 4]) //2000 - 1111X
profit(rules, [1, 1, 1, 1, 1]) //4000 - 11111
profit(rules, [1, 2, 4, 3, 5]) //8000 - 12345
profit(rules, [2, 3, 4, 5, 6]) //8000 - 23456
profit(rules, [2, 2, 3, 3, 6]) //4000 - AABBX
crutch_master ★★★★★
()
Ответ на: комментарий от rumgot

но на крупном реальном проекте это сыграет в обратную сторону.

На крупном проекте fuzbuzentreprise сыграет в какую надо сторону, что придётся принудительно бухать после работы, чтобы хоть как-то привести в порядок нервы, после дебага многослойки дерьмоклассов размазанных по всему проекту тонким слоем. Нельзя же сделать буквально «хочу чтобы на 3 пива чипсы проходили бесплатно» и отправил, чтобы оно само там проверялось на вменяемость, на соответствие с другими правилами, нет надо развести зоопарк с подпрыгиванием и приседаниями вокруг культа «чистого кода», который нихера не делает сам, не может анализировать себя сам, вокруг которого прыгать надо и плясать с вениками.

crutch_master ★★★★★
()
Ответ на: комментарий от rtxtxtrx

Могу добавить только что Java и Javascript это две разные попытки сделать «кроссплатформенное ООП с человеческим лицом». Не смотря на то что оба языка используют виртуальные машины и практически все в них является объектом, сам ООП в них реализован абсолютно разными методами. В Java - классический class-based, в javascript - более древний prototype-based, т.е. разный подход для разного круга задач. А т.к. подходы разные то и типизация в них также - разная. Поэтому 42 == "42" в Javascript, в отличии от Java, будет true.

Возвращаясь к типизации, она бывает не только статическая/динамическая, но и сильная(строгая)/слабая. Поэтому если и обсуждать их то с учетом этой характеристики. Самый неудачный вариант, имхо - слабая статическая типизация как в С. На нем я больше всего видел дичайших велосипедов без сидений. На втором месте с конца - сильная статическая типизация - Java и C#. Затем идет сильная динамическая как у Python, ну и на первом месте - слабая динамическая типизация аля PHP c JS которую я считаю лучшей из всех 4х вариантов (для решения моих задач!).

Поэтому когда адепты одного языка (моноязычники) на 24 страницы спорят о том какая типизация лучше при этом не упоминая даже сильная она или слабая - это вызывает лишь улыбку.

Obezyan
()
Последнее исправление: Obezyan (всего исправлений: 1)
Ответ на: комментарий от Obezyan

ООП в них реализован абсолютно разными методами

Теорему Эскобара не обманешь. Теорема Эскобара неумолима. Теорема Эскобара не знает жалости.

Nervous ★★★★★
()
Ответ на: комментарий от Obezyan

подходы разные то и типизация в них также - разная

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

Nervous ★★★★★
()
Ответ на: комментарий от Obezyan

Тут проблема в терминологии. Одни считают статической типизацией задание типов при компиляции (классическое определение), другие - невозможность изменить тип переменной при присвоении в дальнейшем. Если исходить из хрестаматийного определения, то можно всю ее свести к тому, что автор бредит, используя правила демагога. А если применять второе определение, то JavaScript будет статически тупизированным, так как там можно объявить пременную через const и ей уже нельзя ни то что тип сменить, но и значение. В пистоне же объявление переменной работает не так как в том же js:

counter = 0

def add():
  counter += 1

# свалится с ошибкой, так как в скопе функции нет значения для `counter`
add()

Те в нем присваивание создает локальное значение в текущем пространстве имен либо его изменяет. Все максимально примитивно. Для чего оно сделано? - Для скорости, если мы будем типы приводить при присваивании, то это затратно. В JS там если переменная не объявлена в текущем скопе, то они ищутся в скопах выше и перезаписываются… В PHP еще круче сделано там даже значение скопа выше получить нельзя, ни то что перезаписать его. Те еще больше на спичках-тактах сэкономили. Ну он и быстрее питона, тем более там многопоточности не было, а значит и страшный GIL не мог помешать планам по захвату мира. Про global я не вспоминаю, потому как и eval тот предан анафеме и за их использование нужно увольнять. Тут совершенно все иначе работает чем в той же Java

в javascript - более древний prototype-based

Не он не древний. Прототип - это один из джава-паттернов. Типа самый прогрессивный для своего времени, но никто эту фишку не понял, поэтому запилили сахарок в виде классов

rtxtxtrx ★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 4)
Ответ на: комментарий от rtxtxtrx

Пример неправильной работы JS-сахарка:

class MyError extends Error {}

throw new MyError('test')
// Uncaught Error: test
//     at <anonymous>:1:7

Почему оно так соевые уже не понимают, и про прототипы эти не знают.

https://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript

rtxtxtrx ★★
()
Ответ на: комментарий от rtxtxtrx

Питон не настолько «компилируемый» как джава, он компилирует только подключаемые модули, что ускоряет повторный запуск…

Пихтон компилирует всё, а не только модули, сначала любой скрипт переводится в байткод, потом этот байткод выполняется. Напрямую исходник не интерпретируется.

Virtuos86 ★★★★★
() автор топика
Ответ на: комментарий от Obezyan

Поэтому 42 == «42» в Javascript, в отличии от Java, будет true.

Это вовсе не от подхода к реализации ООП. Пыхпых скопировал поведение Перла. Но в Перле это глубоко обосновано на уровне фундамента: там нет чисел и строк, там есть сущность «скаляр», поэтому 42 и "42" это разные формы представления скаляра, а не апельсин и яблоко. И «автоматическое приведение типов» в данном случае выглядит идеологически верным (неверным выглядит только желание использовать Перл для программирования за пределами сонсолевых однострочников, если в нем нет ни строк, ни чисел нормальных человеческих). Ну а пыхеры утащили следствие без причины в классический язык с числами и строками. Еще и умудрились головы задурачить людям, раз кого-то не воротит от этого, даже нравится 😁.

Поэтому когда адепты одного языка (моноязычники) на 24 страницы спорят о том какая типизация лучше при этом не упоминая даже сильная она или слабая - это вызывает лишь улыбку.

В треде не раз упомянули про строгую/нестрогую типизацию, так что мимо.

Virtuos86 ★★★★★
() автор топика
Последнее исправление: Virtuos86 (всего исправлений: 2)
Ответ на: комментарий от rtxtxtrx

Не он не древний. Прототип - это один из джава-паттернов.

Я имел ввиду что prototype-based появился прилично до class-based.

Obezyan
()
Ответ на: комментарий от Virtuos86

Я вам правильный пример о JS/Java, вы мне про правильное обоснование, но на PHP(Perl) :) Хоть и мимо контекста, но все верно. Поэтому мы обезъяним на PHP т.к. он берет все нужное и не берет все ненужное из разных языков. Я помню каким говном был php v3 и я вижу какой php v8 сейчас. Он готов для продакшна чуть более чем полностью.

В треде не раз упомянули про строгую/нестрогую типизацию, так что мимо.

Каюсь, я просто скипнул середину тк там были суждения высосанные из, ну пусть будет - пальца.

Obezyan
()
Последнее исправление: Obezyan (всего исправлений: 1)
Ответ на: комментарий от rtxtxtrx

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

Virtuos86 ★★★★★
() автор топика
Ответ на: комментарий от rtxtxtrx

можно объявить пременную через const и ей уже нельзя ни то что тип сменить, но и значение

Всегда так делаю. А чо? Все беды от присваивания, каждый школяр знает.

Nervous ★★★★★
()
Ответ на: комментарий от ugoday

Мда… аргумент. Сам выбрал 8 бит, сам знаешь что 8 бит не хватит для результата, и сам негодуешь :-)

rumgot ★★★★★
()
Ответ на: комментарий от crutch_master

Это скорее про js лапшу, где нельзя часть ошибок словить на этапе компиляции, т.к. компиляции как таковой нет.

rumgot ★★★★★
()
Ответ на: комментарий от rumgot

ыбыбы, а вот там ошибки компиляции

Что ошибки «компиляции»? Ты уже показал, на примере представленного кода чего можно там такого сделать и не заметить это ни при разработке, ни при тестировании? На фузбузынтерпрайз у тебя нет ошибок компиляции, и что, у тебя код не говна кусок? Или тебе мешает что-то сделать правило, которое разорит казино? Или у тебя компилятор ругнётся на неисполнимое правило «3 бутылки пива 0,5л, стоимостью меньше 50 рублей»?

crutch_master ★★★★★
()
Ответ на: комментарий от Obezyan

Я имел ввиду что prototype-based появился прилично до class-based.

А можно подробнее? class-based OOP появилось в Simula-67.

А prototype-based OOP – это язык Self, где-то район 1987-го года.

eao197 ★★★★★
()
Ответ на: комментарий от crutch_master

На фузбузынтерпрайз у тебя нет ошибок компиляции, и что, у тебя код не говна кусок? Или тебе мешает что-то сделать правило, которое разорит казино? Или у тебя компилятор ругнётся на неисполнимое правило «3 бутылки пива 0,5л, стоимостью меньше 50 рублей»?

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

rumgot ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)