LINUX.ORG.RU

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

 , , ,


0

4

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

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

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

Не Си и не современные коммерческие языки (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)
Ответ на: комментарий от monk

l, I, 1, O, 0

А вот это разумный совет. По крайней мере в паролях эти буквы лучше избегать.

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

Типизация облегчает рефакторинг, вызванный типизацией.

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

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

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

Задача экспорта ПО в ЕС решается использованием композиции массива «части тела». Там даже мутанты подойдут в таком случае.

В целом, мне видится, так что противники строгой типизации пропустили лекции по философии касательно понятия «категория». Им кажется, что Аристотель, Кант и Гегель какую-то фигню толкали.

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

Потому что «плохой дизайн» это на 90% попытки идти поперек того, как в языке принято что-то делать.

Вот тут не соглашусь с вами. Тем более про 90%. Плохой дизайн - он плохой вообще независимо от языка. Это так сказать следующий уровень абстракции. К примеру ожидание какого-нибудь события наглухо блокирующее работу интерфейса программы - это плохо на любом языке. Есть такой вобщем-то хороший почтовик Sylpheed,но если он полез за почтой по меееедленному каналу(через сотового оператора) то даже буквы в окне редактирования письма набираться перестают. Полное ощущение повиса. Аналогично,попадаются программы которые ничего полезного не делая тем не менее крутят холостые циклы и жрут электричество. Раньше часто встречалось,сейчас намного реже. Опять от языка не зависит. Даже на сайтах в скриптах попадается,тогда кушать начинает браузер с просто открым этим сайтом. А черезмерное использование глобально доступных переменных для связи между частями программы вместо передачи значений в виде параметров вызываемых функций. Тоже на разных языках такое нагородить можно.

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

в конце концов IT должно облегчать жизнь людям, разве нет?

Облегчения от него ничуть не больше чем новых неприятностей. Особенно если IT оказывается «на госслужбе».

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

1 + 1 = 1. занимательная арифметика.

Если «+» рассматривать как логическое сложение,то есть операцию ИЛИ, то выражение вполне корректно написано.

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

а новый год может наступить?

В строгом изложении он может только начаться как и любой другой промежуток времени. А что до разговорной речи -так в русском нелитературном очень многие действия одним и тем же глаголом выражаются и все всех понимают:)

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

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

Вот есть функция mapcar. Какой у неё тип? Первый агрумент «какая-то функция», а остальные «какой-то список»? Или надо на языке типов описать что-то вроде «первый аргумент является функцией, принимающей количество аргументов, равное количеству остальных аргументов mapcar, имеющих типы, совпадающие с типами элементов списков, являющихся остальными аргументами, mapcar».

Вот и получается, что на Си вместо типов 0.0..100.0 для доли в процентах и -273,15..+∞ для температуры в градусах Цельсия используют double. Потому что система типов не позволяет.

после некоего навыка это происходит автоматически

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

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

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

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

