Pull to refresh

Comments 113

На мой взгляд, начинать обучение программированию следует с алгоритмизации. А тут чем проще язык, тем лучше. И C не подходит для этой цели. Это очень мощный язык и для новичка теряется фокус.
Куда уж проще Си-то? Наследование, интерфейсы, компараторы, что? То ли дело стандартная либа Си. Около сотни функций из которых постоянно дай бог десяток нужно. Даже не представляю, что представляет собой 99% библиотеки C# и как этим пользоваться.
Сам синтаксис не прост. Ой как не прост. Это отвлекает от сути. Вместо того, что бы вникать в основы программирования, приходится вникать в язык C. Т.е. начиная с C, вы изучаете именно C, а не программирование как таковое. В этом проблема.
Ага. Давайте учить Haskell, Scheme или хотя бы Forth. Минималистичный синтаксис, ни какого наследования!
не, начинать надо с языка, исходники которого легко читать с гитхаба и смотреть как на нем вообще пишут, не углубляясь в магию. А Си — это магия указателей и макросы, язык грязных хаков. Чтобы легко читать на си придется развить внутренний препроцессор и резолвер указателей.
То, что С — язык грязных хаков…
Простите, но вы сейчас напердели в душу, я думаю, трети населения хабра.
ой, да ладно вам дуться. Вот на гитхабе ребята более самокритичны относительно хаков https://github.com/search?q=ugly+hack&ref=reposearch&type=Code&utf8=%E2%9C%93
Это почему в хаскеле наследования нет?
Потому что подтипы сильно усложняют проверку и автоматический вывод типов. И компилятору, и программисту.
Ну я так рассуждаю — если полиморфизм есть и типы есть — значит есть наследование. Оно может не совсем C-like, но есть.
UFO just landed and posted this here
Тайпкласся не совсем наследуются. Там можно описать ограничение, что тип данного класса обязан реализовать и другой класс. А так как классы могут связывать несколько типов, и наследование уже не будет графом.
UFO just landed and posted this here
Для ООП если кто-то реализует B, то он автоматически реализует A. Хотя согласен, что общего много. Из-за этого вывод типов иногда не справляется.

Бывают классы вроде
class Vecspace v f where
  mul :: f -> v -> v

Для них зависимости объяснить наследованием будет сложнее.
А что там сложного?

#include <stdio.h>

int main() {
    int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int sum = 0;
    int i;

    for (i = 0; i < 10; i++) {
        sum += arr[i];
    }

    printf("Your sum is: %d\n", sum);
    return 0;
}

А биты, байты, размерность переменных, переполнение, sizeof, символьные последовательности, ука.затели — это из разряда must know в любом случае.
биты, байты, размерность переменных, переполнение, sizeof, символьные последовательности, ука.затели — это из разряда must know
Вы могли бы пояснить, почему это must know? Во многих современных языках биты, байты, указатели – это всё под капотом и позволяет сосредотачиваться на главном – на самом программировании. Условно говоря, чтобы быть хорошим водителем автомобиля с автоматом (не пилотом болида, прошу заметить), мне не важно, как устроен двигатель, кроме самых общих представлений. Мне важнее знать ПДД.

Ах, да. Должен ли начинающий программист изучать ассемблер?
Под капотом это хорошо, удобно. Но понимание всегда лучше, чем заучивание и принятие «на веру». Если ты знаешь, как устроена память, не нужно будет потом часами вникать, например, почему же deepcopy такой медленный.

Поэтому вопрос, must know или не must know — это личный вопрос каждого начинающего программиста. Хочет понимать, как устроено — учит внутренности, не хочет учить внутренности — stackoverflow ему в помощь. Аналогично и с ассемблером.
Программист, который действительно серьезно думает о том как стать лучше — да. Посмотрите ка на чем написаны TACP Кнута. Мix — это ассемблер и есть. Пусть и под выдуманную машину.
UFO just landed and posted this here
1) #include <stdio.h> — подключение библиотеки ввода-вывода, без понятий «ввод-вывод», «библиотека», «подключение библиотеки» в отрасли делать нечего.

2) int — целое число, целые числа проходят максимум в шестом классе общеобразовательной школы, кстати, тогда же проходят и дробные числа (float); освоение всей сути чисел с плавающей запятой можно спокойно отложить года на 2-3.

2) arr[10] — выделение памяти под 10 ящичков с числами, без понятия «выделение памяти» (хоть на стеке, хоть в куче) в отрасли делать нечего. Явно писать [10] нужно для того, чтобы выделить память именно под 10 ящиков. Кроме того, если не ошибаюсь, стандарт C99 поддерживает объявление и инициализацию массива без указания размера. Кроме того, можно использовать конструкцию «int arr[10] = {1, 2, 3}», чтобы создать 10 ящиков, в первые 3 положить числа 1, 2 и 3, а в остальные 7 — нули.

