LINUX.ORG.RU

ЛОР, помоги выбрать ЯП для обучения

 , , ,


0

3

Часто слышу просьбу научить программированию. Хотя пока я этим не занимаюсь, мне стало интересно, какой ЯП выбрать для введения в программирование.

Вот к каким мыслям я пришёл:

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

Не Си и не современные коммерческие языки (Java, C#, Go). Си, хотя примитивный в основе, усложнён из-за окружения, в котором используется. Современные коммерческие языки были созданы для решения проблем индустрии. Проблема общая: я хочу преподавать материал по мере нарастания сложности. Если в языке неизбежно приходится использовать классы или printf, то это затруднит объяснение (не хотелось бы слишком часто говорить «потом узнаешь для чего это нужно»), напугает студента (ему придётся писать код, используя возможности, которые он плохо понимает), создаст неправильное восприятие основ (как будто printf — это какая-то важная часть компьютера или ОС).

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

Языки, между которыми я выбираю: Pascal и Python.

Pascal устарел и денег не принесёт (обидно), но это и не является основной целью. Целью является программирование, а не современное окружение.

В частности, я не собираюсь задрачивать студента на Delphi или любой «продвинутый» диалект языка. Это противоречит цели. Я рассчитываю на то, что после должной тренировки “bare bones” нужно перейти на современный язык и это будет легко.

Важно упомянуть, что спека языка Oberon (Виртовский язык, тот же Паскаль, только упрощённый и доработанный) составляет 17 страниц.

Питон мне сложнее оценить, потому что я избегал работы с ним.

Если ограничиться императивным подмножеством, без ассоциативных массивов, классов и мета-классов, list comprehensions, HOF, исключений, то выглядит как альтернатива Паскалю. Хотя меня беспокоит динамическая типизация. Типы — очень важная вещь, хотелось бы чтобы язык помог это донести, а не быть типа «ну да, это важно, но ты забей».

Это все мои мысли.

Что касается практики, то я имел несчастье наблюдать как человек впервые знакомился с программированием, изучая Java на javarush. На это было больно смотреть.

Edit: дальнейшие пояснения по теме:

  • Почему не Си и не ассемблер: 1 2
  • Почему Паскаль: 1 2
  • Почему не Питон: 1
  • Целевая аудитория: 1
  • Почему такая размытая аудитория: 1 2
  • Про важность иерархии: 1


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

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

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

P.S. А ешё, при использовании перечислимого типа, вам для добавления нового гендера нужно будет каждый раз программу перекомпилировать. Не очень-то удобно.

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

в рамках с++ это шаблон функции, а не функция…

Вот я про то же. А в таком же статически типизированном Haskell это нормальная функция с типом (b -> c) -> (a -> b) -> a -> c. Ограничения системы типов ограничивают возможные алгоритмы.

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

Угу. Типы. Как бы произвольные.

Да.

а какие именно сможете угадать, если прочитаете реализацию класса

Плохо может назвал, но по сигнатуре можно сделать более понятно. И в IDE видно будет.

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

Я не пишу на С++ вообще, я не знаю его. Просто композиция объективно вредна.

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

все, на что хватает фортана 4, мы не рассматриваем как доказательный пример.

Т.о. ООП следует использовать только и только там, где это удобно, а вовсе не везде и обязательно. Ч.т.д.

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

Суть же в произвольном количестве?

#include <ranges>
#include <vector>
#include <array>
#include <iostream>
#include <numeric>

int main() {
    std::vector<std::vector<int>> v = {{1,2, 5}, {3,4}, {9}};
    auto r = v | std::views::transform([](auto arr){ return std::reduce(arr.begin(), arr.end()); });
    for (int i : r) {
        std::cout << i << "\n"; // 8 7 9
    }
}

Потому что если суть в разнородной структуре входных данных, то непонятно зачем тут mapcar. Начинать надо с того, как эту структуру хранить, я бы сказал что не надо хранить неопределенную по типу структуру вовсе. Если нужна реально динамика, то она строится поверх статики со своими правилами. Так же и в DB есть строгая таблица но можно перейти к EAV если очень нужно. Думаю работа с таблицами тебе более понятна по роду деятельности, или они тоже динамические у тебя?

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

Любой шаблон Си++. На каждую комбинацию типов создаёт по функции.

Ты не так понял, я просил пример использования твоей композиции в С++ коде.

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

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

P.S. А ешё, при использовании перечислимого типа, вам для добавления нового гендера нужно будет каждый раз программу перекомпилировать. Не очень-то удобно.

В справочник засунь.

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

Какая связь между математикой и скобчатой мудянкой?

Так математика и есть скобчатая мудянка. Хотя и на Си половина строк в листинге это { или }.

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

суть в разнородной структуре входных данных

Именно в них.

то непонятно зачем тут mapcar

Есть

int f(int x, std:string s, std::vector<int> z)
{
  return x + s.length() + z[0];
}

Как сделать

mapcar(f, {1, 2, 3}, {"a", "b", "c"}, {{1,2}, {3,4}, {5}})

?

Или вообще как-то менее уродливо, чем

for(auto i = a.begin(), j = b.begin(), k = c.begin();
    i != a.end() && j != b.end() && k != c.end();
    i++, j++, k++) { f(*i, *j, *k); }
monk ★★★★★
()
Ответ на: комментарий от watchcat382

В автошколе на втором занятии не выезжают на улицу,да и на площадку скорее всего тоже.

Знание ПДД, умение крутить баранку и умение водить по городу – это 3 разных умения.

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

Теория без практики мертва. Школоту никто не планирует подпускать к программированию контроллеров АЭС, так что самое плохое, что у неё может случиться, это программа не скомпилируется.

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

Как сделать

Для начала нужно не допускать что бы у тебя появились такие входные данные. У тебя проблема не в функциях, не в исполняющем коде, а в структуре данных.

С такой узкой постановкой без контекста, довольно трудно что то ответить, но например я бы рекомендовал перевести сначала это в формат int[][3], а там глядишь даже массив не понадобится, прямо в функции конвертации все вычислишь.

Для массива чисел компилятор и векторизацию применить сможет, одни плюсы.

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

Ты не так понял, я просил пример использования твоей композиции в С++ коде.

Ответ был на «Вот не уверен, что необходимость копипастить 100500 раз один и тот же код с чуть-чуть разными типами лучше ложится на железо.» / «А так и не надо делать. Можешь привести пример использования тоже если это просто.»

Что касается композиции, она очень активно используется в коде на Haskell. А на Си++ она очень жутко тормозит, поэтому практически неработоспособна.

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

Для каждой используемой. А если qsort обернуть в шаблон, то обёртка тоже начнёт копироваться на каждую используемую комбинацию типов.

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

Т.о. ООП следует использовать только и только там, где это удобно, а вовсе не везде и обязательно. Ч.т.д.

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

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

Ответ был на «Вот не уверен, что необходимость копипастить 100500 раз один и тот же код с чуть-чуть разными типами лучше ложится на железо.» / «А так и не надо делать. Можешь привести пример использования тоже если это просто.»

А, ну c_qsort элементарно оборачивается в шаблонную функцию.

Что касается композиции, она очень активно используется в коде на Haskell. А на Си++ она очень жутко тормозит, поэтому практически неработоспособна.

Лол, а пруфы есть? Потому что я не представляю какую оптимизацию Haskell может использовать, скорее всего никакую и еще GC сверху.

Для каждой используемой.

Если в машинном коде результат одинаковый то нет.

А если qsort обернуть в шаблон, то обёртка тоже начнёт копироваться на каждую используемую комбинацию типов.

Это не будет отличаться от обычного вызова qsort из С, то есть никакого копирования на самом деле не будет, скорее будет вызов. Ты же понял идею? Вызываем c_qsort() из template функции. Это одна строка в теле.

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

Для начала нужно не допускать что бы у тебя появились такие входные данные.

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

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

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

Так вот, читаешь из файла свою разнородную информацию, потом переводишь в int[][3], потом вызываешь sum. Компилятор векторизирует, память попросту не тратится, ошибки еще на этапе чтения устранены. Твое решение в динамике же выглядит очень нехорошо по сравнению, подходит лишь для однострочника.

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

Традиция именовать счетчик цикла буквой i - это наследие тех времен(видимо от слова iteration).

Числовые ряды старше Фортрана, как и тензорное исчисление. i, j, k, s – это индексы из математики.

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

она сломается с непонятной ошибкой, в рантайме

С очень понятной. Будет известно на каком элементе и из какого аргумента пришли неправильные данные.

в статике такое невозможно.

ЛОР, помоги выбрать ЯП для обучения (комментарий) - сломается, если в элементе третьего массива попадётся пустой массив.

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

С очень понятной. Будет известно на каком элементе и из какого аргумента пришли неправильные данные.

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

ЛОР, помоги выбрать ЯП для обучения (комментарий) - сломается, если в элементе третьего массива попадётся пустой массив.

Так это код не по уму, а наоборот. Вот когда у тебя сумма int[] сломается, тогда жалуйся. А такого не произойдет.

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

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

Опять система типов языка ограничивает возможные алгоритмы.

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

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

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

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

mapcar на системе типов сделать легко, реализуешь заново cons ячейки, реализуешь функции для работы с ними, и будет у тебя повторение динамики. Нужно ли такое? Абсолютно нет, так пишут только те кто не умеют программировать. «Заготовочку» из лиспа выучили, а нормально переписать не могут.

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

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

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

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

В смысле? Эти алгоритмы работают. И типы Typed Racket, например, им не мешают. Мешают типы ограниченных систем типизации.

Например, делает человек расчёт по формуле. Си++ заставляет выбрать между тремя типами: float, double, long double. Хотя с точки зрения задачи числа рациональные.

Или ограничение на int на целые значения, даже если это не указано постановкой задачи.

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

Например, делает человек расчёт по формуле. Си++ заставляет выбрать между тремя типами: float, double, long double. Хотя с точки зрения задачи числа рациональные.

Ну сделай свой расчет в классе с шаблонным параметром NumberType. Добавится только строка template <typename NumberType>, все! И вместо float, double погнал NumberType использовать. В чем проблема то?

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

Например, делает человек расчёт по формуле. Си++ заставляет выбрать между тремя типами: float, double, long double.

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

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

и еще. физическая реальность не может мешать. это максима.

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

Не правила именования идентификаторов, а правила именования идентификаторов Си.

Идентификатор - штука универсальная. Даже в PL/1 были те де правила - буквы,цифры и подчеркивание.

ссылаться здесь на Микрософт…

Противника надо знать в лицо. Да и позаимствовать что-то полезное у него не грешно - трофей однако!

Вот правила именования идентификаторов от Оракула

А там тоже самое - A-Z,a-z,цифры,подчеркивание и символ бакса.

The «Java letters» include uppercase and lowercase ASCII Latin letters A-Z (\u0041-\u005a), and a-z (\u0061-\u007a), and, for historical reasons, the ASCII underscore (_, or \u005f) and dollar sign ($, or \u0024). The $ character should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems.

The «Java digits» include the ASCII digits 0-9 (\u0030-\u0039).

Я предпочту, чтобы скачанный файл назывался 世遗之城.txt, а не shiweizhicheng.txt. Так хоть сразу понятно, что в файле.

Так это вам понятно. А большинство европейцев даже прочитать написанное иероглифами название не сможет. Не говоря уже о россиянах. И уж тем более расшифровать что это значит,учитывая многозначность толкования иероглифов. У меня оно хотябы не квадратиками показывается потому что я специально ставил китайские шрифты чтобы по их сайтам и форумам ходить. Иначе там часто верстка разъезжается,да и гуглопереводчику не скормить.

Кстати,хоть бы сказали что же в этом файле? Любопытно же!

Если они не знают русский язык, зачем им файл с русским именем и, очевидно, русским содержанием?

Там может быть исходник программы или электронная схема - они интернациональны. Я например однажды делал устройство на микроконтроллере Atmega для подключения PS/2 клавиатуры к arm-компьютеру имеющему только usb. За основу взял изделие некоего японца. К счастью иероглифами он не злоупотрелял. Вот описание той истории https://radiokot.ru/forum/viewtopic.php?f=61&t=100200

С таким же успехом можно рекомендовать избегать в именах файлов l, I, 1, O, 0. Они тоже у некоторых выглядят неотличимо.

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

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

Абсолютное большинство даже российских программистов не называют русскими буквами функции,переменные и прочие именованные сущности в своих программах - а чем имена файлов отличаются? Исключением будут разве что «программисты 1С».

Кстати, если избегать всех, которые неоднозначны в юникоде, то надо также избегать i, a, b, k, c, e, x, y, p, n.

Русские буквы й и ё не являются лигатурами.

Если европейские буквы с точками и крышками можно набрать как лигатуры то разве что-то технически мешает набрать также й и ё? Тем более что если русский текст станет набирать например француз то он легко может воткнуть туда букву из слова Citroën вместо «настоящей» буквы ё. Ибо в законах Мерфи сказано «Если что-то может пойти не так, оно пойдёт не так». Так вот не надо умножать случаи где что-то может пойти не так.

Так что не надо лишний раз юникодом ЗЛОупотреблять. Кстати, например авторы Питона это понимают и предусмотрели возможность указать локальную кодировку в которой был создан исходник посредством написания в начале псевдокомментария

#-*- coding: ХХХХ -*-

Был приятно удивлен когда пришлось иметь дело с питоном на микроконтроллере (точнее SoC) к которому был подключен экран у которого байт==символ. А у всяких знакосинтезирующих индикаторов это почти всегда так. Туда загружаются битовые карты символов потом эти символы выводятся на экран,как в текстовом режиме VGA.

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

Кстати,хоть бы сказали что же в этом файле? Любопытно же!

Возможно это подскажет: 世遗之城. С английскими крякозябрами: shiweizhicheng, фокус, понятно, не срабатывает.

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

В детстве нравилось собирать конструктор. Вот такой примерно.

Аналогично,такой же собирал. Начало 70х.

Каким типом вы предложите описать размер ноги?

Я думаю что перечислимым типом. Потому что множество существующих размеров ограничено и не велико даже если взять вообще все какие бывают. Да и называться они могут не только цифрами, а S,M,XXL и тому подобное.

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

Я думаю что перечислимым типом

В ваш обувной заходит квадробер. Теперь размер ноги — это два размера. Для передних ног и для задних.

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

Ну ты бы в моем ответе разобрался сначала. Я предлагал две таблицы

tbl_product и tbl_shoe_size, к одному tbl_product можно привязать сразу несколько значений. Вообще без изменений в итоге решается.

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

вас уже двое

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

Можете клуб организовать.

А вы используете в своих программах именование русскими буквами переменных,функций и прочих объектов? Чем например имя массива отличается от имени файла? И то и другое - идентификатор поименованной области памяти. Только в одном случае оперативной,а в другом - дисковой.

watchcat382
()
Ответ на: комментарий от MOPKOBKA

Лол, а пруфы есть?

Беру простую программу на Haskell:

$ cat test.hs
module Main where

import System.Environment

main = do
  [x] <- getArgs
  let n = read x :: Int
  putStrLn . show . sum . filter ((== 0) . (`mod` 2)) $ [1..n]

Перевожу её же на Си++ так, чтобы сохранить использование композиции для суммирования/отбора и компоновки условия.

$ cat ./test.cpp
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
#include <cstdlib>

long long sum(std::vector<int> x)
{
        long long result = 0;
        for(int i : x) { result += i; }
        return result;
}

auto filter(auto f)
{
        return [=](auto a)
        {
        std::vector<int> result;
        std::copy_if(a.begin(), a.end(), std::back_inserter(result), f);
        return result;
        };
}

auto compose (auto f, auto g)
{
        return [=](auto x) {
                return f(g(x));
        };
}

int main(int argc, char **argv)
{
        std::vector<int> v(atoi(argv[1]));
        std::iota(v.begin(), v.end(), 1);
        auto cond = compose([](auto x) { return x == 0; }, [](auto x){return x % 2;});
        std::cout << compose(sum, filter(cond))(v) << std::endl;
}

Компилирую, запускаю

$ ghc -O3 test.hs > /dev/null
$ time ./test 300000000
22500000150000000

real    0m0,553s
user    0m0,338s
sys     0m0,016s
$ g++ -O3 -std=c++20 test.cpp -o test-cpp
$ time ./test-cpp 300000000
22500000150000000

real    0m19,740s
user    0m2,097s
sys     0m2,311s
monk ★★★★★
()
Ответ на: комментарий от watchcat382

Чем например имя массива отличается от имени файла? И то и другое - идентификатор поименованной области памяти. Только в одном случае оперативной,а в другом - дисковой.

Тем, что идентификатор переменной обычно приходится показывать иностранным программистам. А файл на своём диске нет.

Если же писать на 1С, то там и имена массивов будут русскими буквами.

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

особенно среди грамотных пользователей ПК с большим стажем

И опытом борьбы с проблемами ms-dos, древних bsd и прочего хлама.

нарушение стандарта именования идентификаторов.

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

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

что будет делать ваша функция если ей на вход подать 32 часа и 65 минут?

Зависит от прикладной задачи. Например моторесурс дизель-генератора может быть не то что 32 часа,а тысячи часов. И программа должна уметь вычислять интервалы сервисного обслуживания,то есть выполнять арифметические действия с временем. Равно как и 65 минут могут быть вполне корректным значением в тех случаях когда традиционно используются минуты.

Если же задача предполагает что часов не может быть больше 24,а минут больше 60 то объявляем эти типы с ограничением диапазона значений и ни 32 часа ни 60 минут там оказаться просто не может - Аda сразу сгенерирует исключение.

watchcat382
()
Ответ на: комментарий от monk

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

std::vector<int> v(atoi(argv[1]));
std::iota(v.begin(), v.end(), 1);

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

Всё хорошо только до тех пор, пока системы типов хватает.

Согласен.

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

Это говорит о том,что или у программы неудачный дизайн из-за которого такая странная штука потребовалась,или если всё-таки без такой функции ну совсем никак не обойтись то значит неправильно был выбран язык под задачу. Надо не на Си/Паскале это писать.

На Си++ такую функцию можно написать, но у неё нельзя описать тип.

На Ada вроде бы тоже можно в последней версии стандарта но подробностей и ограничений не знаю так как ни разу не требовалось.

watchcat382
()

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

rebforce
()
Ответ на: комментарий от watchcat382

из-за которого такая странная штука потребовалась

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

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

Unix time прекрасен тем что про все это позволяет забыть.

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

ограничение на часы/минуты/секунды мало интересно.

Смотря где-когда. Например в управлении технологическими процессами и секунды важны бывают,не говоря о минутах.

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

Вот и получается, что использовать желательно три языка программирования.

  1. Racket или Python. Типизация не мешает, но при необходимости есть (Typed Racket и Mypy).

  2. Haskell или Idris. Нормальная типизация, позволяющая решить подавляющее большинство задач.

  3. C++. Если скорость выполнения программы очень критична.

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

Есть много языков со своими достоинствами которые мало где реализованы, если реализованы вообще.

Так если бы Ada была в числе «малореализованных» то я бы и не возникал. А так она есть и под общеупотребительные десктопные ОС и даже под микроконтроллеры STM32 и AVR(наверно и еще какие-то - просто не интересовался). И даже вроде бы есть вариант компилятора Ады,которые генерирует байт-код для андроидной джава-машины. Хотя я это тоже живьем не видел и не уверен что он бесплатный,только слухи слышал.

и библиотек больше.

В Аде есть штатные средства подключения сишных библиотек(не уверен насчет плюсовых). Я например писал когда-то адские «переходники» для подключения библиотеки C-Scape от Oakland Group - и получился хороший экранный интерфейс. Текстовый конечно так как было это году в 93 и дело происходило в ДОСе. Там правда есть тонкость - пакет с переходниками надо вдумчиво писать вручную чтобы хорошо получилось,а не автогенерировать скриптом как это нередко делают.

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

Но в более выразительных языках композиция функций не является странной штукой.

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

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

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

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

Хаскелл Карри поперхнулся чаем. А может и джином. Кто его знает. Хаскелла Карри.

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

Бесполезно учить человека рисовать кнопочку с реакцией через калбэк

Мне вообще такая логика построения программы не нравится. Может потому что я знаю способы написать иначе и даже когда-то писал.Правда под дос и интерфейс был текстовый,но кнопки и там были. И «mainloop» был в моей программе,а не в недрах библиотеки. Библиотека была C-Scape от Oakland Group и она умела работать в обоих вариантах - как с подсовыванием ей калбеков и главным циклом внутри,так и под «внешним управлением» теми же экранными объетами из своей программы,что позволяло более тонкое и точное управление. Причем еще и обходилась без плюсового синтаксиса! Ну очень приятная штука была!

я хз как можно объяснить человеку принцип работы калбэка без понятия ссылок.

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

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

Что указывать в качестве длинны члена для мужчин без члена

То же что указывают на банковском счете для мужчины без денег.

И тут в ваш магазин приходит квадробер.

И что? Список выпускаемых размеров обуви от одного квадробера никак не меняется. Вот если начнут выпускать специальные комплекты обуви для квадроберов и введут для них новую шкалу размеров - тогда придется эти размеры в обувной enum добавить.

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