Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++. Глава 4. экскурсия по C++ #163

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

Intey
Copy link
Contributor

@Intey Intey commented Dec 11, 2024

Бранчевался от #162, потому суда включены изменения из нее.

@Microvenator
Copy link
Contributor

Давй добавим про вычисления в компайл-тайме?

@Intey
Copy link
Contributor Author

Intey commented Dec 11, 2024

Давй добавим про вычисления в компайл-тайме?

constexpr, consteval, шаблоны, X-макрос ?) Что-то конкретное или про все?)
я бы честно говоря пока бы не грузил этим. Будет же отдельная глава, которая просто расширяет возможности как раз в этом направлении

@Microvenator
Copy link
Contributor

Давй добавим про вычисления в компайл-тайме?

constexpr, consteval, шаблоны, X-макрос ?) Что-то конкретное или про все?)

constexpr, consteval, constinit. Что из этого и зачем юзается в связке с шаблонами.

@Intey Intey changed the title C++. Глава 4. экскурсия по C++ (только оглавление) C++. Глава 4. экскурсия по C++ Dec 16, 2024
# условия
Для управления потоком исполнения кода есть 3 варианта: `if`, тернарный оператор `?` и `switch`. Начнем с чисел, для примера.
## if ... else if ... else ...
Простой способ проверить а точно ли все у нас в порядке, использовать `if`:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

@Intey Intey Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Есть же 3 глава "Базовые концепции". Если конечно их как-то по другому сформировать, то да. Но я следовал от идеи "спирали" и наличия 3 главы, где как я понял, должно быть что-то про выражения и так далее.
И курс все же для абсолютных новичков? Я ориентировался на частично состоявшихся программистов и старался излагать в формате "а в C++ ифчик делается вот так, а не как в вашем питоне/java/c#".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Держим в голове, что в C++ можно попасть из совершенно разных языков. Можно и явы, которая синтаксически во многом похожа. Тогда читателю заранее все понятно. А можно из питона. Тут возникает шок от обилия скобок и точек с запятой. А если человек пришел из раста, мы должы составить текст так, чтоы он четко понял: if - это не выражение. if - это оператор.

Так вот. Глава "базовые концепции" развешивает ружья: объясняет, для чего точки с запятой и скобки разных видов. Что такое оператор, выражение, инструкция. Как одно соотносится с другим. В той главе могут появиться примеры каких-то конструкций из главы "экскурсия". Но лишь каких-то.

А в главе экскурсия ты окончательно расставляешь по полочкам конкретные языковые конструкции. Ты говоришь: if - это оператор. И выглядит он вот так.

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

Copy link
Contributor Author

@Intey Intey Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if - это не выражение. if - это оператор.

Выражение, пруф - cpprefence: if statement. Хотя мне тоже хочется сказать "оператор if".

Могу перефразировать попробовать, Сделать не настолько фамильярным. Тут как раз на контрасте
"Для управления потоком исполнения кода" и "все ли в порядке".
Попробую притянуть к первому варианту.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нет. Не путай statement и expression. В расте, @khva , поправь, если вру, if - это именно expression. Как и цикл. И это очень важно, потому что в таком случае ты можешь присвоить какой-то переменной результат ифа и результат цикла:

let big_n =
        if n < 10 && n > -10 {
            println!(", and is a small number, increase ten-fold");
            10 * n
        } else {
            println!(", and is a big number, halve the number");
            n / 2
        };

Если говорить про тонкости перевода, то есть operator (ну это точно "оператор"), expression (выражение) и statement. Вот statement я бы перевела как инструкция. Это всё, что заканчивается точкой с запятой или является управляющей конструкцией (иф, цикл, ...).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Выражение - это то что у ифа в круглых скобках) Но, повторюсь, сам иф выражением не является.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нет. Не путай statement и expression. В расте, @khva , поправь, если вру, if - это именно expression. Как и цикл.

Всё верно.

Copy link
Contributor Author

@Intey Intey Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Выражение - это то что у ифа в круглых скобках) Но, повторюсь, сам иф выражением не является.

Понял, дело в переводе. Я так понимаю, мы согласны, в том что if - statement, а не expression или operator.
Признаю косяк, оперирую понятием "выражение" кажется и для statement и для expression. Просто думаю я в англ терминах, а на русский транспалится уже в автомате с пометкой native. )

Вот statement я бы перевела как инструкция.

добро =) будет инструкцией.