3) = — оператор присваивания (положить в ящик) — есть хоть один ЯП, который его не имеет?

4) {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} — запись чисел от 0 до 9 в ящики, которые были подготовлены в п. 2

5) Потому что в «int sum = 0» происходит создание ящика и запись туда значения, а в «int i» — только создание ящика (закрепляем понятия «выделение памяти», «оператор присваивания»). При желании, можно всегда присваивать переменным значения при инициализации, заодно и обезопасить себя в будущем (в Java, например, это вообще обязательно).

6) Насчет printf согласен, для обучения было бы проще избегать форматирования, однако тут мы узнаем понятия «символ переноса строки» и «форматирование строк».

7) C — это такой язык, в котором любая функция, если она не void, должна явно возвращать значение. Обязательный явный возврат значений вырабатывает полезную привычку не забывать писать return, а также позволяет при беглом взгляде на код сразу же найти точки выхода из функции (особенно при диковинных ветвлениях, которые так свойственны начинающим при изучении алгоритмов). Кроме того, возврат значения из функции main определяет код завершения работы программы. Понятие «код завершения работы программы» на ранних этапах обучения необязательно к изучению (в этом случае функцию main можно просто объявлять как void), но все равно полезно.

Тем, кто подобную информацию освоить не в состоянии, предлагаю использовать язык HQ9+. Обычные ученики 10-го класса обычной общеобразовательной школы вполне в состоянии прослушать мини-лекцию (1.5 урока) по адресации и статической маршрутизации в сетях IP и затем применить полученные знания на практике путем составления плана разбиения сети класса C на N подсетей с переменной маской подсети, а затем составления статических таблиц маршрутизации для произвольных узлов подсетей. Так что не надо считать начинающих программистов дебилами, неспособными за два-три урока освоить азы языка C.

P.S. Хотелось бы видеть подобную программу на любом другом хоть как-то типизируемом (на JS я тоже могу однострочник написать, ага) ЯП, мне тоже хочется покритиковать немножко ;)
P.P.S. Если что, я вообще пишу на Python и Javascript.
P.P.P.S. Да, с ассемблером тоже знаком.
P.P.P.P.S. www.lib.ru/CTOTOR/starterkit.txt — пригодится ;)
P.S. Хотелось бы видеть подобную программу на любом другом хоть как-то типизируемом (на JS я тоже могу однострочник написать, ага) ЯП, мне тоже хочется покритиковать немножко ;)


Пожалуйста:

main = putStrLn $ "Your sum is: " ++ (show $ foldl (+) 0 [1..9])
А что такое $?
А зачем $ нужен?
А если я напишу a $ (b $ c $ d) $ e $ f $ g, где a, b, c, d, e, f, g — лямбды, что будет?
А что такое foldl?
А что такое (+)?
А почему он в скобках?
А что там делает 0?
А если туда другое число поставить?
А можно нумерацию в скобках с нуля?
А почему у %username% в PHP нет такого количества непонятных символов?

P.S. А код таки красивый ;)
А что такое $?

Это правоассоциативный оператор применения функции с низким приоритетом.
то есть f $ x — это то же самое что f(x).
А зачем $ нужен?

В большинстве случаев он используется для того что бы не писать скобки группирующие операции в выражении, кроме того иногда частично примененный $ удобно передать в функцию высшего порядка, например
map ($ 2) [\x -> x ^ a | a <- [1..10]]
вернет все степени двойки от 1 до 10. Здесь в map мы передаем список лямбд и функцию ($ 2), которая вызовет каждый элемент списка с двойкой в качестве аргумента.
А если я напишу a $ (b $ c $ d) $ e $ f $ g, где a, b, c, d, e, f, g — лямбды, что будет?

Будет a((b(c(d)))(e(f(g)))).
А что такое foldl?

Левая свертка.
А что такое (+)?

Функция суммирования двух аргументов.
А почему он в скобках?

Потому что его нужно привести к префиксной форме для передачи в функцию.
А что там делает 0?

Это стартовое значение для функции свертки.
А если туда другое число поставить?

Результат будет отличаться на величину этого числа.
А можно нумерацию в скобках с нуля?

Можно.
А почему у %username% в PHP нет такого количества непонятных символов?

Не правда, есть. Там долларов еще больше чем в хаскеле.
Вам намекают на вопросы новичка которому выдали такое, вам-то конечно оно все понятно, да вот только это не для вас
А зачем foldl (+) 0? Есть же sum

main = putStrLn $ "Your sum is: " ++ (show $ sum [1..9])

sum ведь реализовать надо, а не использовать готовый.
Вроде бы в корневом комментарии речь шла о сложности синтаксиса, а не о том, что нужно реализовывать какую-то функцию «своими руками». Библиотечная sum упрощает дело (и, кстати, делает синтаксис более понятным).
Хорошо, тогда вброшу решение на Python.

