Pull to refresh
1
0
Send message

Проблема не в том, чтоб кислород для дыхания стал сжат вдвое сильнее, этим всё равно занимается наземный агрегат, а для перекачивания внутри ракеты, уже для дыхания, особой мощности и так не надо. Проблема в том, что теперь баки с дыхательным кислородом станут вдвое тяжелее, а ещё проектной толщины стенок может просто не хватить и придётся баки либо делать с ещё более толстыми стенками, либо ставить два бака рядом ( = существенное изменение конструкции). А ещё эти мешки с мясом туристы не только суммарно вдохнут вдвое больше, но и выдохнут вдвое больше, углекислый газ надо тоже куда-то девать.

А уж увеличение кабины в два раза - вообще смешно, это почти как в доме пытаться заменить лифт на вдвое более человекоподъёмный: мотор и трос ладно, а с кабиной-то что делать, пусть люди напихиваются вдвое плотнее? Тут надо всю шахту переделывать, а это перестройка части / всего здания... о чём и статья.

Или ещё лучше: ваша фирма производит фонарики, и вам пришёл заказ на 150 штук со следующими требованиями: питание от 3-х батареек AA, 1 лампочка накаливания, кнопку необходимо удерживать (не защёлкивается). "Отлично", думаете вы, "типичный набор компонентов".
Потом заказчик присылает письмо, в котором просит заменить лампочку на светодиод (в интернете вычитал, что они служат дольше и потребляют меньше энергии). Вы пожимаете плечами: "Ну ладно, конструкция почти та же самая, только вместо винтового патрона для лампочки - небольшая печатная плата со светодиодом."
Через 2 дня заказчик просит вас заменить батарейки на AAA, якобы для уменьшения веса. "Хм, придётся вставлять другой отсек для батареек, а отверстия от уменьшенных габаритов компенсировать дополнительными пластиковыми перегородками".
А затем заказчик просит вас поставить матрицу из 18 светодиодов, питание заменить на 3 батарейки типа D, а ещё добавить функции включения на половину и мигания красным. Как думаете, сколько компонентов у вас останется от предыдущей конструкции? Я думаю, что в лучшем случае кнопка

А как определить, сколько действий выполняет данный код, и самое главное - может ли количество действий в одном и том же коде различаться для разных задач/требований?

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

function print_quadratic_solutions(a, b, c) {
  const d = b * b - 4 * a * c;
  if (d < 0) {
    console.log("0 корней");
  } else if (d == 0) {
    console.log("1 корень", -b / (2 * a));
  } else {
    console.log("2 корня", -b - Math.sqrt(d) / (2 * a), -b + Math.sqrt(d) / (2 * a));
  }
}

Вроде логично разбить на 2 подфункции: решение и получение численных ответов, и печать, верно? А если следовать заветам Дядюшки Боба очень фанатично, то можно и до

такого дойти
function print_0_solutions() {
  console.log("0 корней");
}

function print_1_solution(x) {
  console.log("1 корень", x);
}

function print_2_solutions(x1, x2) {
  console.log("2 корня", x1, x2);
}

function print_solutions(x) {
  switch (x.length) {
    case 0: {
      print_0_solutions();
      break;
    }
    case 1: {
      print_1_solution(x[0]);
      break;
    }
    case 2: {
      print_2_solutions(x[0], x[1]);
      break
    }
  }
}

function get_number_of_solutions(d) {
  if (d < 0) {
    return 0;
  } else if (d == 0) {
    return 1;
  } else {
    return 2;
  }
}

function calculate_discriminant(a, b, c) {
  return b * b - 4 * a * c;
}

function solve_quadratic(a, b, c) {
  const d = calculate_discriminant(a, b, c);
  const n = get_number_of_solutions(d);
  switch (n) {
    case 0:
      return [];

    case 1:
      return [-b / (2 * a)];

    case 2:
      return [-b - Math.sqrt(d) / (2 * a), -b + Math.sqrt(d) / (2 * a)];

  }
}

function print_quadratic_solutions(a, b, c) {
  const solutions = solve_quadratic(a, b, c);
  print_solutions(solutions);
}

В 6 раз длиннее, зато каждая функция настолько мала, насколько возможно, ага.

А теперь представьте, что этот код размещён на HTML-странице, где есть поля ввода для a,b,c и кнопка для решения. Я бы вообще не стал делить этот код на функции, или даже отделять от получения значений из HTML-элементов, мне это кажется избыточным, я бы всё это поместил в единственный onсlick-обработчик.

И ведь никто не скажет как объективно лучше...

С мобильным рынком вообще страшно получается. Многие проекты - бесплатны, но с микротранзациями. Активно платящих игроков на самом деле не так много, подавляющее большинство или не платит вообще, или очень редко и немного; практически вся прибыль идёт от ничтожной доли "китов". И беда в том, что эта незначительная доля активных плательщиков может легко "протащить" проект через границу пороговой прибыли, после которой внезапно окажется, что все эти миллионы pure Free2Play игроков не просто "отбирают" у компании деньги на поддержку инфраструктуры, но и теперь вынуждают переводить их в Unity.

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

Аргументный аргумент, однако. Сколько миллиардов установок у какого-нибудь OpenSSL? Представьте, что они будут взимать плату с владельцев сайтов / хостеров за каждое посещение (пусть даже и после достижения определённого порога, пусть даже и только с тех сайтов, которые приносят какую-либо денежную прибыль владельцам). А то и вовсе GNU начнёт взимать плату за каждую установку бинарей, собранных с помощью GCC, вот хорошо будет.

Ну и да, Unity Runtime использует .Net - но ой как сомневаюсь, что они захотят отчислять, скажем, половину от своего Unity Runtime Fee в Microsoft...

Один нативно не поддерживает все эти типы. Чтобы работать с ними, нужно подтянуть некоторое количество зависимостей (библиотек).
...
Второй язык все это поддерживает нативно

Если второму языку не нужно даже библиотек для подключения к БД (то есть всё нужное есть либо в стандартной библиотеке самого языка, либо предоставлено специальным рантаймом) - значит он специально для взаимодействия с БД разрабатывался, так? А как у него обстоят дела с поддержкой всех других смежных областей, для которых требуется взаимодействие с БД? То есть, если, например, у меня есть вебсайт, работающий с БД - второй язык определённо удобнее с этой стороны, а что у него с поддержкой HTTP(S)? А другому пользователю нужно проводить аналитику по данным из БД - как дела со статистикой в этом втором БД-языке? А третьему пользователю... А четвёртому... То есть либо в итоге второй язык превращается в тот самый комбайн, от которых вы предлагаете избавляться, либо он хорош для одной-двух задач (например, конвертация данных из БД в один из текстовых форматов типа XML/JSON/YAML), а остальным всё равно придётся использовать нечто другое, вместо или вместе с этим БД-языком.

В одном языке вам для этого нужно создать объект string (опять конструктор вызывать) который содержит нужные методы.

Во втором ничего этого не надо - просто пишем цикл типа for-each word in split(phrase) и работаем непосредственно с той фразой, что получили из записи в БД. Без создания лишних сущностей (объектов).

То есть вы описываете примерно такую ситуацию, верно?

// Язык 1
var a = String("abcde");
a.split().forEach(process_segment);

// Язык 2.1
var a = "abcde";
forEach(split(a), process_segment);


// Язык 2.2
var a = "abcde";
split(a).forEach(process_segment);

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

Реализуете на JS? Будет работать?

Вы упустили (судя по вашему ответу и даже по цитате) два очень важных символа в моём предыдущем сообщении: /s. Это обозначение сарказма в текущем предложении (иногда в целом абзаце).
Но я не удивлюсь, если на npmjs.com найдутся пакеты для взаимодействия со многими +- распространёнными железками. Например, raspi-sensors (устаревший) или i2c-bus - раньше с железками на ASM/C взаимодействовали, потом пришла Arduino со своим C++ с библиотеками, более известном как Wiring (он был и до Arduino, но не так известен), а теперь вот можно и из JS битиками в провода пулять.

"Универсальный ЯП" - это что-то типа машины, которая и для Формулы-1 и для Париж-Даккар. Не находите, что несколько странная концепция?

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

То, насколько активно вы предлагаете дробить языки по их области применения, выглядит слишком уж радикально. Да, объединять всё в единый СуперЯзык+++ - не очень разумно, но и 100500 очень эффективных, но очень узкоспециализированных языков - это тоже перебор. Нелегко определить границу, когда "много" становится "слишком много", когда чайная ложка №317 - для клубничного мороженого, а ложка №318 - для шоколадного (у них разный состав сплава, что придаёт им чуть разный цвет, поэтому на фотографиях они смотрятся лучше именно так, а не наоборот). Нишевые языки конечно же могут существовать, но для их существования должно быть достаточно причин: востребованность, универсальность в рамках своей ниши (представьте, что, например, jq не умеет работать с JSONами, у которых корень - не объект), наличие ресурсов на поддержку и разработку (либо "замороженная" предметная область, что позволит сделать поистине готовый продукт).

И даже если будет множество ну очень уж хороших нишевых языков, всё равно будут востребованы пусть и менее удобные, но более универсальные. Примерно как если вы пишите программу для работы с медиафайлами, то для поддержки всего одного-двух форматов лучше подключить конкретные библиотеки (например, libflac + liblame), но если вы хотите более универсальный продукт - вы обподключаетесь по одной, намного проще сразу libav взять.

Хотя, универсальный язык существует, JavaScript называется. Скоро на нём перепишут вообще всё /s

освоить еще один абсолютно несложно

Если только вы при этом не прыгаете с одной парадигмы на другую. После многих лет отборного ООП, переход на (первый) функциональный язык будет... не столь быстрым.

Подскажите, почему в уравнениях Максвелла в одном случае операция умножения обозначается точкой, а в других "х"?

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

Вы предлагаете обобщить базовый синтаксис, но он и не является проблемой. Выучить ключевые слова и общие правила расстановки скобок и отступов в новом языке можно за день, а то и вовсе автоматически преобразовать имеющийся код к новым требованиям. Примерно тем же самым, только внутри одного языка, уже занимаются программы для автоформатирования кода. Условному astyle достаточно передать ровно 1 аргумент, чтоб привести код к одному из стандартных стилей. Даже если условные JS и Go требуют разного синтаксиса, то их по большей части можно преобразовать друг в друга, что даже сработает для простых случаев типа школьных заданий по информатике (вроде "Пользователь вводит 2 числа, программа должна вывести большее из них, или же написать что они равны").

Настоящая же сложность в том, что разные языки имеют разные библиотеки ( = разные имена системных констант, функций, классов, модулей, ит.д.), а самое главное - зачастую и разные идеи. В браузерном JS нет тредов, в лучшем случае service worker'ы, значит горутины не получится "просто переименовать". А прямого доступа к TCP/UDP нет вообще, только HTTP(S), WebSocket и RTP DataChannel, значит никакую программу, использующую другие сетевые протоколы вы в принципе не можете портировать без значительных изменений. А ни в JS, ни в Go нет поддержки настоящих, системных тредов, которая есть в Rust (и условный tokio позволяет очень легко запускать и таски = гринтреды = горутины). А паттерн-матчинг из того же Rust (match) чем заменять, switch-case ведь даже близко не подходит - цепочками if-ов?

Ибо генераторы абстрактных фабрик конфигураторов скриптов сборки нужного тебе проекта порой генерят не саму сборку а скрипт сборки в 40 тыщь раз больше чем сама прошивка.

Ох уж этот дивный мир сборки C, где сначала придумали make чтобы не писать shell-скрипты для сборки, а потом придумали automake чтоб не писать и тем более не шаблонизировать Makefile-ы вручную... В итоге генерируются configure-скрипты на 30 тысяч строк, которые затем (через пару минут работы) превращаются в Makefile на 5 тысяч строк.

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

Например, комментарии к модулям, классам и заголовкам функций (типа JSDoc / Doxygen / Rustdoc / etc.) часто используются IDE для показа подсказок при автодополнении или для автогенерации онлайн-документации - их определённо стоит поддерживать, хоть это и дополнительная работа.

С другой же стороны, что-то вроде

// convert inches to millimeters
length *= 25.4;

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

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

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