```cpp {.example_for_playground ci-wrap=function}
// там где должно быть условие, мы можем сначала инициализировать переменную,
// чтобы ее видимость ну уходила дальше тела if
const int charsInThisChapter = 4000;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Предлагаю сразу на старте договориться о стиле кодирования: snake_case, camelCase, расстановке скобок и т.п. Чтобы примеры и задачи во всех главах выглядели единообразно.

@Microvenator какой стиль кодирования планируется использовать в курсе?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Давайте за основу возьмем гугловый как самый распространенный.

https://google.github.io/styleguide/cppguide.html

Тогда, кажется, у @Intey все в целом правильно, а я в своей главе поправлю стиль.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Microvenator

Currently, code should target C++20, i.e., should not use C++23 features.

Ну, наверно только стили, верно? )
Как участник многих holy war по code style, скажу - тут либо линтер в автомате (pre-commit, или уже CI-сборщик), либо оно так и останется только тут. Ну или кто-то будет ходить и на каждую скобку оставлять коммент. Берегите силы! Оно того не стоит)

Насчет линтера могу помочь, уже наработка есть.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Есть линтеры, которые могут корректировать код прямо в рамка md-файла?

Copy link
Contributor Author

@Intey Intey Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Есть линтеры, которые могут корректировать код прямо в рамка md-файла?

Его не сложно приготовить. Я написал небольшой скрипт который так же парсит md, выдергивает блоки кода и, пока что, просто прогоняет их через компилятор. Добавить вызов clang-format - тривиально.

if (const int magic=42; charsInThisChapter == magic) {
std::println("University, it that you?");
}
else if (charsInThisChapter == 4000) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь и в других условиях используются только операторы сравнения == и !=. Предлагаю упомянуть какие они бывают и разнообразить условия. Например:

if (charsInThisChapter < 2000) {
    std::println("too small");
} else if (charsInThisChapter > 4000) {
    std::println("too big");
} else {
    std::println("well, that was expected!");
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сделаем!

if (charsInThisChapter != 4000) std::println("Huston, we have a problem");
```

{.task_text } Вам же, предлагаю посчитать ворон. Представим, что вороны могут образовывать "табуны" (табуны это про коней, но допустим) по 2, 5, 10, 89 и 1000 штук. Напишите код, который напечатает для каждого из вариантов:
Copy link
Collaborator

@khva khva Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Вороны могут образовывать стаи. Табун типа для шутки, но не все поймут эту шутку.
  2. В HOMM названия few, several, pack и тд обозначают диапазоны. Здесь почему-то конкретные числа. Не логично.
  3. Всего в задаче 5 диапазонов (хорошо не всё 9), но всё равно не прикольно писать 5 веток if-else.

Сорри, задача в текущем виде не очень хороша. Предлагаю:

  • Использовать логику названия диапазонов из HOMM 3 в качестве демонстрации множественного if-else (не все 9 диапазонов, некоторые можно объединить). Это выглядит интереснее, чем количество символов в главе :)
  • Вместо этой задачи предложить студенту реализовать логику функции std::clamp(). Есть диапазон и число, если число попадает в диапазон, то возвращается само число. Если число больше верхней границы диапазона, то возвращается верхняя граница. И нижняя граница, если число меньше последней.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Может тогда уж расширим контекст задачи, мол "вот пишем HOMM3 аналог, нужен clamp, программировай"?
По идее логические операторы мы уже задели, чтобы написать условие вида:

if (count = 1 && count <= 4) println("мало");

Насчет всех диапазонов согласен. Можем предложить реализовать 2-3, а остальные (для примера и целостности) я ж сам добавлю?)

Copy link
Collaborator

@khva khva Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Задача может быть любая, главное, чтобы она укладывалась в 3-4 ветки условия. Лучше чтобы студент решал задачу полностью сам. Для сокращения количества веток можно объединить диапазоны, например:

  • few + several [1 .. 9] => few (несколько)
  • pack + lots [10 .. 49] => pack (группа)
  • horde + throng + swarm [50 .. 499] => horde (орда)
  • zounds + legion [500 .. ∞) => legion (легион)

Разбивка и названия могут быть любыми, главное, не больше 4.

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

C++ имеет стандартный набор логических операторов: отрицание !, И &&, ИЛИ ||.

Форма подачи на Ваше усмотрение, главное, чтобы читатель узнал как они выглядят в C++.

P.S. Идея использовать механики из игр хорошая! ИМХО

Copy link
Collaborator

@khva khva Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В дополнение к сказанному. Для возвращения результата лучше использовать переменную, а не println(). Так проще будет тестировать.

}

return a;
## тернарный оператор
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Intey
Большая просьба! Сделайте rebase или merge на мастер, чтобы изменения шли на чистую главу. Текущая псевдозамена очень мешает при ревью.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ух, я надеялся, что мерж !162 решит эту проблему (это как раз его изменения), но UI github не может с этим справиться. Поправлю