print("Your sum is :", sum(range(10)))
Раз уж вы решили не повторять код на си и не создавать массив ( в котором могли бы хранится любые другие значения не возврастающая прогрессия ) то вот там си аналог вашего кода:

#include <stdio.h>

int main() {
    printf("Your sum is: %d\n", (0 + 9) * 10 / 2);
}


зы: return 0 в функции мейн не обязателен уже давно насколько я помню.
Можно даже проще:

#include <stdio.h>

void main() { printf("Your sum is: 42^W 45\n"); }
P.S. Хотелось бы видеть подобную программу на любом другом хоть как-то типизируемом (на JS я тоже могу однострочник написать, ага) ЯП, мне тоже хочется покритиковать немножко ;)

Немного скалы:

println("Your sum is: " + (1 to 10).sum)
Сам себе отвечу на Go (так сказать, для коллекции):

package main

import "fmt"

func main() {
	arr := []int{0,1,2,3,4,5,6,7,8,9}
	sum := 0
	
	for _, x := range(arr) {
		sum += x
	}
	fmt.Println("Your sum is:", sum)
}

подключение библиотеки ввода-вывода, без понятий «ввод-вывод», «библиотека», «подключение библиотеки» в отрасли делать нечего.

Хм… можно вспомнить, прости господи, Basic. Только не надо ставить минусы, потому что не нравится этот язык — я просто привел пример.

2) int — целое число, целые числа проходят максимум в шестом классе общеобразовательной школы, кстати, тогда же проходят и дробные числа (float)

Одно дело — знать, что такое целое и дробное, другое — понимать, почему типы разные для целого и дробного. На этапе обучения самым азам — это лишняя деталь. Достаточно понимать, что есть, скажем, «число» и «строка».

2) arr[10] — выделение памяти под 10 ящичков с числами, без понятия «выделение памяти» (хоть на стеке, хоть в куче) в отрасли делать нечего.

При чем тут отрасль? Могу тогда вам сказать, что без знания ассемблера (мнемокодов), машинного языка (бинарник), детального понимания электроники на уровне проектирования кристалла — в отрасли делать нечего.
Напомню, разговор шел об обучении азам, начиная с алгоритмизации. На зачем козе баян при обучении алгоритмизации вдаваться в детали реализации массива в конкретном языке? Есть другие, в которых массив можно создать динамически.

5) Потому что в «int sum = 0» происходит создание ящика и запись туда значения, а в «int i» — только создание ящика (закрепляем понятия «выделение памяти», «оператор присваивания»)

При обучении азам, алгоритмизации «создание ящика» — ненужная деталь. Это слишком низкий уровень. Для первичного обучения достаточно «у нас есть ящик i, в нем будет лежать номер ячейки, с которой мы работаем». И «укажем, что начинаем с ячейки 0», как отдельный шаг.

Обязательный явный возврат значений вырабатывает полезную привычку не забывать писать return

… который нужен именно в Си.

P.S. Хотелось бы видеть подобную программу на любом другом хоть как-то типизируемом (на JS я тоже могу однострочник написать, ага) ЯП, мне тоже хочется покритиковать немножко ;)


OK, чисто в порядке бреда (массив списком нельзя инициализировать):

dim i, sum, element

for i = 0 to 9
  read element
  sum = sum + element
next i

print "Your sum is:"; sum

data 0,1,2,3,4,5,6,7,8,9 


dim нужен только для типизации (можно указать AS INTEGER), так можно и опустить.
UFO just landed and posted this here
А биты, байты, размерность переменных, переполнение, sizeof, символьные последовательности, ука.затели — это из разряда must know в любом случае.
Ваши взгляды на обязательные знания в программировании устарели лет этак на 20-30. В наше время можно окончить обучение на программиста, получить корочки и сертификаты, комитить в опенсоурс, работать, периодически меняя место на более высокооплачиваемое, дорасти до архитектора и выйти на пенсию, так и не узнав о том что такое
биты, байты, размерность переменных, переполнение, sizeof, символьные последовательности, указатели
Плохо это или хорошо — уже совсем другой вопрос. Но, факт, можно жить и без этого.
Нууу… Без одной почки, в общем-то, тоже можно жить ;)

Я выше более подробно изложил свою точку зрения. Да, я считаю, что те вещи, с которыми ты работаешь, нужно знать на пару уровней ниже, чем необходимо для работы. И это касается не только программирования, но и даже обычной шариковой ручки — чтобы потом не злиться, от того что она на потолке не пишет.
Если говорить о ручке, то для успешного её использования вовсе не обязательно знать химический состав чернил, показатель их вязкости, правила перезаправки стержня и утрамбовки этой полупрозрачной гелевой штуки, предотвращающей чернила от вытекания.
Ты просто пользуешься ручкой как ин-стру-мен-том, на собственном опыте определяя границы её возможностей (по побелке потолка пишет плохо, по бумаге хорошо).
Для этого требуется лишь о-пыт. Понимание внутренних процессов не о-бя-за-тель-но!

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

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