В комментариях пишут, что код слева/справа легче читается, но как будто никто не прочитал код полностью И слева, и справа написано по 28 строк, но слева на "обёртки" (заголовок + фигурные скобки - границы блока) функции ушло ровно 2 строки, а справа - 11 (немногим меньше половины, Карл!), причём по меньшей мере 3 функции там объявлены, но не реализованы.

Я понимаю, почему некоторые считают правый вариант более удобным/понятным, но есть же граница, когда дробление кода приносит больше синтаксического мусора, чем пользы. Тем более, очень это странное дробление:bake() создаёт oven с параметрами по умолчанию, но настройка = разогрев вынесен в отдельную функцию? Вы уж или factory / builder используйте, или настраивайте в этом же месте, а то ни туда, ни сюда. И почемуpizza инициализируется нужными значениями Base, Order и Cheese сразу, а не в 3 отдельных функциях?

Проблемы нет, просто хотелось напомнить, что если переменная (точнее, её тип) допускает значение, равное "ничего", то без проверки на это самое "ничего" не обойтись, независимо от языка и строгости/мощности его системы типов.

Кстати, очень интересно наблюдать за С-программистами, которые изучают алгебраические типы, и осознают, что type* - это фактически сумма NULL и non_null_ptr<type*>.

P.S. Зачем в JS, в отличие от большинства других языков, есть аж два разных "ничего" ( "ничего потому что ничего" =undefined и "ничего потому что так надо" =null) - отдельный интересный разговор.

Например, сортировку массива чисел по значению, а не лексикографчески :)

Как будто в базовом JS не надо проверять на undefined...

Да и TS не один такой, где переменную с типом, аналогичным any, надо проверять на пустое значение: в C это проверка указателей на NULL (а потом ещё и приведение к ожидаемому, а не фактическому типу), в C++ - на nullptr, в Python - проверка на None, в Go - на nil, и так далее. Даже с более мощными, полноценными алгебраическими системами типов, всё равно надо проверять Option на Some(x) / None в случае Rust или Maybe на Just x / Nothing в случае Haskell, хоть там это и зачастую удобнее, чем может предложить if.

Нормальная рекомендация, учитывая что WordPad - это лютый огрызок по сравнению с Word.

Как используют Блокнот - видел (как встроенный в Windows, так и более мощные варианты типа Notepad++), редактор Markdown (в лице VS Code и Obsidian) - видел, Word - видел, LibreOffice Writer - видел (сам использую), а WordPad - разве что на занятиях/курсах, но не для каких-то реальных задач.

Очень важно, что на графике видно, что оно действительно падает до нуля.

Нет, не видно. Масштаб там такой, что меньше примерно 5*10^{-4} ом см не разглядеть, слишком близко к оси X. При этом резистивность банальной, вовсе не сверхпроводящей меди - 1.7*10^{-6}ом см, то есть если бы она была на графике (ну, для сравнения, как это по-хорошему и должно быть), то её сопротивление тоже было бы "действительно равно нулю".

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

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

Тот же условный C позволяет одинаково открывать файлы в разных системах только благодаря тому, что систмено-зависимый код сокрыт в недрах stdlib. Если ваша программа была написана, скажем, с использованием pthreadов - она не соберётся в MS VC, потому что нет в Win тредов по-POSIXовски. А в MinGW/Cygwin - соберётся, потому что там pthread.h - это обёртка на Win-реализацией. А можно с самого начала использовать треды из какой-нибудь GLib, которая тоже обёртка над POSIX/Win-тредами.

Если фича конкретной платформы очень удобная, то обычно какой-нибудь энтузиаст делает библиотеку, которая на изначальной платформе - тонкая обёртка, а на других лишь эмулирует аналогичное поведение (иногда частично). Например, условная libnicequeue может напрямую использовать MessageQueue на AS/400, и быть толстой обвязкой поверх какой-нибудь ZeroMQ для Win/Linux.

В некоторых (многих?) дистрибутивах для root выключен вход из коробки, в /etc/shadow там что-то подобное:

root:!locked::0:99999:7:::

То есть ни напрямую рутом зайти, ни su не работают, только sudo. Можно, конечно, сделатьsudo passwd, но это уже не "из коробки".

Information

Rating
Does not participate
Registered
Activity