Безусловно да. Ну так и пишите функции. А выдумали какие-то reader`ы,потоки… Я именно к этому докопался,а не к тому что процитировал.

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

Проверяется во время компиляции или исполнения?

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

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

Дополнительная секунда добавляется по астрономическим наблюдениям в конце суток по всемирному времени 30 июня или 31 декабря так, чтобы время UTC не отличалось от UT1 более, чем на ±0,9 секунды. Считается, что в такие дни после времени 23:59:59 идёт 23:59:60[8].

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

В смысле? А как, например, начало Страстной Седмицы определять? С вычитанием получается легко и изящно: $ДатаПасхи - 7 дней.

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

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

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

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

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

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

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

На вопрос ответа не увидел. Если пол был enum, то что мешает добавить еще сколь угодно пунктов?

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

Странный вопрос, ну допустим я продаю обувь. Заведу справочник с размерами, где точно будет указан тип измерения, потому что они бывают разные, и его строковой вид. Числовое представление ОтДо по возможности и желанию.

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

гендеркомисару

лови шпиёна

гендеркомисаро гендерно нейтрально без этого вашего шовена

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

Вот есть функция mapcar. Какой у неё тип?

Посмотри на С++, там есть аналогичная функция.

Вот и получается, что на Си

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

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

Не верю.

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

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

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

ограниченные float значения хранимые в виде целых чисел выглядят очень вкусно

Там еще и типы с фиксированной точкой есть. Тоже полезная штука. И всё это есть аж с 1983 года. А в 1993 уже был доступен свободный компилятор Gnat (и коммерческий от Meridian Software тоже). В смысле что я сам именно тогда тем и другим пользовался,хотя «Меридиан» под ДОСом лучше работал. Но людям всё равно Лень изучать Аду. Будут продолжать с С++ мучиться.

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

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

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

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

всё остальное «опасно для детей»

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

А вообще это способ дать детям понимание как оно всё работает. Собственно это необходимо и в программировании. Бесполезно учить человека рисовать кнопочку с реакцией через калбэк, если он не понимает что такое калбэк, и я хз как можно объяснить человеку принцип работы калбэка без понятия ссылок.

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

Продали значит, свой рыночный продукт к нам в ЕС, а тут, внезапно, у мужчины члена не может быть вообще. И что теперь?

Указывать нулевую длину например. Например когда у мужчины нет денег на счете в банке указано 0. Хотя существует мнение что без денег это не мужчина а самэц:) https://www.anekdot.ru/id/-10088000/

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

Если пол был enum, то что мешает добавить еще сколь угодно пунктов?

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

Странный вопрос, ну допустим я продаю обувь. Заведу справочник с размерами, где точно будет указан тип измерения, потому что они бывают разные, и его строковой вид.

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

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

Указывать нулевую длину например.

И в функции, которая определяет во сколько раз самый длинный длиннее самого короткого как max(penis_size) / min(penis_size) внезапно возникает деление на ноль. Сегфолт, продукт падает, акции падают, у всех всё падает, а виноваты в этом вы. При этом предполагалось, что система типов как раз от такой беды и должна защищать.

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

тут, внезапно, у мужчины члена не может быть вообще

КСЖ!

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

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

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

вы, батенька, ретроград.

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

Я же говорю - пришлют вам китайцы файл с именем из иероглифов тогда поймёте о чем я. Впрочем - даже они выкладывая в интернет файлы (например документацию на свою электронику) именуют их латинскими буквами.

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

Кстати,еще более трудноуловимые глюки происходят если в имени файла случайно смешиваются русские и латинские буквы. Особенно этому подвержена буква «С» - потому что и выглядит одинаково с латинской,да еще и на одной кнопке с ней находится. А типичный сценарий этой ошибки такой: пользователь начинает набирать имя файла, начинающееся с этой буквы,но забывает посмотреть какая раскладка включена. То,что на экране набирается что-то не то - он обнаруживает на втором-третьем символе. Стирает «неправильные» символы,включает нужную раскладку и продолжает набор имени. Вот только первый символ визуально для него выглядит правильным и он его не стирает так как типично «с» от «c» отличаются мало или вообще никак. Ну и получается или латинское имя файла с первой русской буквой или русское с первой латинской. Первое конечно создает больше проблем чем второе.

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

Будет легче если ты будешь нормально писать, а не как сиделец из дурки. Я читаю с самого начала.

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

Синдром утёнка: Закрепление признаков объектов происходит преимущественно на ранних этапах жизни, чаще всего вскоре после рождения, и возможно лишь в течение определённого, обычно весьма ограниченного, срока — «сенсибильного» (или «критического») периода. Как правило, результат запечатления с очень большим трудом поддаётся дальнейшему изменению («необратимость» результатов запечатления).

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

Впрочем - даже они выкладывая в интернет файлы (например документацию на свою электронику) именуют их латинскими буквами.

Я уже отвечал на это, китайцы любят свой язык, если зайти в топ GitHub, то будет много проектов чисто на китайском https://github.com/jeecgboot/JeecgBoot

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

https://github.com/648540858/wvp-GB28181-pro/tree/master/数据库/old

Я же говорю - пришлют вам китайцы файл с именем из иероглифов тогда поймёте о чем я.

Для меня это тоже самое что и файл на английском. Однако если им удобнее китайский, я не только за.

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

Вот и получается, что на Си вместо типов 0.0..100.0 для доли в процентах и -273,15..+∞ для температуры в градусах Цельсия используют double. Потому что система типов не позволяет.

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

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

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

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

mapcar // Посмотри на С++, там есть аналогичная функция.

Где? Как называется, в какой библиотеке? Если речь про std::transform, то он только 2 или 3 аргумента принимает, а не сколько угодно как mapcar. И у неё нет типа, так как она шаблон-макрос.

Не верю.

По себе замечал, когда переходил с CL/Racket на Haskell. Если на CL написанная мною функция, использующая битовое поле, позволяла вызывать себя с числом, списком символов, символом.

(set-state 3)
(set-state :ok)
(set-state '(:wait :red))

то в Haskell строго

setState [Ok]
setState [Wait, Red]

Потому что писать вариантный тип неуклюже (лишнее слово на каждый вызов).

А если вдруг всё-таки надо число, то setState $ intToState 3

Везде, где результат был «значение или ошибка» как в cl:nth, ошибка заметается под ковёр как в Haskell a[x].

а из за того что это ненужная шняга которая плохо ложиться на железо.

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

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

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

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

Попробуйте написать, не используя auto.

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

а не сколько угодно как mapcar

Напиши пример с 4 аргументами, не понимаю о чем ты.

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

А так и не надо делать. Можешь привести пример использования тоже если это просто.

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

Если ты хочешь обобщенную функцию, то auto в самый раз. Так себе у тебя задача. Кстати, обрати внимание что она удобно без GC не решается.

Дальше нужно будет у std::vector тип элемента зафиксировать, и лишь тем самым подтвердить нужность типизации?

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

Попробуйте написать, не используя auto.

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

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

Если ты хочешь обобщенную функцию

это не обобщенная функция, а просто шаблон для построения конкретных функций.

alysnix ★★★
()
Ответ на: комментарий от monk
#include <iostream>

template <typename X, typename Gr, typename Fr>
struct compose {
  using G = Gr(*)(X);
  using F = Fr(*)(Gr);
  G g; F f;
  compose(G g, F f) : g{g}, f{f} {}
  Fr operator()(X x) { return f(g(x)); }
};

int add10(int x) { return 10; }
float mul125(int x) { return x * 1.25; }

int main() {
  auto f = compose{add10, mul125};
  std::cout << f(5) << "\n";
}

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

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

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

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

Вы должно быть из Питера?

Пока нет. Уже словил вайб, когда туда повторно тянет. Вот цены на мавзолеи припадут, а там посмотрим :)

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

Хранить проще в unix time.

Сильно зависит от области применения. Если например это административно-бухгалтерские расчеты (с этим приходилось иметь дел в 90х) - то вычисление каких-нибудь «номочасов» существенно отличается от астрономического времени. Есть «нормочас»,может использоваться (а может и не) половина нормочаса. Это надо согласовать с бухгалтерским начальством и его сложившейся практикой учета. Не бывает нормоминут и нормосекунд. Поэтому хранить и считать надо в минимальных используемых единицах - если это часы то в часах,если есть половинки то в половинках. И всячески избегать операций деления и округления,которые дают дробные «хвосты»,накапливающиеся к концу отчетного периода. Кстати,правильное округление это две страницы текста в старом математическом справочнике для экономистов. В школьном учебнике вам соврали что это просто. Далее,при переводе нормочасов в количество рабочих смен,которое официально предписывается «производственным календарем»(докУмент,который утверждает Минтруд) - бывают свои казусы. Например ночная работа может учитываться с каким-нибудь коэффициентом. И это я еще далеко не всё перечислил с чем сталкивался.

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

Вспомним Гаусса,который сказал: «Недостатки математического образования с наибольшей отчётливостью проявляются в черезмерной точности численных расчётов» - это к вопросу об использовании числа секунд с 1970 года.

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

Напиши пример с 4 аргументами, не понимаю о чем ты.

* (mapcar 
    (lambda(x y z) (+ x (length y) (car z)))
    '(1 2 3)
    '("ok" "test" "go")
    '((1 2) (3 4) (5 6)))
(4 9 10)
monk ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Как это произошло? Использование boolean?

Правильнее будет использовать перечислимый тип,который при необходимости не трудно дополнить новыми возможными гендерами. По разным подсчетам сейчас существует от 46 до 78 гендеров. Например Tinder использует 36 гендеров для более точной самоидентификации своих пользователей.

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

Сильно зависит от области применения.

Несогласен, для времени он почти везде единственный правильный выбор.

то вычисление каких-нибудь «нормочасов» существенно отличается от астрономического времени.

А это не время.

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

Хранить надо так, что бы потом можно было пересчитать %) То есть источники расчетов.

И всячески избегать операций деления и округления

Округления бывают разные, и везде свои правила.

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

Время и даты в человеческом виде действительно очень и очень сложная штука, unix time это легко.

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

(lambda(x y z) (+ x (length y) (car z)))

Тут достаточно заменить лисповое определение lambda на void lambda(std::any_container<>), потому что именно как то так твои «аргументы» в нее и будут попадать.

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

А так и не надо делать. Можешь привести пример использования тоже если это просто.

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

Если

void qsort(void *base, size_t nmemb, size_t size,
   int(*compar)(const void *, const void *));

имеет одно тело, то std::sort для каждой пары «тип итератора» + «тип функции сравнения» будет создавать по копии тела.

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

Покажи аналогичный вызов для Си++. Пусть вместо аргументов-списков будут std::vector для простоты.

monk ★★★★★
()
Ответ на: комментарий от MOPKOBKA
template <typename X, typename Gr, typename Fr>
struct compose {

Угу. Типы. Как бы произвольные. Но на самом деле не произвольные, а какие именно сможете угадать, если прочитаете реализацию класса. А при любой ошибке получите «no matching function» без указания, какие типы возможны.

но нужность хотя бы одной композиции еще нужно выяснить

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

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