Клеймить писателей ручками (пользователей современных высокоуровневых языков программирования) за это всё равно что[...]
Еще раз приведу свою цитату:
Поэтому вопрос, must know или не must know — это личный вопрос каждого начинающего программиста. Хочет понимать, как устроено — учит внутренности, не хочет учить внутренности — stackoverflow ему в помощь.
UFO just landed and posted this here
В Си («C») нет наследования, интерфейсов и пр. Всё вышеперечисленное относится с Си-Плюс-Плюс («C++»). А это несколько более другой язык.
Я в курсе. Я именно про то, что ни один другой язык без этой шелухи не обходится.
Pascal — очень простой чзык. Обходится без этой «шелухи».
А еще он практически мертв и я бы не сказал, что он хоть сколько-то проще Си, если в последнем делать всё по книжке.
Его используют для обучения алгоритмизации. При этом не заморачиваясь на особенности самого языка. Свою задачу он выполняет на все 100%.

Вот пример изучения C++ по книге.
image

С проще чем С++, но суть в том, что как язык программирования для обучения программированию он не подходит — слишком сложный. Поняв основы алгоритмизации на безе того же Pascal, можно уже браться и за С. Да, Pascal сам по себе сейчас уже вряд ли пригодится. Но он и не является целью. Он только средство.
Выше уже заметили, что «C» и «C++» — суть разные языки. Не нужно путать. Классический ANSI C будет не сложнее Pascal.
И ещё не стоит смешивать вопросы изучения и знания языка программирования с вопросами знания и изучения фреймворков и стандартных библиотек (API) написанных на этих языках.
Можно и С использовать не заморачиваясь над особенностями самого языка. В паскале, знаете ли, тоже есть указатели, структуры. Так же, как Вам уже написали, вы очень сильно заблуждаетесь на счет сходства С и С++. Не могу представить что такого сложного для понимания есть в С, чего нету в паскале.
В паскале, знаете ли, тоже есть указатели, структуры.

Это значит, что ими можно пользоваться, но не значит, что нужно.
Если в Си мне надо передать переменную, которая будет изменяться, в процедуру, я должен разобраться с указателями. И использовать вырвиглазный дереференс для простого присвоения. Там попутно идет арифметика, Сишное представление массива как указателя на ячейку и т.д. В Паскале же переменная просто передается вовнутрь, нужно указать спецификатор «var» перед именем и все. В некоторых языках, том же Basic, все параметры по умолчанию сквозные — это еще лучше при обучении.
UFO just landed and posted this here
Нет, я именно о консольном турбо. Там указатели необязательны, для обучения — самое то.
Да и при чем тут библиотека/фреймворк?
Pascal — язык, который был придуман и разработан Н.Виртом специально для обучения студентов программированию. Является прямым потомком и наследником Algol.
ДЛЯ ОБУЧЕНИЯ Си от Паскаля отличается видом операторов, если объективно. Особенно когда ВНЕЗАПНО окажется, что в Паскале тоже есть указатели и динамическое выделение памяти. На крайняк можно написать маленькую среду, которая будет с помощью Валгринда отслеживать переполнения буфера и прочую няшность и разница испарится окончательно.
UFO just landed and posted this here
Нужно различать разные диалекты П. ООП (действительно, хороший) есть в Турбо-Паскале, интерфейсы (вот тут надо уточнить, какие именно имеются в виду) есть в Дельфи.
UFO just landed and posted this here
Особенно когда ВНЕЗАПНО окажется, что в Паскале тоже есть указатели и динамическое выделение памяти

Это значит, что ими можно пользоваться.
А вот строки в Паскале «из коробки» — бесценно при обучении, в сравнении с костылем Си.
Вы даже представить не можете мой восторг, когда я познал отсутствие секции var и ключевых begin и end. Это было первое знакомство с «С».
Но этот восторг умирает на корню после первого же чужого проекта или библиотеки на C++, которые вы пытаетесь скачать и собрать. Главный плюс Pascal и сред на его основе — отсутствие проблем со сборкой.
Сборка C++ это ад. Нет, это хуже любого ада. Оно настолько негуманоидно, что можно потратить недели, разбираясь, почему же проект отказывается собираться. Вы переберёте все возможные ключи линкера и компилятора, а заодно по 5-6 версий каждого. Вы будете сутками напролёт изучать include-файлы, выясняя, где там что конфликтует или отсутствует. Вы заодно освоите Perl, Python, bash и синтаксис makefile, т.к. половина проектов при сборке умудряется юзать их все одновременно.
И, конечно, каждая неудачная итерация сборки будет отнимать несколько часов (в лучшем случае) времени. Такое ощущение, что всё это специально придумывали, чтоб проект не мог собрать никто кроме создателя.
А в Delphi красота: F9, и всё тут же работает. Даже очень крупные проекты больше 10 сек. не собираются, а простенькие программки до 20к строк вообще стартуют мгновенно.
Прямо сейчас иду ставить Borland Delphi 7 на свой headless-сервер с FreeBSD и заодно на рабочую станцию с Debian GNU/Linux.
Вполне можно собирать и make'ом, вот насчет nix — другой вопрос.
Грамотно настроенный для сборки проект на C++ собирается как нибудь типа cmake [path] && make
Видимо вы никогда не сталкивались с тем чтобы ваш код работал под delphi и free pascal/lazarus, под windows и linux, под intel и ARM. Поверьте, сложность сборки, работы с include/define, борьба с версиями fpc, легко дорастает до сложности сборки C++.
UFO just landed and posted this here
begin/end — вкусовщина — меня, например, тошнит от фигурных скобок в Си, но я не выпячиваю это как «недостаток».

Что плохого в секции var? Во всех старых языках переменные объявляются в начале процедуры, до использования. Говорить о том, что «если выделять ближе к месту использования, то нагляднее» не приходится — хорошим тоном считается там, где это возможно, сокращение размера процедур, так что секция var все равно перед глазами.
А еще он практически мертв

Именно поэтому Embarcadero регулярно выпускает новый Delphi. Потому что он мертв.
UFO just landed and posted this here
Отнюдь.
Вам никто не запрещает взять современный Дельфи и написать консольное приложение без ООП. Нет принуждения к парадигме — хочешь, используй наглядное процедурное, хочешь — ООП, хочешь — смешивай.
Передавать массив в си в качестве аргумента методу (или как там он называется) — очень не просто
Куда уж проще Си-то?

Для обучения — Паскаль, например.
Я, когда только начинал учиться, начал с С++. В процессе изучения, разумеется, реализовывал стандартные темплейты, затем, на их базе, изучал паттерны и проч… Конечно, мои библиотечки с STL не сравнятся, но работали не плохо )
Хорошая школа — С, С++ и т.д., автор прав.
Сейчас пишу на C# и весьма этим доволен.
А мне посоветовали свифт покурить, в качестве заместительной терапии после php. Вот, весь в раздумиях нахожусь.
Вообще из разных плоскостей языки. Покурите лучше руби с рельсами, или питон с джангой/фляком коль занимаетесь web-разработкой.
Так вроде это тот же ObjC с своими приколами для Mac-dev.
upd: А, понял, вы про назначение языков. Да как раз и хотелось бы поробовать что-то отличное от веба. Посоветовали свифт, так как он, сишарп, джава: «отвечает тенденциям разработки в настоящее время».
Покурите, почему нет? Но я бы для изучения чего-то нового взял уже более-менее развитый, устоявшийся язык, с большим количеством библиотек. Ничто так не раздражает в молодых языках, как необходимость писать свои библиотеки: бывает, нужно решить относительно небольшую задачу, которуая на какой-нибудь Java решается за час, а у тебя уходит день или два, потому что никто ещё не написал клиент HTTP, библиотеку регулярок или ещё что-нибудь.
Ну, я почему его тут упомянул, это же модифицированный ObjC с обратной поддержкой, так что в крайнем случае можно использоватьбиблиотеки родителя :)
с использованием библиотек Objective C там, мягко говоря, проблемы. А еще мой код на нем примерно раз в 1-2 месяца перестает компилиться из-за очередных изменений синтаксиса…
зря, слишком гибкий язык для обучения, лучше Java/C# изучайте
Покурите, покурите! Сейчас он в моду войдет — будет вам и работа, и документация и библиотеки. К тому же, система типов там прямо таки вытащена из Хаскелля ну и много других плюшек есть которые тщательно скрыты чтобы не пугать новичков. Освоите — потом в других нормальных языках легче будет.
Стоит так же заметить, что сам я не сварщик и свифт видел пару раз краем глаза у коллеги на компьютере, но этих пары раз мне хватило чтобы впечатлиться.
Призывы что-то изучать — это хорошо, но не отменяет того факта, что статья крайне слабая.

По перечисленным признакам «семейства Си» (фигурные скобочки, статическая типизация, ООП) отвергнутая с порога Scala подходит больше, чем глава семейства :)

Зная C# легче разобраться с Java? И все потому, что оба этих языка принадлежат с «семейству Си»? А не потому ли, что они созданы для решения схожих задач и в них заложены одни и те же парадигмы? Кстати, зная C#/Java легко разобраться и в Python, и в JavaScript, а вот насчет сходу разобраться в C/C++ я совсем не уверен.

Вибираем язык по рейтингам? Ну так рейтинги надо смотреть в динамике. По графикам TIOBE видно, что многолетний тренд для языков «семейства Си» — на спад. Может наоборот стоит посмотреть на не так широко используемые в настоящее время языки, чья популярность стремительно растет?
Абсолютно не согласен с высказыванием о том, что знание си-подобного языка помогает перейти к новой парадигме, особенно к функциональной — для этого требуется совершенно иной способ мышления, который никак не поощряется императивными языки вроде си.
Ни C#, ни Java не являются языками «Семейства С» никаким боком. То, что синтаксис похож — так он и у Perl и PHP похож.
«В качестве очень грубого определения можно сказать, что язык относится к семейству С, если в нём для выделения функциональных блоков используются фигурные скобки {}.» Гениальное определение.

С отличается от других языков тем, что имеет дело с физическими объектами. Целое число — это процессорное целое, строка — это байты. В C# и Java (и в некоторых других перечисленных) это объекты. C ценен тем, что позволяет программировать в терминах процессора, и опыт программирования на С позволяет, например, оценить затраты на упрощения, доступные в других языках.

«Если вы освоите один из языков семейства С, то это даст вам понимание фундаментальных основ программирования: переменных, значений, типов, присваивания, выражений, функций, параметров, возвращаемых значений, потока команд и т.д.» — всё это можно узнать из других языков. Но только C позволит понять, что такое на самом деле функция, что такое тип и что за ним лежит, как устроены параметры и передаваемые значения.

Ну и напоследок — между С и Java общего нет практически ничего. Кроме скобок.
UFO just landed and posted this here
Мне например Питон очень симпатичен на стерильных примерах из учебников, но когда я вижу образцы реального кода современных фреймворков и всего такого — он отторгается. Отвратительно, мусорно, нечитаемо и так далее. Я не понимаю эту кашу.
Хм, впервые вижу такой негативный отзыв об языке, который из кожи вон лезет, чтобы быть простым и читабельным.

Может быть вас смутило отсутствие типов?
Нет, именно визуально — каша.
Я не могу читать вот такое, мне скобки нужны! И операторные, и в логическом выражении.
if self.request.cookies is not None and name in self.request.cookies:
    return self.request.cookies[name].value

Раздражает обильное использование символа подчеркивания (кэмел мне милее).
Невероятно бесит манера комментировать функцию (строк на 10-15!) внутри её тела, а не перед.
Куцое словечко def теряется и замыливается — то ли дело человеческая function.

Я бы сказал, что Питон изо всех сил стремится к краткости, но краткость != удобочитаемость. Если из русского текста убрать все знаки препинания — получится короче, но совершенно нечитаемо. Кстати, примерно тем же, но в ещё более адской форме занимается CoffeeScript — там просто тихий ужас :)
(В питоне есть скобочки, но (если они не нужны), они опускаются) и читать становится проще
То что скобки есть в самом языке (естественно, они там есть!) мало что дает, потому что в питоновой практике их принято опускать везде, где можно. То есть имеется стандарт де-факто.
Идти против шерсти и в своих файлах ставить их везде? Глупо. И сам в сообщество не интегрируешься (чужой-то код читать все равно надо), и оно тебя отторгнет.
мне скобки нужны!
Логические — сколько угодно. А операторные? Я вот заколебался писать паскалевские BEGIN-END при писанине процедур T-SQL. Если бы можно было обойтись отступами — код бы сократился на четверть точно. Про читаемость просто молчу.

кэмел мне милее
а андерскор читаемее. Ну_правда_ведь. НеТакЛи?

def теряется
Выберите себе подходящую цветовую тему в IDE. Что? В блокноте как? Ну, скажем, Вирт в Обероне сделал обязательным верхний регистр в операторах — чтобы ч/б листинги были читаемее.
begin-end это было в прошлом веке. Сегодня как-то более распространены {}

Андерскор не читаемее, потому что:
а) Когда его много, рябит в глазах в целом.
б) Он сильно «интерферирует» со знаком равенства (ну то есть присваиванием).
в) Хуже читаемость цепочек объектов/методов. Случайный пример из Flask:
 _request_ctx_stack.top._after_request_functions.append(f)
Подчеркивание создает визуально бОльшую дырку, чем точка, поэтому в такой строке stack.top или functions.append сливается в одно слово, а на _ расспается на сегменты. Получается наизнанку.

Как установить свою цветовую схему на гитхабе?
не читаемее
Но, по-моему, всё-таки, всё субъективно, ко всему привыкаешь. Опять-таки, Гвидо не придет к вам с топором, если вы будете использовать camelCase (наверное). Впрочем, к использованию Python, если подчеркивания так уж рябят, также никто не принуждает.

(Занудство: люди на ассемблере пишут, и ничего у них не рябит. Про Лисп с его тучей скобок вообще молчу. А всё почему? Потому что цветовая схема правильная.)

Как установить свою цветовую схему на гитхабе?
Можно как-нибудь так. Может, есть способ и поприличнее.
ну, я сконвертировал ваш пример: requestCtxStack.top.afterRequestFunctions.append(f)
легче стал читаться?)
Конечно. Сразу иерархия видна.
Куцое словечко def теряется и замыливается — то ли дело человеческая function.
Подсветка синтаксиса вас спасёт. В некоторых языках вообще нет ключевого слова для обозначения функции — люди пользуются.

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

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

if self.request.cookies is None:
    return default
return self.request.cookies.get(name, default)


Три строки вместо одной, но читабельнее.
Вообще в Python много мест, которые можно записать очень просто, но в силу незнакомства программистов со стандартной библиотекой код часто выглядит сложнее. Пример из Python Cookbook:

d = {}
for key, value in pairs:
    if key not in d:
        d[key] = []
    d[key].append(value)

С использованием defaultdict:
d = defaultdict(list)
for key, value in pairs:
    d[key].append(value)
snake_case смотрится нормально в языках, где не используются очень сложные и ветвистые объектные модели. C/C++ как раз такой.
А если в языке цепочки из 3-5 свойств/методов является нормой (JS, С#, Java, VB) — там сразу подчеркивания лучше свести к минимуму.
UFO just landed and posted this here
Мне кажется для обучения нужно что-то нетипизированное, без контроля за памятью типа PHP или Python. И их проще применить на практике — типа сайтик свой склепать. А там где практика там и интерес к дальнейшему развитию в этом направлении. К Си сложнее привить интерес у обучающихся, как мне кажется.

З.Ы. Сам начинал с Паскаля и Си.
Python — сильно типизированный язык, а C и PHP — слабо типизированные.

Python и PHP — языки с автоматическим контролем любой памяти, а C — с ручным контролем для динамически выделяемой.

Основная разница между Python и PHP с одной стороны и C с другой — первые интерпретируемые с динамической типизацией, а последний — компилируемый со статической.
Слышал выражение «Си-образные языки», где главный упор на сходстве скобочек, основных конструкций контроля потока выполнения, вычисления выражений. Кроме упомянутых к ним однозначно относятся Javascript и PHP.
Несмотря на то, что я сам довольно много пишу на C и на языках с унаследованным синтаксисом, полагаю, что для первоначального обучения этот язык подходит плохо. Попробую объяснить причины. Ещё раз обращу внимание, что речь идёт о первоначальном обучении. Для профессиональных программистов требования будут совсем другие. И им определённо стоило бы выучить C хотя бы для общего развития.

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

1. Глубокое знание архитектуры компьютера на этом этапе будет только отвлекать. Первый курс какого-то естественного языка начинается с алфавита, а не с изучения культуры страны. Тут цель — научить сказать сперва хоть что-то, а не сразу стать Шекспиром/Шиллером/ещё кем-то. В C есть указатели, которые могут запутать новичка. Для их понимания нужно знать, что да как располагается в памяти компьютера, а это отвлекает от алгоритмов. Да, это важные знания, но должны ли они быть первыми важными знаниями, которые изучит человек? Как мне кажется, нужно брать более высокоуровневый язык. Пример более подходящего языка: Pascal (высокоуровневое программирование, но при желании можно и указателями воспользоваться).

2. Без указателей и выделения памяти в C не поработаешь толком с массивами. Одно неверное движение и программа работает не так, как надо. Как нет и сложных структур данных в стандартной библиотеке, таких, как словари, списки и так далее. Даже строк как отдельного типа в C нет. Порог вхождения новичка в структуры данных значительно повышается: вместо изучения того, как их применять, ему придётся сидеть с карандашом и аккуратно рисовать стрелочки-указатели. Это, безусловно, полезно, но изучить внутреннюю организацию структур данных можно и потом, когда уже понимаешь, что это, для чего нужно и какие требования к структуре предъявляются на практике. Пример более подходящего языка: Python (списки, словари, строки — естественная часть синтаксиса).

3. Если выбрать достаточно сложный или запутанный язык, то его синтаксис будет только отвлекать. Я помню, когда я учился в школе, у меня первое время не было учебников по C и Pascal, но я брал в библиотеке книги, в которых были программы на этих языках. Так вот, программы на Pascal я понимал не зная языка, а программы на C были для меня набором закорючек, пока я не выучил язык (довольно быстро, справедливости ради). В C есть ещё такая штука как undefined behavior. Да даже конкурс есть по непонятному программированию на C. Профессионалы опасные места знают и обходят уже подсознательно, новички — нет. Поэтому желательно, чтобы синтаксис языка не был двусмысленным. В идеале он вообще должен быть незаметен и минимизирован, чтобы рассказать один раз о нём и не возвращаться больше. Пример более подходящего языка: Scheme (из синтаксиса только скобочки, но тем не менее, в SICP эти скобочки довольно сложные вещи делают).

4. Важный момент при обучении программированию — наличие учебной литературы подходящего уровня. На постсоветском пространстве в школах был популярен Pascal (хорошо это или плохо обсуждать не будем), поэтому в книжках по решению олимпиадных задач фигурирует чаще всего именно он. Не то, чтобы авторы всегда были этому рады: то, что в другом языке делалось бы одной строкой, в нём иногда занимает несколько. Например, обращение порядка элементов массива. Или создание списка. Но если, скажем, школьник готовиться к олимпиаде, то Pascal он должен знать. Есть неплохая книжка у Вирта «Алгоритмы и структуры данных», в которых на пальцах про эти самые структуры данных и алгоритмы рассказывается. Это, конечно не Кормен и др. по уровню, но и целевая аудитория у неё другая. К слову, у Кормена псевдокод используется, а Кнут вообще взял ассемблер для несуществующей машины. Книжки про алгоритмы или олимпиадные задачи с примерами на C, конечно, есть. Но они обычно рассчитаны на человека, уже знакомого с программированием.

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

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

Буду рад конструктивным возражениям. Давайте вместе попробуем сформулировать цели первого курса программирования.
Так вот, программы на Pascal я понимал не зная языка, а программы на C были для меня набором закорючек, пока я не выучил язык (довольно быстро, справедливости ради). В C есть ещё такая штука как undefined behavior.
В pascal вся работа с динамическими массивами — undefined behaviour. Только интерфейсами можно нормально пользоваться, но они с подсчётом ссылок. Как научить начинающего разруливать циклические ссылки? Для этого надо объяснять правила работы с указателями, правила организации древовидных структур и прочее. В результате уровень сложности начинает превышать сложность использования умных указателей в C++. Поэтому pascal не может быть языком начального уровня.
Для начального уровня нужно что-то со сборщиком мусора, отсутствием необходимости работы с указателями и нетребовательное к изучению 100500 сложных правил использования.
Лучше python или javascript, но javascript можно даже не учить специально — он в любом случае понадобится.
Java не подходит. В Java начинающий легко пишет:
protected Boolean active;
synchronized(active) {
}

Pascal же стоит, как и basic ранее, объявить языком, калечащим молодые умы.
Только сейчас заметил этот ответ.

Я вовсе не агитирую за Паскаль. Я наоборот, пытался показать, что серебряной пули нет (хоть многие комментаторы со мной и не согласятся). В приведённых мной примерах в зависимости от критериев отбора три разных языка побеждало. А примеров можно придумать и больше. Нет просто «обучения программированию». Каждый понимает это по-своему. Кто-то считает, что нужно начинать с языка ассемблера, чтобы понимать, как работает компьютер. А кто-то начинает с принципов ООП, чтобы человек сперва научился разбираться в задаче. У каждого найдётся масса хороших аргументов.
В pascal вся работа с динамическими массивами — undefined behaviour.

В чем это выражается? Именно UB.
В зависимости от версии работают или работают частично деструкторы записей/объектов старого типа в динамических массивах. Особенно плохо с вложенными динамическими массивами. В результате в динамических массивах лучше хранить только примитивы а лучше не использовать вообще. В зависимости от версии инициализируется или нет результат функции если он динамический массив.

Вы конечно скажете, что в версии N это исправлено. Охотно верю, но поверьте, я работал с delphi, tp/bp, free pascal/lazarus win/lin/dos x86(16/32/64)/ARM и помимо проблем переходящих из версии в версию, практически каждая версия добавляла свои.

Конечно же, я сталкивался и с багами компиляторов asm/C/C++/Java, но пальму первенства безоговорочно отдаю pascal. Ну нельзя считать pascal хорошим языком в вакууме в отрыве от его плохих компиляторов/ide. Да хотя бы посмотрите на код крупных, поддерживающих много версий компиляторов библиотек или посмотрите на код системных библиотек fpc, сравните с кодом схожих библиотек на других языках и скажите, готовы ли вы тратить на копание в этом своё время?
работают или работают частично деструкторы записей/объектов старого типа в динамических массивах. Особенно плохо с вложенными динамическими массивами

Не думаю, что это UB, это скорее именно ошибка компилятора.
«Старого типа» — это что имеется в виду? Конкретный пример кода можно? Я не поспорить, просто интересно — у нас продукт пишется полностью на Delphi, вдруг действительно интересный баг, который надо знать.

Да хотя бы посмотрите на код крупных, поддерживающих много версий компиляторов библиотек или посмотрите на код системных библиотек fpc, сравните с кодом схожих библиотек на других языках и скажите, готовы ли вы тратить на копание в этом своё время?

Если сравнить, скажем, RTL Delphi в части стандартных контейнеров и STL, то я «еще подумаю», какой код приятнее.
«Старого типа» — это что имеется в виду?

Насколько я помню, есть value-type классы типа object и reference-type классы типа class
В каком из диалектов?
Sign up to leave a comment.