return a;
## тернарный оператор
Тернарный оператор - когда хочется все в 1 строке.
Его структура выглядит так: `CONDITION ? TRUE_EXPRESSION : FALSE_EXPRESSION`. Тернарный оператор, это выражение, которое вычисляется в некоторое значение, потому слева от его `CONDITION` можно поставить присваивание чему-то. Например:
Copy link
Collaborator

@khva khva Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Так же предлагаю договориться о форме нотации. На мой взгляд SCREAMING_SNAKE_CASE слишком кричащий :) Я бы предложил использовать что-то вроде такого:

<condition> ? <true expression> : <false expression>

Не настаиваю. Но Вам стоит договориться о форме нотации с @Microvenator

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Может, без треугольных скобок?)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Может, без треугольных скобок?)

Это как больше нравится :) Видел вариант, где для нотификаций используется курсир:

condition ? true expression : false expression

string message = charsInThisChapter == 42 ? "University, it that you?": "well, that was expected.";
std::println("{}", message);
```
Здесь мы значение `message` устанавливаем в зависимости от
Copy link
Collaborator

@khva khva Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

На мой взгляд акценты расставлены неправильно. Очень много уделено внимания как не надо использовать тернарный оператор. Лучше сместить акцент на то как надо!

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

const bool max = first > second ? first : second;

Как об этом лучше сказать - на Ваше усмотрение :) Главное акцентировать внимание на этом. Также нужно упомянуть, что оба выражения тернарного оператора должны иметь один тип.

Для демонстрации неправильного использования тернарного оператора достаточно одного примера с пояснением.

```cpp {.example_for_playground ci-wrap=function}
const int crowsCount = 1000;
string message = crowsCount != 89 ? (crowsCount != 1000 ? "неизвестно" : "легион") : "орда";
std::println("{}", message);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Желательно добавить задачу на использование тернарного оператора.

Пример выше, с определением размера вороньего табуна, можно переписать в новом виде:
```cpp {.example_for_playground ci-wrap=function}
const int crowsCount = 89;
switch(crowsCount) {
Copy link
Collaborator

@khva khva Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Пример неправильный. Нет ни одного break.

@Intey @Microvenator
Может не будем рассказывать про switch-case в этой главе? Конструкция полезная, но сильно реже используется чем тернарный оператор, а в сравнение с if-else тем более.

И чтобы два раза не вставать, про цикл do-while тоже предлагаю не рассказывать в данной главе.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да. Давайте про это скипнем. А то для глав про условия и циклы ничего не останется)

Описание курса.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Этот файл пока не трогай, заполню его отдельно)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хотел его отдельно прислать, а то постоянно терялся "кто ЦА" и так далее. Вот решил накинуть, выброшу из PR.

@@ -139,7 +139,7 @@ default:
# Циклы

## for
`for` как и в других СИ-подобных
Один из вариантов итерации - `for`. Его структура: `for (INIT; COND; STEP_ACTION)`. Это не совсем точно, но в общем плане чаще всего оно выглядит именно так.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Intey , ты только начал составлять текст, но боюсь, что замучаю тебя комментами по стилю/подаче материала. Мне бы этого не хотелось ;)

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

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

Один из вариантов итерации - for.

Ты кидаешь читателю ключевое слово как пирожок из печи) Представь, что ты только начал учить хаскель, и тебе вбрасывают: "Один из вариантов заведения псевдонимов - type". Что type?..) Конечно, дальше по тексту ты въедешь. Хоть и споткнешься о составленное таким образом предложение. Оно бы читалось проще, если бы звучало так: "Для заведения псевдонимов используется ключевое слово type".

Его структура: for (INIT; COND; STEP_ACTION).

Если с места в карьер расписывать, что это за INIT, COND и STEP_ACTION, восприниматься будет тяжеловато. Перед формальным описанием напрашивается наглядный пример.

Это не совсем точно, но в общем плане чаще всего оно выглядит именно так.

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

Один из вариантов организации циклов - с помощью инструкции for. Так выглядит вывод в консоль чисел от -5 до 8 в цикле for:

for (int n=-5; n<9; ++n) {
    std::println("{}", n);
}

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

@Intey не воспринимай, пожалуйста, этот коммент близко к сердцу. Мне @khva и @alexey-zakharenkov бывает по паре сотен замечаний выгружают, дело житейское)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Microvenator не волнуйся (надеюсь мы обоюдно перешли на "ты") за меня я уже отрефлексировал все это:

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

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants