Pull to refresh

Comments 234

Знаете, почему нельзя ни C, ни C++ первым языком изучать?

#include <iostream>

int main(int argc, char**argv)
{
    cout << "Hello world!\n";
    return 0;
}


Так вот, в первой же программе у нас #include, типы (int), указатель на указатель(char**), потоки ввода/вывода, перегруженный оператор <<, символ перевода строки, возвращаемое из программы значение. Каждая из этих штук не является очевидной и требует 1-5 часов на объяснение. Напомню, это первая программа, которую мы показываем неподготовленной аудитории.
Не надо передергивать. Убрать параметры функции main, заменить int на void и убрать return — и всё уже совсем не страшно. А детали объяснить со временем — нельзя и не нужно объять необъятное на первом же занятии.

И, кстати, добавить using namespace std;, а то то, что вы написали, не заработает.
Убрать параметры функции main, заменить int на void и убрать return — и всё уже совсем не страшно.
И поймать предупреждения компилятора. Отличный план, показывать некорректную программу на первом же занятии. А #include вы тоже уберёте? И cout? И \n? Или сразу объясните, что есть препроцессор, который может включать заголовочные файлы, про которые надо тоже рассказать. Итого чтобы просто перейти к объяснению второй строки программы вам понадобится минимум два часа учебного времени, в ходе которого больше половины студентов крепко уснёт.
Ну или «это мы вам потом объясним», или на пальцах объяснять неправильно. В итоге получится не лекция, а чёрт знает что.

Сравните это с паскалевским или бейсиковским хэлловордом на одну строку.
Во-первых, какой это компилятор выдаст предупреждение? Visual C++ никаких предупреждений не выдаст.

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

И в-третьих, уснут или нет зависит от того, как объяснять. У меня вот не засыпают.

Поверьте мне, я 11 лет преподаю, и начинаем мы как раз с С++. И мои выпускники сейчас работают и тимлидами, и синьёрами во многих компаниях. Кто-то специализируется на С++, кто-то на стеке .NET, кто-то на Java. Главное — это продумать и правильно организовать весь процесс обучения. И тогда можно начинать и с С++ — всё будет хорошо.
gcc и clang генерируют ошибку для случая «void main». Стандарт гарантирует только 2 обязательные формы:
int main() { /* ... */ }
int main(int argc, char* argv[]) { /* ... */ }

Всё остальное — это особенности конкретного компилятора. А вот return можно опустить, для main стандарт явно описывает, что, фактически, неявно будет подставлен «return 0».

Поэтому, пожалуйста, если Вы преподаёте C++, а не Microsoft® Visual C++®, то рассказывайте о «int main». Или хотя бы рассказывайте, что «void main» работает не всегда.
Я безусловно это рассказываю, но вот только не на первом занятии, а несколько месяцев спустя, когда мы уже прошли темы «Функции» и «Указатели» и они уже всё понимают про функции, про возвращаемое значение функции, про способы передачи параметров в функции и про массив указателей вообще и массив указателей на строки в частности. А до этого (и в особенности на первом занятии) им более чем достаточно «void main».

Всему свое время. О чем и речь, когда разговор идет о грамотном выстраивании процесса обучения, а не о выпендривании давно уже состоявшихся и никогда в жизни не преподававших профессиональных программистов, уверенно заявляющих, что начинать с С++ нельзя, но забывающих писать using namespace std;. (Это я не про вас, я надеюсь, вы понимаете.)
В таком случае — претензий не имею.
Если уж говорить про Си, то вот пример минимальной работающей программы:
main()
{
    printf("Hello world!\n");
}


Не понимаю, что здесь сложного или непонятного. А потом уже можно ввести понятия типов данных, инклудов и т.д.
Оба варианта получат предупреждение о неявном определении функции. Ваше счастье, что такое определение вообще корректно; и то оно корректно только из‐за того, что обе функции возвращают int:
(zyx-desktop:zyx:~) 1 % echo $'main(){puts("Hello word!");}' | clang -x c -
<stdin>:1:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main(){puts("Hello word!");}
^~~~
<stdin>:1:8: warning: implicit declaration of function 'puts' is invalid in C99 [-Wimplicit-function-declaration]
main(){puts("Hello word!");}
       ^
2 warnings generated.
(zyx-desktop:zyx:~) 1 % echo $'main(){puts("Hello word!");}' | gcc -x c -Wall -
<stdin>:1:1: предупреждение: по умолчанию возвращаемый тип функции - «int» [-Wreturn-type]
<stdin>: В функции «main»:                                                                                                                                                                                                                     
<stdin>:1:1: предупреждение: неявная декларация функции «puts» [-Wimplicit-function-declaration]                                                                                                                                               
<stdin>:1:1: предупреждение: control reaches end of non-void function [-Wreturn-type]
Кстати, видите первое предупреждение? Функция без возвращаемого типа должна возвращать int. А что возвращаете вы? Я не думаю, что приводить в качестве первого примера не корректную программу — хорошая идея.

Если компилировать как C++ (я помню, что EuroElessar сказал «Если уж говорить про Си») будут тоже две, но ошибки:
(zyx-desktop:zyx:~) 1 % echo $'main(){puts("Hello word!");}' | clang -x c++ -
<stdin>:1:1: error: C++ requires a type specifier for all declarations
main(){puts("Hello word!");}
^~~~
<stdin>:1:8: error: use of undeclared identifier 'puts'
main(){puts("Hello word!");}
       ^
2 errors generated.
(zyx-desktop:zyx:~) 1 % echo $'main(){puts("Hello word!");}' | gcc -x c++ -
<stdin>: В функции «int main()»:
<stdin>:1:26: ошибка: нет декларации «puts» в этой области видимости
На этот раз gcc не молчит даже без -Wall.
Разумеется :)

Но я бы не сказал, что это «наше счастье» — выбор на printf/puts пал вполне осознанно в виду его возвращаемого значения.
Тут вроде можно спокойно всё пояснить. А перегруженный оператор намекает на действие.

#include <iostream>

// C++ 11
int main()
{
std::cout << «Hello» << std::endl;
}
Можно личный вопрос?

У меня тут в одном этюде на XE5
ofstrCfg << cbxLeft1When->ItemIndex << std::endl;
[bcc32 Error] Main.cpp(2727): E2335 Overloaded 'endl' ambiguous in this context


Вы мне можете посоветовать как расследовать такой тупняк? Как у меня вышло, что endl перегрузился?

Я просто пытаюсь портировать этот этюд с Turbo C++ Explorer на XE5, а в TC проект собирался без единого предупреждения.

Спасибо!
include можно убрать, да ;-)

extern _cdecl int printf(const char *, ...);

:-D
Заменили один include на extern, конвенции вызова и const. Отличный план.
Вот и я о том же.

Я, наверное, сужу по себе, но идеальным стартом был бы Donald Alcock «Illustrating Pascal» на турбопаскакале.
(Щас глянул — можно Pascal.ABC вкрячить, причём легально).

Затем уже я бы предложил K&R и Ceebot4. Параллельно SQL.

После чего уже C++/C#/Java/ObjC по вкусу в разных комбинациях.

Хотя у меня тут выпадают языки с другими парадигмами, с которыми я, к сожалению, не знаком (кроме Turbo Prolog).
нельзя и не нужно объять необъятное на первом же занятии.
На первом занятии не должно быть необъятного. Студент должен чётко понимать, что делает каждая строка, и какие последствия она несёт. Иначе это не обучение программированию, а курсы заклинателей компьютера.
Не должен он вам ничего, тем более на первом занятии. Он должен научиться системному мышлению, а это долгий процесс. Человека, который столь категорично предполагает, что либо всё сразу понял, либо это заклинания, нельзя подпускать к процессу обучения, уж извините.
Да не будет он сразу всё понимать. Приближённо можно объяснить каждую строчку, а потом по мере курса раскрывать подробнее и корректнее.
Несогласные помнят как они учили языки? Я — помню. Первый — BASIC, потом частично ассамблер/машинные коды, Pascal, потом Си и только после — C++. И изучение шло в основном по примерам, которые часто не работали из-за разных версий (инета тогда не было), и методом тыка. Так вот, понимание идёт не сразу и всего. Потом поступил в университет, и там ещё новое узнавал. И после университета ещё много нового узнавал. И речь о C++, не о программировании вцелом. Для начала, будет мантра, с примерным объяснением, а детали раскрываются значительно позднее. Так изучаются любые предметы.

Да, на простейшей программе тот же Pascal проще, только begin/end и всё. Но чуть больше — и получаем почти то же самое. Чем uses проще #include? Лично мне казался проще именно #include своей наглядностью — вот include, а вот файл, там всё написано, можно открыть, посмотреть какие функции.
Другая проблема. Если набрать < вместо <<, то программа компилируется, но не будет работать. А вот если перепутать и набрать cin вместо cout, то в неподготовленного обучаемого g++ плюёт почти 8 килобайт ошибок.

Как раз в Turbo Pascal был накрутейший error handling. Подсвечивается строчка кода, туда ставится курсор, сообщение об ошибке почти всегда простое и понятное. Меньше возможность сделать опечатку и чтобы программа при этом продолжала компилироваться или делать вид, что работает.

Еще момент. В Turbo Pascal по умолчанию был режим проверки на выходы за границы массивов. В C++ же наверняка a[10], а потом 1-индексация от 1..10 не будут приводить к падению программы. У обучаемых, конечно, будет мнение: работает, значит правильно, значит ошибки нет. Да, а в TP7 программа бы аварийно остановилась с подсветкой нужной строки кода и сообщением, что в ней произошел выход за границы.
Тогда Java в руки и вперёд! Современно + грамотная подсветка ошибок + достаточно жёсткий контроль за многими вещами (в частности — индексами).
Вам перечислить количество совершенно лишних для первой программы сущностей, содержащихся в хелловорде на Java, или сами посмотрите?
Даже любопытно, а какой ваш вариант?
Я бы предложил scala. Если запускать через scala HelloWorld.scala, то минимальный пример будет выглядеть так:

println("Hello world!")
Думаю с Scala можно быстро начать, однако дальше можно упереться на некоторые сложности.
Например?

Если не лезть целенаправленно в дебри до сложностей можно и не добраться.

Написано же выше - Pascal, есть pascal.ABC

Смотря с какой точки зрения смотреть. Если с точки зрения чистого программирования — да, Java избыточно. А если исходить из последующего использования Java как инструмента — в самый раз: только простейшие базовые сущности.
Для начала нет необходимости объяснять всё подробно. Люди просто не обладают достаточными знаниями для того, чтобы начать бросаться перед ними фразами вроде «std::cout — это экземпляр класса ostream, представляющий собой стандартный буферизированный выходной поток, по умолчанию связанный с дисплеем консоли». Насчёт include все должно быть понятно сразу. Обычно до того, как показать программу есть некоторая вводная лекция, на которой затрагивают этапы сборки, в том числе и препроцессинг. Уже через месяц всё (за исключением глубокого понимания потоков) будет понятно, если не после двух лекций. Зависит от уровня аудитории на самом деле. Многие приходят из школы с пониманием что такое функция, например.
забыли пространства имён: «std::cout», так что всё ещё хуже.
Я недавно стал снова студентом, на этот раз забугорном вузе, на вводном занятии нас воодушевили фразой —

«Studying is hard, it must be hard. And if you don't feel it's hard — than we (институт) are doing something wrong!»

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

А с этой точки зрения C++ подойдет лучше.
В геймерской среде есть такое понятие, как «хардкор».
И хардкорные игры — это не непонятное/кривое/неотзывчивое управление, не ошибки из-за лагов/глюков/багов игры, не борьба с игровым движком, не регулярные проигрыши из-за полного отсутствия баланса или логики.
Хардкорные игры — это когда игра тяжелая из-за того, что для ее прохождения просто необходимо наращивать опыт, скилл, знания.

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

Одно делать быть сложным, а другое не понимать вообще

Я просто предствил C# или Java static public void main(String args[])
UFO just landed and posted this here
Честное ООП, ага. class Mega: private Super, publlc Ultra, virtual publlc Gammma;
Вы еще вспомните отсутствие системы обьект-сообщение для обьекта )))
Для того чтобы выбрать C++ в качестве первого языка программирования существует четыре причины:

4. STL.
И начать с красно-чёрных деревьев, да.
Стоит отметить такой важный момент, как не принудительное ООП. То есть данный подход к программированию применяется тогда, когда это удобно, и его можно смешивать, например, с функциональным программированием.

В плюсах появилось функциональное программирование? А можно и мне его отсыпать?

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

В С и C++ нет строк как таковых. Есть указатель на char'ы. Char — не символ (потому, что юникод). Указатель на первый из них — не строка.

И вообще, изучать типы на языке со слабой типизацией — то ещё извращение.

Нет, C++ — вполне себе выбор языка под определённые задачи, но это — наверно, самый сложный из используемых сейчас языков. Смысл начинать с него?
В плюсах появилось функциональное программирование?

Метапрограммирование на шаблонах — чистой воды функциональщина.

Char — не символ (потому, что юникод).

На этот случай есть wchar_t, который вполне себе юникод.

Указатель на первый из них — не строка.

Имеется std::string, std::wstring, по мне, так они вполне себе строки.

Смысл начинать с него?

Я начинал с C/C++, и мне кажется, что это наиболее правильный путь к обучению. Во время обучения программированию должно быть по минимуму черных ящиков, чтобы ученик/студент понимал принцип работы, почему и зачем все происходит.
Разумеется не нужно вываливать на обучающихся все сразу, но если давать это правильными порциями, то будет конфетка.
> На этот случай есть wchar_t, который вполне себе юникод.

Нет, wchar_t — legacy, которое часто путают с юникодом.
«The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compiler should not use wchar_t for storing Unicode text. The wchar_t type is intended for storing compiler-defined wide characters, which may be Unicode characters in some compilers.»

>Я начинал с C/C++

Это — два совершенно разных языка. С на порядки проще.

> Метапрограммирование на шаблонах — чистой воды функциональщина.

Ну да, шаблоны в начале обучения программированию — прекрасная идея.
Нет, wchar_t — legacy, которое часто путают с юникодом.

Но при этом на современных системах — это, как правило, 2 или 4 байта. Для гарантии можно, конечно же, использовать char16_t или char32_t, которые гарантированно представляют из себя utf-16 и utf-32 соответственно.

Это — два совершенно разных языка. С на порядки проще.

Так никто и не заставляет окунаться во все дебри C++, вначале — Си, потом классы, потом уже шаблоны и т.д. В физике же тоже начинают не сразу с квантовой механики, но при этом курс все равно называется «физика».

Ну да, шаблоны в начале обучения программированию — прекрасная идея.

Использование функционального подхода в начале программирования — в принципе плохая идея. Его стоит давать только после обучения лямбда-исчислению.
>char16_t или char32_t, которые гарантированно представляют из себя utf-16 и utf-32 соответственно.

Эмм. Вы в курсе, что в UTF-16 все те же 1 112 064 символа (на данный момент), что и в UTF-32? Как char16_t поможет с этим?
Точно так же как и в любом другом языке/фреймворке (Java, C#, Qt, etc), в котором строки хранятся в 16-битном юникоде — появятся суррогатные пары.
В них есть веская причина использовать эти суррогатные пары. В новом софте — нет.

char16_t* не лучше, чем char* с utf-8. И в любом случае нам понадобится внешняя библиотека уже для базовой работы с этим. Я не уверен, что оно нужно в первом же языке.
В них есть веская причина использовать эти суррогатные пары.

Насколько мне известно, то этой причиной является потребление памяти. Если использование utf-16 еще осмысленно (т.к. большинство языков в utf-8 не помещается в 1 байт), то utf-32 уже является перебором. Мало кто захочет платить в 2 раза больше за тоже самое.
Все они начинали разрабатываться до массового перехода на UTF-32. Кроме .NET, но в windows везде utf-16, поэтому особых вариантов не было.
Метапрограммирование на шаблонах — чистой воды функциональщина.

Лолшто?
В плюсах появилось функциональное программирование? А можно и мне его отсыпать?

Начиная с C++11 появились встроенные лямбды, можно использовать замыкания, никто не мешает писать функции высшего порядка. Появились, например шаблоны с переменным числом параметров, кортежи, вывод типов… Всё это было и до стандарта C++11, правда в сторонних библиотеках.
UFO just landed and posted this here
Как перевернуть строку в С++
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include <errno.h>

int strrev(char *const target, const char *const source)
{
    const size_t  length = (source) ? strlen(source) : 0;
    size_t        offset = 0;
    size_t        have, nextlen;
    wctype_t      combining;
    mbstate_t     state;
    wchar_t       next;

    /* Invalid parameters? */
    if (!target)
        return errno = EINVAL;

    /* NULL or empty source string? */
    if (length < 1) {
        *target = '\0';
        return 0;
    }

    /* Get the combining character type. */
    combining = wctype("combining");

    /* Clear shift state. */
    memset(&state, 0, sizeof state);

    /* Length of the initial wide character. */
    nextlen = mbrtowc(&next, source, length, &state);
    if (nextlen < 1 || nextlen > length)
        return errno = EILSEQ;

    /* Character loop. */
    while (offset < length) {

        /* Take the next character. */
        have = nextlen;

        /* Scan for the next character. */
        while (offset + have < length) {

            /* Convert next character (so we can find out its class) */
            nextlen = mbrtowc(&next, source + offset + have, length - offset - have, &state);
            if (nextlen < 1 || nextlen > length - offset - have)
                return errno = EILSEQ;

            /* Not a combining character? */
            if (!iswctype((wint_t)next, combining))
                break;

            /* Combining characters are grouped with the previous character. */
            have += nextlen;
        }

        /* Copy the wide character, including any combining characters that follow it. */
        memcpy(target + length - offset - have, source + offset, have);
        offset += have;
    }

    /* Terminate target. */
    target[length] = '\0';

    return 0;
}

Работает только в линуксах. Советую попытаться портировать на windows (да, этот код там не работает) или FreeBSD.

Чему из этого учат на «Операционных системах» или «Основах теории информации»?
Можно поступить проще:

std::string s("foo");
std::reverse(begin(s), end(s));
Вы в курсе, что будет, если, например, s это строка в UTF-8?
Вы в курсе, что добавили в C++11? Вот, почитайте. Всё работает, даже если строка в юникоде, правда с небольшим дополнением (u8"").
Не работает же. Нужно, во-первых, std::u32string (c++11 не настолько умён, чтобы обращать utf8-строки сам), а, во-вторых, обрабатывать комбинирующие символы (поскольку, опять же, c++11 обзывает символом юникодный codepoint, а люди — нет).
Я в курсе про литералы, только они здесь не при чём и никак не помогут. Вот эта программа:

#include <string>
#include <algorithm>
#include <iostream>

int main() {
    std::string s("фыва");
    std::cout << s << std::endl;
    std::reverse(std::begin(s), std::end(s));
    std::cout << s << std::endl;
}


Выводит
фыва
°вЋфÑ

даже если заменить литерал на u8.
Верно, вы правы. С начала, не совсем понял что вы имели ввиду.
Но всегда же ведь можно использовать сторонние библиотеки. Для примера, проверил с QString, строка поворачивается нормально. Думаю, что есть и более маленькие библиотеки или другие способы поворота. Сам я работаю с Qt.
Да, можно. Собственно, 3al привёл код, судя по всему, из какой-то стандартной сишной библиотеки. А QString внутри юникодовая, содержит 16-битные символы с суррогатными парами.
Но обучать на основе Qt… Почему бы тогда сразу не взять что-то более высокоуровневое, чем C++?
Попробуйте сделать так со строкой foo x⃣ o⃝⃔ bar. Если получится не «rab o⃝⃔ x⃣ oof», то этот «простой» вариант не работает.
Специально проверил. Всё работает под виндой и линуксом. Ссылка на вики с C++11 выше.
UFO just landed and posted this here
По моему скромному имху, начинать нужно либо с какого-нибудь питона, чтобы начать мыслить абстракциями, не думая о железе.
Либо с Си — чтобы понять железо. Си — кристально чистый язык, в котором всегда понятно, что происходит (особенно если динамическую память не трогать).
А ЦПП где-то по середине болтается, ни нашим ни вашим. То есть, как про язык разработки ничего про него говорить не буду, но для обучения что-то он мне не нравится.
Согласен на все 100%. Либо Python либо Си. Добавлю пару копеек в чашу Си, хоть сам и являюсь адептом Питона: как мне кажется научиться на низком уровне Си и после перейти выше на Python проще. Тем паче, что базовая версия, CPython — напсана как раз на Cи.
Это что-то типа естественный отбор? Синтаксис может и выучат, а вот писать грамотно — нет.
Для первого раза подойдёт любой язык со статической строгой типизацией — как я заметил, когда люди только начинают изучать программирование, такие языки меньше взрывают мозг, вот это всё.
>со статической строгой типизацией

В смысле выбирать из Java, Haskel и Ocaml?
Standard ML отлично подходит для первого языка. Есть REPL, нету классов и пакетов полный вывод типов — не нужно задумываться, что такое generic'и, immutability и ещё куча преимуществ.
Вспоминается небольшая статья «Язык Си и начальное обучение программированию» — А. В. Столяров.
Я находил только в виде PDF файла.

Если вкратце, автор сильно против и дальше по тексту поясняет почему.
Автор читает лекции на ВМК, поэтому имел удовольствие наблюдать его в деле. Весьма эксцентричный товарищ, с налетом фанатизма, любовью ко всему низкоуровневому и показной ненавистью к майкрософту. Но с другой стороны — ценнейший источник знаний, может рассказать массу нюансов и неочевидных вещей, реально глубоко разбирается в теме. Его книжки(а их достаточно много, доступны на его сайте, в основном C/C++/UNIX/NASM) определенно стоит почитать, но все же при этом нужно критически относиться к некоторым излишне категоричным заявлениям.
рассмотрим процесс выбора первого языка исключительно для студентов профильных специальностей
наличие заинтересованности и определённого склада ума у студентов. Такие студенты чаще всего уже пробовали программировать, а возможно даже и написали сайт/игрушку.
По своему опыту учёбы в ВУЗе хочу заметить, что та категория студентов (их меньшинство), которая ещё до прихода в ВУЗ плотно сидит на различных… языках и олицетворяет собой образ того, кого на западе называют Geek; судя по всему именно к ним изображён ваш посыл; так вот они всегда будут зевать на лекциях по любому языку программированию (у нас так и было) — им это всё уже известно, а что неизвестно — они сами быстро могут освоить в комфортной домашней обстановке, нежели слушать лекционное разжёвывание «для всех».

И есть другая категория студентов, гораздо более многочисленная, для которых программирование это лишь одна из сторон жизни и для которых учёба требует не только мыслительных усилий. Так вот для них вопрос заинтересованности действительно очень важен. Конечно, можно сходу врубить академический подход и начать нагружать студентов любыми знаниями, которые способствуют пониманию работы компьютера. Начать можно, например, с химии кремния.
Вот только отношение к учёбе у них будет… лишь бы сдать. Зачем добиваться этого и с самого начала прививать отношение к программированию как к чему-то необъятному и перегруженному всякими деталями?

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

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

Поэтому с с самого начала, с первых курсов, следует обучать студентов на примере чего-нибудь наглядного и очень низким порогом вхождения (да-да, я «за» много раз упомянутый Python; хотя можно подобрать и другие варианты), чтобы весь процесс обучения выстраивался от простого к сложному, а не от академического к практическому.

И даже если и всё-таки учить низкоуровневому (на старших курсах), то обучение на основе C++ это… кхм, отдельный сложный (и для многих болезненный) вопрос, требующий отдельного обсуждения. Всё-таки его чудовищная переусложнённость заставляет смотреть куда-то в сторону классической няшной сишечки. Или вообще D.
Скрытый текст
пользуясь случаем, хочу передать привет Андрею Александреску и Уолтеру Брайту, желаю им всяческих благ и процветаний.
Язык для первоначального обучения программированию (то есть когда студенты еще ни на чем никогда не программировали) должен иметь следующие свойства:
1) Не требовать установки софта вообще
2) Иметь минимум «базовых» сущностей и никакого public-static-void-main-overhead
3) Иметь динамическую типизацию и\или мощный авто вывод типов
4) Никакого менеджмента ресурсов
5) Быть практическим (то есть на нем можно писать реальные программы)

Идеально подходит JavaScript. C++ категорически не подходит по всем параметрам, C# и java тоже. Python — нормальный вариант.

Далее чему учить: никакого ООП в первые полгода-год, объекты — наборы «ключ»-«значение» и все. Нельзя давать ни классы, ни прототипы.
Обязательно функции, рекурсию, лямбды и замыкания. Алгоритмы на массивах, матрицах, деревьях, графах.

Уже потом можно грузить компиляцией, модульностью, ООП, управлением ресурсами. Лучше всего на C#.

А вот на третий год уже выносить мозг C++ с шаблонами. А также можно параллельным\асинхронными программированием.
Не стал бы для первоначального обучения рекомендовать языки с нестрогой типизацией =/
Преподавание математики идет от простого и идет к сложному. Сначала таблица умножения, а потом кольца и группы.

Излишняя сложность в начале убивает желание учиться. Типизация — дополнительная сложность и надо её избегать на начальном этапе.
Если вы хотите избежать типизации, то вам надо программировать на ассемблере. Во всех остальных языках (статических и динамических) есть типы. Должен же человек понимать, что такое int, а что такое string. В JS это как-то сильно неявно, к тому же нестрогость делает это понимание еще более размытым.
Зачем понимать что такое int и string? Достаточно понимать что в переменной x записано число, а в переменной y — строка.
Не забывайте что это первоначальное обучение, там надо минимизировать количество сущностей, которые надо держать в голове.

Типы вообще отдельная и сложная тема, которая при начальном обучении мешает. Любая попытка использовать статически типизированный язык натыкается на генерики\шаблоны при переходе к контейнерам. Я помню как у нас на первом курсе из 100 человек осилили array of record человек 10 всего. и это еще мягкий вариант обобщений.
Ну так большего понимания, чем «в переменной x записано число, а в переменной строка», и не надо. Типы — сложная тема, если речь идет о наследовании. Генерики/шаблоны можно сделать неявными, если преподавать язык с полным выводом типов (SML, например).
Полный вывод типов часто спотыкается, особенно на структурах.
На JS:
var x = [{x: 1, y:2}, {x:3, z:4}];
for(var i=0; i<x.length; i++) {
    console.log(x[i].x);
}


Код валидный. Теперь попробуй портировать его на язык с выводом типов. Какой тип будет у x?
Здесь проблема не с выводом типов, а с тем, что этот код вообще не валидный. В ML списки не гетерогенные: туда нельзя положить элементы разных типов (val list = [1, «a»] не скомпилируется). И это с одной стороны хорошо, с другой плохо. Все зависит от решаемой задачи и предпочтений программиста.
Во-во. Код вилидный, а в рамках строго типизированного языка не решается. И вывод типов не поможет.
Нормально решается. Сделайте тип данных с соответствующими конструкторами и пакуйте в список, что заблагорассудится. Не знаю, как это описать в SML, но на Haskell это будет выглядеть примерно так
data MyType = Int n | String s

myFilter :: [MyType] -> [MyType]
...
В Haskell можно через тайпклассы гораздо лучшее поведение сделать. Но вот это требует больше знаний, чем написать код на JS.

А в начальном обучении надо как можно меньше загружать мозг такими вещами.
Я спорил исключительно с утверждением «в рамках строго типизированного языка не решается». Все (если быть точнее, почти все необходимое на практике) решается, если есть нормальная система типов.
Тут же очевидно ошибка: либо опечатка, либо просто недоступные поля `y` и `z`.
И хорошо, что не скомпилируется — поможет не пропустить ошибку.

Можете привести не просто «рабочий» код, а код без ошибок?
В том-то и прикол что это рабочий код, и реально два объекта в массиве имеют разную структуру.

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

Поэтому и предлагаю учить на динамически типизированном языке, чтобы не забивать голову студентам лишними для начального обучения сведениями.
А теперь придумайте задачу, в которой:
— нужно хранить в одном списке элементы разных типов
— имело бы смысл задать на уроке программирования
Развивайте мысль. Сколько работал с деревьями ни разу на строгую типизацию не жаловался.
var tree = { child:[
    {data:1},
    { child:[
        {data:2},
        {data:3}  
    ]}
]};


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

val tree = 1.node( 2.leaf, 3.leaf)
println(tree.drawTree)
// 1
// |
// +- 2
// |
// `- 3
Детишки до деревьев при правильном подходе доберутся через 4-5 занятий. Если путь буде лежать через ООП, то через полгода, не раньше.
Можно подумать вы JSON и прототипную модель со всеми нюансами собрались за час рассказать. В вашем варианте те же объекты. В чем разница? Все мои примеры — на scala. В ней OOP часть объясняется за пару часов.
datatype tree = Data of (int * tree list)

val t = Data (1, [
    Data (2, []),
    Data (3, [])
])

Угу, покажите в Java эквивалентный код из моего примера.
Объясните какую задачу он решает? От этого сильно зависит реализация.
Вычисление высоты дерева.
Важный аспект — не должно быть классов и, тем более, виртуальных функций.
Тогда при чём тут вывод параметра .x?
И интересно, как в ООП языке можно без классов? А виртуальными функциями Java пока не обзавелась.
Я же писал что для начального обучения ООП нельзя. Во-первых поражает мозг, во-вторых банально сложная тема со всеми примочками, в третьих в разных языках сильно разное ООП, поэтому для изучения ООП нужно минимум два языка, а лучше три. В четвертых в небольших программах ООП только мешает.
JS — это тоже ООП. На прототипах, но ООП. Вы либо будете объяснять объекты в JS как Map (с указанием, что a.b — это a['b']) — упаси боже от такого способа преподавания. Либо вам придется объяснить что такое объект, его свойства и методы (привет console.log). В таком случае подход со статической типизацией всего лишь делает явными все ваши неявные контракты на структуры данных (которые вы предлагаете держать в уме).
Объекты в JS и есть map. Значение в map может быть функцией.
Этого достаточно.

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


Подход со статической типизацией требует изучения системы типов, а это чуть ли не самое сложное в современных языках. Только некоторые ФЯ умудряются прятать сложность системы типов для потребителя, остальные, вроде java и C#, и тем более C++, вываливают эту сложность в самом начале.

Целью начального обучения не является изучение системы типов конкретного яызка. Поэтому динамические языки подходят гораздо лучше статически типизированных.
Объекты в JS и есть map.

То есть вместо общей концепции вы предлагаете изучать конкретную реализацию? Да еще и довольно не наглядную?

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

Я не предлагаю изучать систему типов досконально. Достаточно базового уровня — как структуры контейнера данных и методов. Это не сложнее, чем JSON. Без инкапсуляции, наследования и полиморфизма (это вы почему-то игнорируете, вспоминая vtbl и метки типов).
Я же не предлагаю обучать студентов C++. Есть языки, где не надо лезть в подобные сложности (мои примеры на scala).

Может какие-то динамические языки и подходят (например lisp), но не лучше статически типизированных. И уж точно в такие подходящие языки я не запишу JS с его кучей сложностей. Один из ярких примеров: как вы в этом топике итерируете по массивам монстром for(var i=0; i<x.length; i++) когда во всех нормальных языках уже есть вменяемые конструкции для этого (а в JS конструкция for(var x in xs) вообще не понятно для кого придумана). Приходится совершать кучу лишних приседаний вместо того, чтобы сосредоточится на задаче. Про области видимости, мутабельность везде и во всем и монструозный синтаксис лямбд лучше вообще не вспоминать.
Это точно не язык для обучения — очень много граблей о которых все умалчивают, но про которые надо знать.
То есть вместо общей концепции вы предлагаете изучать конкретную реализацию? Да еще и довольно не наглядную?


Ты смотришь через призму ООП. Если не затрагивать ООП и классы, то Объект === map отличная концепция. Очень простая и понятная.

Я не предлагаю изучать систему типов досконально. Достаточно базового уровня — как структуры контейнера данных и методов.


Любой контейнер в типизированном языке это generic. Это вызывает кучу проблем с пониманием. Многие, кто переходят на C#\Java с PHP\JS довольно долго втыкают generic_и. Не думаю что на курсе начального программирования имеет смысл рвать этим мозг.

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

Для инженерных специальностей лучше таки JS или Python.

Кстати в JS уже есть давно Array.prototype.forEach. Граблей много в любом яызке, по ним можно просто не ходить. Ведь во время начального обучения каждый шаг под присмотром преподавателя.

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

ЗЫ. После того как я прочитал JavaScript: Good Parts я вообще забыл про все грабли JS, просто перестал пользоваться потенциально опасными вещами. Ничего от этого не потерял.
Кстати в JS уже есть давно Array.prototype.forEach.

Я в курсе. А теперь без гугла ответьте где он поддерживается, а где — нет.
К слову о граблях: `===` — самые эпичные грабли, что я встречал. Не будете рассказывать о существовании `==`?

`JavaScript: Good Parts` — сколько времени займет их изучение у неподготовленного студента? Как заставите соблюдать?
Везде поддерживается, кроме IE8-, а что это меняет? кстати первым же упражнением на массивы имеет смысл написать свой forEach.

Где надо ===, а где == расскажет jshint, встроенный в jsfiddle. Кстати JSHint как раз работает по рекомендациям из книги JavaScript: Good Parts.
Здравствуйте, приплыли. Обязательное использование удобного только для мизерных кусков кода инструмента? Доступного только online (при любых проблемах с сетью занятие отменяется?). Не локализованного (у наших студентов с английским проблемы). Ну и да, вам таки придется объяснить на что оно там ругается в случае `==`/`===` и рассказать с чем эта ругань вообще связана.

Нет, спасибо.

Да и изучать по началу лучше в REPL. Он у JS есть, но это не jsfiddle.
Английский — обязательно. В любом случае рано или поздно надо будет изучить на уровне понимания команд в IDE. Главное чтобы учебник был на русском.

Проблемы с сетью? Вы о чем? У всех 3г\4г, да и на крайняк можно поставить ченить в классе.

Объяснить '===' и '==' очень просто. Первый выполняет простое сравнение, второй семантическое. Таблица для семантического сравнения простая, но все равно лучше не использовать.

Кстати почти во всех языках есть аналоги '===' и '==', ниче живут люди.

Английский они не знают и ругань на нем от jshint не поймут. Это факт, с которым придется смириться — такие у нас студенты.

Вы где собрались преподавать? Ни кто 3G вам не оплатит. Да и доступ к администрированию класса не дадут. А классов несколько. Так что только то, что есть. А то, что есть, имеет свойство ломаться (по своему опыту сужу).

Аналога "2" == 2 нет почти ни где. Что такое семантическое сравнение лучше просто не заикаться.
А я вот категорически против динамически типизированных языков: они позволяют прятать и не понимать важную часть программирования. Это может неслабо аукнуться позже. Потоки тоже очень сложная вещь, но без них сейчас никуда и их всё равно придётся изучать. Пусть и чуть позже.
Ты видимо не совсем понимаешь.

1) Начальное программирование преподается для тех, кто еще ни на чем никогда не программировал.
2) Весь курс занимает один учебный семестр, примерно 17 недель занятий (минус два, ибо первое вводное, а последнее — зачет). 15 занятий по 2 ак. часа + столько же практики. При интенсивном обучении такой курс можно уложить в неделю по 8 астрономических часов в день.
3) Цель курса — научить комбинировать программы из подпрограмм, обучить базовым структурам данных и базовым алгоритмам. Обязательно должны войти массивы и матрицы, рекурсивные структуры данных (списки и деревья), графы, немного динамического программирования.

Если ты в этот курс нагрузишь типизацию, управление ресурсами, ООП, многопоточность и синхронизацию, то только их будешь объяснять полгода.
Именно поэтому многопоточность и синхронизация идут отдельным курсом.
Управление ресурсами, типизацию и ООП на необходимом для начала уровне можно уложить в 2-4 академических часа. Ну а далее потихоньку раскрывать понятия параллельно изучениям алгоритмизации.

1. У нас было всё просто: даётся теория по алгоритму, даётся на выбор два языка (pascal, c) и задача. Никто языки нам вообще не преподавал, но все быстренько изучили на минимальном уровне паскаль и выполнили задачи. Были у нас и деревья, и рекурсия, и сложные циклы. Но такого подхода никому не желаю.
2. Аналогично.
3. Цель — научить составлять подпрограммы и комбинировать из них программы. А для этого неплохо бы знать теорию.
Откуда вы языки знали?

Какую теорию надо знать чтобы комбинировать? Разве что про ленивые\энергичные вычисления.
Лично я? Ещё со спектрумов с бейсиком баловался, Pascal пришлось быстренько подтягивать, C — изучать. Некоторые вообще ни одного языка не знали.

Чтобы составлять подпрограммы, а потом их комбинировать нужно владеть теорией написания этих самых подпрограмм вообще и на выбранном языке и правила комбинирования в рамках выбранной парадигмы и выбранного языка.
Я спрашиваю про всех. Практика показывает что даже на программистских специальностях не более 20 процентов имеют опыт программирования. В школе сейчас программирование или не преподают вообще или делают это крайне плохо.
На мой взгляд, большая часть примеров из данной статьи очень наглядно демонстрирует непонимание базовых концепций, таких как: тип данных, объект, формальные аргументы, способы передачи и т.д. В общем и целом, это неплохой перечень аргументов в пользу того, что обучать лучше на статически типизированных языках, где все механизмы на поверхности.
Нужно и можно, так как ООП легко объясняется примерами из реального мира и биологии. Точнее та часть, которая нам нужна в начале программирования. Сложные концепции можно оставить на потом. Ну и всяко слабее поражает мозг, чем GOTO и образуемая из-за него лапша.
ОМГ, тока не биология. ООП на основе реального мира задает категорически неверный подход к проектированию.

После такого обучения ООП люди неправильно понимают ООП.
И чем же он неверен-то? Можете подробнее описать?
Тем что люди начинают после этого наследовать квадрат от прямоугольника. В реальном мире то квадрат является частным случаем прямоугольника.
И правильно делают! Квадрат это подмножество прямоугольников! Так же как прямогульник — подмножество четырёхугольника — подмножество «геометрическая фигура»…
Не умею высасывать воду из пальца.
Почему не должно быть классов? Класс как структура для хранения данных крайне прост для понимания (без инкапсуляции, наследования и полиморфизма. То есть без ООП как подхода к проектированию).

case class Tree[T](data: T, children: Seq[Tree[T]])
def height(tree: Tree[_]): Int =
  if (tree.children.isEmpty) 1
  else 1 + tree.children.map{height}.max

Что тут объяснять? В случае с JSON делается неявное предположение о структуре каждого элемента (это, кстати, тоже надо объяснить). Тут это предположение делается явно — вот и вся разница.
Тебе понадобится много времени чтобы объяснить generics, а для этого тебе надо будет объяснить как работает типизация. Некоторые опытные программисты до сих пор не понимают это.

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

Важно дать понимание комбинированию, базовым структурам данных, алгоритмам, при этом как можно меньше загружать мозг лишними деталями.
Объяснять типизацию и генерики не сложнее, чем объяснять неявную типизацию в JS и правила приведения типов там. Нам не понадобятся все нюансы (как и в случае с JS) — достаточно показать пару примеров. Не надо студентов уж совсем безмозглыми считать.
Да и надо вообще типизацию объяснять, кто вам такую глупость сказал что нужно объяснять типизацию?

Прочитайте SICP, там в первых трех-четырех разделах проходится материал, эквивалентный году обучения в российском вузе. И там вообще нет типизации. Она неявно присутствует, но нигде не объясняется.

Потому уже, при создании интерпретатора вводятся метки типов и vtbl.
Не надо объяснять типизацию в JS? Пусть студенты сами выясняют почему "2" * 2 == 4, a "2" + 2 == "22"?

Типизацию в JS объяснить придется. Как придется объяснить неявный контракт на тип (вроде того, что обращаясь к полю `x` мы не явно предполагаем, что у переданного параметра такое поле вообще есть и содержит координату, а не что-то еще).

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

Как в анекдоте:
— доктор, когда я так делаю мне больно
— не делайте так

И типизацию не придется объяснять. Посмотри SICP там не объясняется типизация языка.
Не нужно просто этого писать.

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

А в SICP — lisp, там нет этих граблей — там нельзя суммировать строки. А типы данных там есть и студенты это узнают после первой же попытки сложить 2 строки.
Какого ввода? Работа с пользовательским вводом и внешними данными отдельная и большая тема. Я бы рекомендовал не начинать с нее. В динамических языках есть REPL, это позволяет вводить данные в терминах языка и не париться с вводом-выводом.

Еще раз говорю — прочитай SICP посмотри как там построен курс.
Программирование без взаимодействие с внешним миром? Да студенты от скуки помрут.
Еще раз говорю — прочитай SICP посмотри как там построен курс.

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

У тебя лично большой опыт преподавания, особенно начального?.
Подход, зарекомендовавший себя с lisp не применим с JS. Именно из-за не строгости JS, а так же из-за огромного количества подводных камней в нем.
Что вы подразумеваете по дженериками? И почему считаете, что они должны быть в каждом классе?
В каждом класса-контейнере. Начиная с массива.
Вы знаете java? Тогда вы, наверное, знаете, что массивы там ни разу не дженерики? А то, что коллекции «достроенные» дженерики вы, наверное, тоже знаете? Т.е. к коллекциям можно относиться и как к массивам типа Object и к массивам заданного дженерика? И до определённого момента про дженерики можно вообще не говорить?
В Java есть разница между системой типов яызка и системой типов рантайма. Вторую не рассматриваем. В первой массив тоже generic тип, хоть и неявно. Для того чтобы эмулировать его обобщенность есть 100500 перегрузок функций класса Array.

Но в Java массивы фиксированы, в JS — динамические. В Java надо будет еще разбираться с ArrayList, который кстати generic и почему он так сильно отличается от обычного массива.
До 1.5 ArrayList ни разу не дженерик и его можно использовать в таком виде и сейчас. Вот только данные извлекать из такой коллекции — геморройненько, да.
кучу дополнительных конструкций

Какую еще «кучу»? Достаточно просто подтвердить, что мол да, я в курсе, что только что введенные мной поля не видимы:

val xs = List[{def x: Int}](new { val x = 1; val y = 2 }, new {val x = 3; val z = 4})
xs.map{ _.x }
// List[Int] = List(1, 3)


А вообще для такого стоит использовать `Map`:
val xs = List(Map('x -> 1, 'y -> 2), Map('x -> 3, 'z -> 4))
xs.map{ _('x) }
// List[Int] = List(1, 3)
Невидимы.
Или вы будете рассказывать что будет если обратиться к отсутствующему полю?
for(var i=0; i<x.length; i++) {
    console.log(x[i].y); // bang!
}

Или, того хуже, будете объяснять как проверить наличие поля у объекта?
Вот уж точно узко специфичные для реализации и совершенно ненужные знания.
for(var i=0; i<x.length; i++) {
    if(x[i].y) {
        console.log(x[i].y); // OK
    }
}

Простите, но это быдлокод.

Как false трактуется далеко не только undefined. О наличии `0`, пустой строки, null и NaN мы так тоже не узнаем. Ну и естественно не узнаем о наличии самого false.

Вот зачем человеку держать в голове столько мелочей, которые и вы, как апологет JS, удержать не можете?

Корректная проверка:
if('y' in x[i])


Сможете без гугла ответить где поддерживается `in`?
Зачем все эти тонкости знать? Код писать можно и без них.

Чтобы учиться программировать не надо изучать все тонкости. Более того, некоторые вещи лучше даже не знать на начальном этапе.
Если вы положили в коллекцию элементы разных типов, то либо вы не сможете использовать разные части из них (возвращаемся к вашему утверждению про «не невидимы»).

Либо вам придется знать эти тонкости, чтоб корректно различать разные элементы из этой коллекции. Чтоб не наткнуться например на то, что поле, оказывается, не может содержать 0 или пустую строку (x[i].y) иначе приятной отладки (вот уж точно врагу не пожелаешь).
Точняк. Уже все языки переплелись в голове. Родное не узнаю.
JS? Вы издеваетесь? Приучать к возможности полного хаоса в самом начале?

1. Таки требует — браузер нужен и нужна IDE (не надо мне про блокнот! Ну не стоит с него начинать, когда есть отличные IDE!)
2,3. уж лучше этот оверхед, который вынудит с самого начала стараться писать правильно. Требования препода к стилю кода куда хуже воспринимается и выполняется.
4. Не совсем. Менеджмент быть должен, но на уровне создания. Остальное лучше что-то вроде GC.
5. Назовите мне хоть один не практический язык и причины, почему вы его таким считаете. Что-то мне подсказывает, что даже на brainfuck можно реальные программы писать.
1) Есть jsfiddle — его более чем достаточно.
2) В jsfiddle есть JSLint, он быстро покажет где неправ.
3) Никакого менеджмента вообще. На начальном этапе важно понять как делать функции и комбинировать их в другие функции. Любое управление ресурсами — головная боль, мешающая достижению цели.
4) Haskell, F#,Scala, Lisp — за всю жизнь может ни разу не пригодиться. Старый паскаль — очень далек от современного delphi. Голый C — может пригодиться только в курсе системного программирования, в качестве языка для начала обучения не подойдет. Про эзотерику вроде brainfuck даже не говорю.
1. Если вы хотите заниматься дома — ваш вариант годится. Если речь идёт про обучение в классе — преднастроенная среда не вызывает никаких проблем. И дома ту же java можно поставить в полпинка (и настраивать ничего не придётся). То же касается почти любого языка.
2. Лучше, чтобы это говорил компилятор/интерпретатор, а IDE подсвечивала (по возможности — до компиляции/интерпретации).
3. Нужен. В JS он скрыт, насколько возможно, но он тоже есть. И легко попасться в ловушку, когда переменная не инициализирована, а человек уже пытается её использовать! Пусть уж контроль будет явным — не инициализирована — не компилируем/интерпретируем.
5. Ну и чего вы мне функциональщиной кидаетесь? А такой активно используемый и не до конца одряхлевший Java? А насквозь мной нелюбимый, но не менее полезный ныне C#? А другие актуальные языки с GC? И C сбрасывать со счетов не стоит (хотя и не считаю самым умным начинать с него… разве что факультативно). Тем не менее речь-то было про практическое использование. А практически использовать можно любой из них. Другое дело, что не под все задачи подходят и распространённость не всегда высокая.
1) Практика показывает что студенты в среднем редко дома ставят софт, кроме того современные IDE требуют мощных компов.
2) посмотри как работает jsfiddle
3) надо учить сразу инициализировать при объявлении, все остальное запретить, кстати JSHint показывает такие места, ну и 'use strict' обязательно. Не забывайте что при обучении код пишется в первую очередь для преподавателя, а потом для компьютера. Естественно преподаватель должен все проблемные места указать и потребовать исправить. В этом и суть обучения — тренировка писать правильный код на уровне моторных навыков.
4) Java, C# и C++ не подходят по причине необходимости установки тонны софта, необходимости знать и понимать систему типов и public-sttaic-void-main-overhead. В качестве языка для продолжения обучения (2 семестр или максимум 2-й год) C# и Java подойдут очень хорошо.
1. Netbeans неплохо крутится и на нетбуках, но заниматься программированием на нетбуке… это в любом случае нужно иметь избыточную силу воли.
2. Посмотрю.
3. Вот зачем мне сразу инициализировать переменную, если я ещё не знаю, чем её буду инициализировать? При обучении, так же как и при работе, код пишется для себя и других. Чтобы можно было прочитать и понять. И поверьте мне — требования компиляторов студентам кажутся менее неприятными, чем «придирки» препода к «code style» («работает же! чё он придирается!»).
4. Java требует установки всего 2х компонент: JDK и IDE (причём есть бандлы NetBeans'а, включающие JDK). Какие тонны софта? Требования к оформлению у Java не такие уж и драконовские, оверхед небольшой. Зато уже на уровне компилятора есть некоторое приучение к code style.
А зачем объявлять переменную, которую не знаешь чем будешь инициализировать?

ЗЫ. Установка даже одного компонента для обучения — дофига, это сразу у 30% студентов отобьёт желание что-то делать. Кстати я как-то пробовал поставить Netbeans когда учился в универе — не взлетел.

Затем что от контекста зависит, что же в ней находиться будет. В JS можно не объявленную переменную использовать — никто ничего не скажет (кроме значения undefined… или неожиданного, если такую переменную уже кто-то инициализировал в другом месте). В статически типизированных языках — сперва объявляешь, потом инициализируешь, потому используешь. Все шаги на виду, все контролируются компилятором.

Вот не знаю, чего уж вам так не повезло — сколько раз нетбинс ставил — всё равно всегда взлетал. Даже на нетбуке. Единственное — если бандл неверный выбирал — он ругался и говорил «Дай мне JDK!»
Вот зачем мне сразу инициализировать переменную, если я ещё не знаю, чем её буду инициализировать?

Зачем вам переменная, в которую вы не знаете что положить? В переменную надо класть значение один раз при объявлении, совмещенном с инициализацией. Остальное — от лукаваго.
И чем вы предлагаете инициализировать переменную при объявлении в случае:
SomeInterface si;
if (someVar extends SomeSpecialClassWithInterfaceImplementation)
  si = someVar;
else
  si = SomeManufacture.getInstance();

Ну такое достаточно абстрактное решение, где заполнять каким-то дефолтовым значением нам не выгодно?
SomeInterface si = someVar extends SomeSpecialClassWithInterfaceImplementation?someVar:SomeManufacture.getInstance();
И вот вы и сами видите, что получается фигня — неудачный перенос == разрыв мысли в коде. Вообще тернарный оператор хоть и удобен при написании при чтении создаёт излишнюю сложность.
Кстати, это я обошёлся двумя строчками, иногда в одной из ситуаций идёт нетривиальная инициализация… Хотя её нередко можно упаковать в отдельную функцию.
А вот это называется: используйте правильные языки программирования для обучения студентов. Вспомните что идет почти в самом начале SICP. И как вы будете объяснять подстановку на основе подобных конструкций?

Вспомните scala, R… да вообще любой язык с поддержкой ФП:

val si =
  if (condition) valueOnTrue
  else valueOnFalse


Вообще путать людей изменяемым состоянием стоит как можно позже.
Не могу вспомнить — не изучал ни SICP, ни scala, ни R. Из ФП — только лисп и только со взрывом мозга, т.к. человеческих лекций по нему в универе сделать не смогли. Точнее — быстрый подъём до сдачи лаб… Что не приводит ни к пониманию языка, ни к любви к нему.
Вот это и плохо, когда изучают бессистемно. Нагружают устаревшими понятиями императивного программирования.

Про подстановку: гораздо нагляднее объяснение, что `=` не записывает какое-то«значение» в какую-то «память» (не нужное на начальных этапах понятие, хоть стек не вспоминайте). А устанавливает равенство, то есть дает новое имя выражению справа от `=` и тогда любое вхождение слева от `=` можно заменить тем, что находится справа от `=`.

В случае с отдельным декларированием такого простого и обобщенного объяснения не получится.
ИМХО, первый язык должен иметь статическую типизацию, для того, чтобы человек лучше понимал систему типов языка. Типы и в JS есть, но там они слишком неявные, и к тому же все что угодно можно присвоить к чему угодно, а это сильно коверкает мозг.
Один из лучших курсов начального обучения программированию — SICP как ни странно на Lisp, где с типами все еще хуже, чем в JS.

Так что не нужно парить мозг сущностями, которые не нужны для достижения цели.
С каких это пор в лиспе с типами хуже, чем в JS? Все там отлично с типами. И типизация там строгая.
Не используйте слова «строгая» в отношении к типизации. Типизация бывает статическая — при компиляции и динамическая — во время выполнения программы. У Лиспа (в частности Scheme) типизация динамическая. Учитывая что там только списки (нет массивов и объектов), то reasoning на основе типов делать еще сложнее, чем в JS.

«Строгость» типизации определяется только вашими ожиданиями от системы типов.

Но все это для начального обучения лишнее.
Строгость — это когда в лиспе нельзя написать (+ 1 «2»). Можно только написать (string-append «1» «2») или (+ 1 2). Нестрогость — это когда в JS можно написать 1 + «2». Что по вашему лучше?
Я же говорю — «строгость» не боле чем твои ожидания.

Я 7 лет уже пишу на C# и 3 года на JS и в обоих можно написать 1+«2». В C++ при желании также можно переопределить оператор + для строк и чисел, чтобы можно было так писать.

Кстати правило приведения к строке довольно простое чтобы из-за него так париться.

+ плохой пример, признаю. Нужно было пример с оператором - привести. 1 - "2" в JS — ИМХО, бред сивой кобылы в JS.
Я не могу этого гарантировать и хочу, чтобы рантайм выкинул ошибку в случае несоответствия типов.
Дык это только твое желание. JS вернет NaN (не-число) в случае неверной операции. Это ведь не undefined behavior.

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

Тем не менее избежать таких ошибок легко. Я вот сколько писал JS ни разу на это не наталкивался.
> Дык это только твое желание
Нет, это не только мое желание, чувак. Это желание большинства нормальных программистов

> JS вернет NaN (не-число) в случае неверной операции
Не всегда. 1 - "2" вернет -1, например.

> Избежать таких ошибок легко
Когда в проекте более 1 человека, начинаются проблемы.
Какое отношение все это имеет к начальному обучению программированию?
Такое, что после изучения JavaScript в качестве первого языка программирования у человека может отпасть желание становиться программистом в принципе.
Скорее, после изучения JavaScript в качестве первого языка программирования, его code-style может стать таким ужасным, что человека потом не примут ни в одну команду.
С чего бы это? JS легкий язык. В нем много тонкостей и тайных мест, но они не нужны чтобы писать программы. Вообще не нужны. Придерживаясь простых правил почти все грабли можно обойти.

У него много недостатков из-за типизации и модульности, но к обучению программированию это отношения не имеет.
Модульность и типизация не имеет отношения к обучению программированию? Всё с вами понятно
Посмотрите на SICP, там нет ни модульности, ни типизации в явном виде. И по нему спешно учили много лет.
Structure and Interpretation of Computer Programs (SICP) is a textbook aiming to teach the principles of computer programming, such as abstraction in programming, metalinguistic abstraction, recursion, interpreters, and modular programming
(wiki)
Я предлагаю скачать SICP и прочитать, найдете там модульность, которой нет в JS — с меня пиво.
Скачаю как-нибудь. Сейчас мне пока хватает материала для самообразования.
Только в C# (если я правильно понимаю и помню) вы получите «12», а в JS 3.

А Pascal подходит для первоначального обучения? а Basic?

Раньше я тоже был такого мнения, что c++ нужно учить первым. Но потом увидел наглядно как человек мучился изучая с++ с нуля.
Проблема была в первую очередь с #include и std::cout.
ИМХО нужно сперва паскаль изучать, просто для понимания программирования, а уже когда человек поймет как программировать нужно переходить на с++ ( ну еще можно и ассемблер для лучшего понимания указателей )

А Python подходит для первого обучения?

«Множество компиляторов, консольные команды, этапы сборки программы» — весьма сомнительный плюс для первого языка программирования ИМХО. Тут разобраться бы вообще как что работает, а обилием директив можно человека вообще отвадить от программирования или, по крайней мере, от компилируемый языков программирования.
Вообще, для ответа на вопрос «какой язык выбрать первым для обучения программированию в ВУЗе» нужно понять, кого ВУЗ хочет выпустить в итоге.

С равным успехом можно выбрать Scheme, C/C++, Java/C#, Python — всё зависит от задачи.

Для математиков идеально подходят Scheme и (или) Python, потом можно посмотреть в сторону Haskell.
Для подготовки «Enterprise-программистов» хорошо подходят Java/C# или тот же Python — довольно низкий порог вхождения, языки просты для понимания, голова не забивается всякими низкоуровневыми вещами.

Если же ВУЗ хочет выпускать действительно хороших специалистов в области программирования, я считаю, что обучение нужно начинать с языка Си. Си, с одной стороны, прост (по сравнению с С++), с другой стороны, имеет несколько высокий порог вхождения и позволяет «отсеить» тех студентов, которые не способны программировать.

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

И в этом самом процессе обучения, язык должен не мешать и не отвлекать.
Первый язык программирования для обучения — блок-схемы. Или псевдо-язык программирования на основе обычного разговорного языка. А в качестве компилятора — преподаватель.
И когда основные концепции процедурного программирования (условные переходы, циклы, функции, типы) станут понятны, тогда уже и можно плавно переходить к какому-нибудь из реальных языков программирования (имхо, Pascal).
А если в реальном языке программирования не будет принято использовать условные переходы (без лишней причины) и циклы (почти всегда)? И почему именно процедурное, тем более Pascal, если он явно не понадобится после?
Парадигма процедурного программирования самая простая для понимания: функциональное или логическое программирование требуют понимания мат. аппарата уровня ВУЗа, декларативное на практике сейчас редко используется, да и в голове не будет понимания происходящего, ну а ООП — это надслойка, для понимания которой все равно необходимо знание хоть одной из основных парадигм.
Да и процедурное программирование ближе к машинной архитектуре в целом.

Pascal мне нравится в плане обучения тем, что в нем более строгая и сильная система типов, нежели, например, в Си, что крайне важно для обучения.
Кроме того, это статически компилируемый язык, а значит через него, при желании, можно познакомить со стандартным tool-chain'ом: редактор-компилятор-линкер.
Также синтаксис для новичка очевиднее и понятнее, нежели различные фигурные скобки, инклуды с решетками, прочие макросы и так далее.

Кроме того, стоит понимать, что обучение программированию с нуля и обучение C/PHP/JAVA/Enterprise/Web/Android/<any-technology-or-language> программиста — это совершенно разные задачи.
То, что Pascal не используется на практике — это не аргумент. Человека, которого обучили основным концепциям программирования и компьютерной архитектуры, несложно обучить конкретной технологии или языку.
А вот переучить человека, которого с самого начала обучали С/С++, а не программированию, очень сложно (отсюда у нас и полно говнокодеров и кривых программ).
>Да и процедурное программирование ближе к машинной архитектуре в целом.

А map-reduce в современных базах данных — это процедурное или ближе к машинной архитектуре?

Вообще, близость к машинной архитектуре — миф со времён софта, умевшего только 1 ядро одного процессора на одной машине и не представлявшего о GPGPU.

> Pascal мне нравится в плане обучения тем, что в нем более строгая и сильная система типов, нежели, например, в Си, что крайне важно для обучения.

Так выбирать же можно не только между ними. Есть тот же Python, использующийся в MIT. Чем мы хуже?
Вообще, близость к машинной архитектуре — миф со времён софта, умевшего только 1 ядро одного процессора на одной машине и не представлявшего о GPGPU.

Не стоит путать теплое с мягким.
Говоря про машинную архитектуру, я имею в виду не конкретные реализации, оптимизации, технологии, а именно базовую архитектуру: процессор с регистрами, исполняющий конкретные инструкции, оперативная память, стек.
Все остальное — это уже более продвинутая программа, а речь идет именно об обучении программированию (почти) с нуля.
Так выбирать же можно не только между ними. Есть тот же Python, использующийся в MIT. Чем мы хуже?

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

UPD: и, конечно же, в питоне нет работы с памятью и стеком, с концепциями которых хороший программист обязан быть знаком.
В питоне строгая типизация, есть типы (причём базовых типов достаточно) и можно объяснить типовую безопасность. Это в C можно привести указатель на число к указателю на строку, там типизация слабая. Динамичность тут ни при чём.

> Все остальное — это уже более продвинутая программа, а речь идет именно об обучении программированию (почти) с нуля.

В смысле с перфокарт и архитектуры PDP-8?

Мы не можем гарантировать, что базовая архитектура останется той же даже 10 лет, не говоря о прочих сроках. И, опять же, начиная с вымерших языков, в которых половину времени приходится писать очевидный как нам, так и компилятору синтаксический мусор вместо тех же map/fold* или list comprehension, вряд ли можно до конца курса успеть понять потоки (которые ГОРАЗДО сложнее и ГОРАЗДО более применимы, чем основы паскаля уже сейчас), не говоря об асинхронном программировании и хотя бы базовых представлениях о кластерах. И те же лямбды сейчас используют все, а не только освоившие нужный мат. аппарат (и зачастую получается неплохо).
В питоне строгая типизация, есть типы (причём базовых типов достаточно) и можно объяснить типовую безопасность.

Строгая типизация не отменяет того, что она динамическая.

Это в C можно привести указатель на число к указателю на строку, там типизация слабая. Динамичность тут ни при чём.

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

Динамичность же мешает тем, что человек не сталкивается с таким понятием, как «тип переменной».
Да, есть «тип значения», но для новичка это неочевидно.

В смысле с перфокарт и архитектуры PDP-8?

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

То есть вы предлагаете обучать программистам архитектуре будущего, которой даже еще не существует?
Или для вас такие понятия, как «оперативная память», «стек» ассоциируется только с перфокартами и вы считаете, что этого знать программисту не нужно?

И, опять же, начиная с вымерших языков, в которых половину времени приходится писать очевидный как нам, так и компилятору синтаксический мусор вместо тех же map/fold* или list comprehension, вряд ли можно до конца курса успеть понять потоки (которые ГОРАЗДО сложнее и ГОРАЗДО более применимы, чем основы паскаля уже сейчас), не говоря об асинхронном программировании и хотя бы базовых представлениях о кластерах. И те же лямбды сейчас используют все, а не только освоившие нужный мат. аппарат (и зачастую получается неплохо).

Чтобы понять, зачем нужны map'ы/fold'ы/filter'ы, надо понимать, что они вообще делают и какие есть альтернативы и чем они хуже.
Можно, конечно, обучить студента их использовать во всех случаях, но он даже не будет понимать, в чем преимущество этих заклинаний. Это все равно, что научить человека решать квадратные уравнения через дискриминант, но не объяснить, что это такое и зачем.

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

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

Вы можете дать первокурснику формулу разложения в ряд Тейлора и научить ею пользоваться, но какой в этом смысл, если по итогу этот человек даже не в состоянии перемножить два многочлена?

То, что вы предлагаете — это тренировать кодеров. Да, они будут уметь пользоваться всеми современными концепциями. Но для них любой низкоуровневый язык, ниже Python'а или Ruby, — это будет чистый rocket-science.
Нет, то, что вы предлагаете — это и есть тренировка низкоуровневых кодеров. Да, они будут уметь пользоваться всеми низкоуровневыми оптимизациями, но заставь их написать что-то распределённое — это будет чистый rocket-science.

Примерно тот же уровень аргументации. Вообще, посмотрите на тот же SICP. Это — один из примеров, как начать не с «типов», характерных для x86-процессоров, объяснить стэк, не используя паскаль и дать базовые знания computer science, а не кодерских навыков «как сделать это в таком языке на x86».

>Потоки, асинхронное программирование, кластеры, лямбды — господи, вы о чем? Этому сложно обучить даже опытных программистов.

Асинхронность сложна? На плюсах? Да. Асинхронный erlang? Нет. Асинхронный gevent? Ни разу. На этом пишут реальный код, понимая теорию, а не особенности реализации конкретной библиотеки на одной-двух ОС на x86? Да. Есть ли будущее у кодера, не умеющего потоки, в мире, где в мобильниках по 4 ядра уже сейчас? Есть ли время изучить каждую деталь их реализации на низком уровне в рамках курса ВУЗа?

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

И я отдаю отчет в том, что начинающий программист не то, чтобы не может отличить процесс от потока, а даже не в состоянии отличить RAM от ROM.

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

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

И только после того, как юный падаван освоит основы чистописания, складывать и умножать числа, решать уравнения, писать в Present/Past/Future simple/progressive, то только после этого его можно уже с легкостью «гнуть» в любую сторону. После этого можно и интегралы с дифференциалами, и матрицы перемножать, и Past Perfect Progressive, и пунктуацию, и асинхронное программирование, и потоки, и все, что ваша душа пожелает.

Только после того, как человек поймет, что программирование — это не Java/C/Pascal/Python/PHP, а создание алгоритма/архитектуры/логики, только после этого его можно пускать писать что-либо более сложное, чем подсчет чисел фиббоначчи.
Но не на ассемблере же эти алгоритмы писать, в конце концов. Средства не должны быть слишком сложными и не должны отвлекать деталями внутренней реализации, иначе мы скатываемся в изучение этих средств.

Нужно хотя бы знать название того алгоритма/паттерна/концепта, который хочешь реализовать. Остальное — реализуемо.
Вы прыгаете из крайности в крайность.
Речь не идет об ассемблере. Я с самого начала обозначил, что по-моему мнению для вышеобозначенных целей (построить картину элементарных концепций программирования, без которых невозможно двигаться сколь угодно вперед) Pascal подходит. По моему мнению.

Можно всему вышеобзначенному обучить и на других языках, но, опять же по моему мнению, большинство языков были созданы для опытных уже программистов, которые могут оценить их плюсы и возможности, но не для новичков в программировании. И, как следствие, эти языки могут обладать особенностями, которые могут помешать новичкам сформулировать в голове основные концепции, что может сказаться на дальнейшем развитии.
Подходит и brainfuck, вопрос в практичности этого.
Тот же quicksort в паскале:
{ X is array of LongInt }
Procedure QuickSort ( Left, Right : LongInt );
Var 
  i, j : LongInt;
  tmp, pivot : LongInt;         { tmp & pivot are the same type as the elements of array }
Begin
  i:=Left;
  j:=Right;
  pivot := X[(Left + Right) shr 1]; // pivot := X[(Left + Rigth) div 2] 
  Repeat
    While pivot > X[i] Do i:=i+1;
    While pivot < X[j] Do j:=j-1;
    If i<=j Then Begin
      tmp:=X[i];
      X[i]:=X[j];
      X[j]:=tmp;
      j:=j-1;
      i:=i+1;
    End;
  Until i>j;
  If Left<j Then QuickSort(Left,j);
  If i<Right Then QuickSort(i,Right);
End;

В python (развёрнуто для понимания непитонистами)
def qsort(list):
    if not list:
        return []
    else:
        pivot = list[0]
        less = [x for x in list     if x <  pivot]
        more = [x for x in list[1:] if x >= pivot]
        return qsort(less) + [pivot] + qsort(more)

Это и есть отсутствие войны с языком. Здесь нет ничего сложного, это — не квантовая физика. Просто нет лишней возни там, где она не нужна. Python создан не только для опытных программистов. И он помогает сформировать базовые концепции (конкретно тут — list comprehension). Кстати, версия без list comprehension возможна и она всё ещё понятнее, короче, проще и полнее, чем в Pascal.

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

Версия на haskell будет в 2 строчки, дословно воспроизводящие алгоритм (а не разворачивающие алгоритм в монстрообразное нечто, как в случае с паскалем), но он не совсем предназначен для обучения программированию. Хотя учить алгоритмы на нём — интересная идея.
О каких «list comprehension» может идти речь, если человек не знает вообще, что такое list?
Человека сначала надо обучать понятию списка, научить его создавать, работать с ним, обучить структуре, прежде чем давать им алгоритмы на их основе.

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

Такое ощущение, что вы даже не вдумываетесь в то, что я до вас пытаюсь донести.
Я вам объясняю, что учиться рисовать для начала надо карандашом на бумаге, начиная с рисования кубиков и апельсинов, а вы говорите «зачем все это нужно, если можно сразу рисовать в Фотошопе».
Более того, ваш же пример на паскале обучает сразу множеству вещей:
1) Осмысленное именование переменных, без чего легко запутаться;
2) Работа с массивами;
3) Понятие циклов;
4) Понятие условных переходов;
5) Типизация переменных
и прочее, прочее.

А пример на Питоне — для обучения новичков вообще противопоказан.

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

Писать лаконичный и короткий код человек еще успеет научиться.
А вот понимать и структурировать его — этому надо научиться.
Вы понимаете, что эту «работу с массивами», «понятие циклов», «понятие условных переходов» и «типизацию переменных» придётся повторить тысячи раз при обучении уже другим концептам. Не потому, что это сложные вещи (нет в них ничерта сложного даже для новичка), а потому, что pascal не умеет по-другому?
И да, ни работа с массивами, ни понятие циклов, ни понятие условных переходов, ни явная типизация переменных не являются базовыми в computer science, вопреки популярному заблуждению. Язык, навязывающий их, заставляет изучать сам язык вместо тех самых базовых понятий.

В том же MIT дают python первым языком точно таким же ничего не понимающим студентам. И они понимают и структурируют этот код.

> А пример на Питоне — для обучения новичков вообще противопоказан.

С чего бы? Он отражает алгоритм, а не проблемы одного мёртвого языка (например, с обязательными типами). Если мы сейчас концентрируемся на алгоритме — начерта нам воевать с языком, разжёвывая компилятору каждое действие?

Такое чувство, что паскаль — это нечто вроде латыни. Не то, чтобы его вредно было учить, но сейчас в нём нет необходимости.
Начнем с того, что MIT — это не просто какое-то ПТУ. Это даже не МГУ или Бауманка.
MIT — элитный институт, куда набираются не просто смышленные ребята, а в принципе одни из самых смышленных. А такие будут в состоянии обучиться программированию даже начиная с брейнфака.

И опять же, вы циклитесь на паскале, но путаете теплое с мягким.

Вы делаете главную ошибку в своем утверждении:
(нет в них ничерта сложного даже для новичка)

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

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

И пример MIT'а подходит плохо, т.к. там начальный уровень студентов уже на две головы выше среднего, а умного студента можно даже складывать научить, начиная преподавание с теории множеств.

И вообще, вы сами-то хоть сталкивались с преподаванием программирования первым курсам университетов?
Да ничерта они не понятны.

wla.berkeley.edu/~cs61a/fa11/lectures/functions.html#introduction — пример того, каким может быть первый язык. Обратите внимание, через какое время даётся понятие «абстрагирование» (которое нужно для этого умения «строить башенку») и насколько мощные абстракции даются практически сразу.

В многословных старых языках так нельзя. В них нет такого repl, нужно явно задать каждый тип (перед этим объяснив типы), объяснить, чем function отличается от procedure (правильный ответ: ничем) и объяснить, почему мы не можем применить функцию к функции или вернуть функцию (правильный ответ: мы можем).
Опять же, вам про Ерему, а вы про Фому.
Я не утверждаю, что Паскаль — единственный вариант для обучения. Это мое личное предпочтение.

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

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

Лекции, которые вы предоставили — это не «программирование с нуля».
Это у вас не возникает никаких вопросов даже при виде элементарной конструкции:
foo = bar.boo(foo) + faz;
А новичок споткнется уже на том, что он даже не поймет, что такое присваивание в переменную, т.к. он будет эту конструкцию смотреть с точки зрения только имеющегося опыта. А единственное в его опыте, что хоть как-то похоже на конструкцию сверху — это математические уравнения.
И все. Баста. Обучение программированию вызывает проблемы уже с первых секунд.

Именно поэтому многословность (правильная многословность, а не brainfuck) первого языка — это не минус, а плюс.
Человек постигает новые знания через призму имеющегося опыта.
Он всегда будет искать аналогии, из-за чего будет натыкаться на проблемы, т.к. все аналогии будут некорректными.
Только достаточно талантливые люди в состоянии воспринимать новый опыт абстрагировано от старого.
Соответственно, после сломления барьера «прошлого опыта» новые знания в человека нужно впихивать разжеванными порциями, а не пихать в него списки и map-reduce'ы.
> Лекции, которые вы предоставили — это не «программирование с нуля».

Наглейшая ложь.

Prerequisites

Math 1A is a corequisite for 61A. (That is, it may be taken concurrently.)

There is no formal programming-related prerequisites for admission to 61A.


CS61, на который я дал ссылку, даётся в том числе людям, не имевшим никакого знакомства с программированием. Он сложен, но с ним справляются. На седьмом уроке там появляются типы, кстати.

Язык для обучения там, кстати, рекомендуют. Этот. Это — CS10, который проще.

Программирование — об абстракциях, а не многословности и типах вроде int/long.

И да, можете привести ссылку хоть на один серьёзный курс, использующий pascal как первый язык в 21 веке?
И да, можете привести ссылку хоть на один серьёзный курс, использующий pascal как первый язык в 21 веке?

Господи, вы на этот паскаль бросаетесь так, словно он у вас девушку увел.
Повторяю еще раз, Pascal — это мое личное мнение. Я не утверждаю, что он идеальный и современный, и признаю его недостатки.
Нет нужды пытаться убедить меня в том, что он старше нас с вами.

> Лекции, которые вы предоставили — это не «программирование с нуля».

Наглейшая ложь.

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

Большинство сегодняшних программистов в России, например, стали таковым «не благодаря, а вопреки» курсам программирования, то есть, имея предрасположенность к этому предмету, они сумели вырасти в хороших программистов, несмотря на далеко неидеальные программы обучения, которые давались на самом старте.
Соответственно, с приведенным вашим курсом такие люди бы получили еще более быстрый и качественный старт.

Язык для обучения там, кстати, рекомендуют. Этот. Это — CS10, который проще.

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

Программирование — об абстракциях, а не многословности и типах вроде int/long.

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

Сложно, объяснить человеку, который очень смутно представляет (если вообще представляет) что такое тип данных, что же не так с абсолютно валидным кодом типа «if (5 == someObject.getValue)» в котором забыли добавить скобки после вызова метода. А человеку, который знает, что сравнение числа с указателем на функцию (хорошо, в данном случае, с объектом класса «method») лишено смысла, всё просто объяснить.

Запись «for x in range(1, 5)», сложнее для понимания, чем обычный цикл с параметром в C-подобных языках. Просто наблюдение.

Ещё один интересный пример: можно попытаться объяснить что, как и почему надо делать, если мы вдруг захотим наследовать класс от двух классов, у которых разные метаклассы. Конечно тут вопрос не начального обучения, но всё-таки.
Учить программированию, начиная с C++ — это то же самое, что учить математике, начиная с интегралов, при том, что большинству ничего кроме дробей и умножения в столбик по жизни не понадобится.
Тут многие жалуются, что современное высшее образование оторвано от реальности, полученные студентами знания никому не нужны, выпускников по устройству на работу приходится обучать заново и т.п.
Так что рекомендую начинать с PHP — после первого же урока можно будет начать применять знания на практике и делать сайты недорого :)
Так что рекомендую начинать с PHP — после первого же урока можно будет начать применять знания на практике и делать сайты недорого :)

И продолжать подпитывать мифы о PHP-программистах :)
У правильного вуза с правильным учебным курсом основная задача — научить пониманию программирования. Как С++ тут поможет? С++ — это промышленный язык для профессиональной разработки, зачем с него надо начинать? Ваши «Почему же...» выглядят притянутыми за уши.

Вспоминаю студенческие годы, как одногрупники мучились с С++, причем программированию толком так и не научили, ни логически мыслить, ни концепциям, ни алгоритмам, не научили правильно писать программы, проектировать и выстраивать архитектуру. Научились те, кто хотел научиться, кто продрался через эти дебри. Остальные сдали свои кривые курсовики и забыли как страшный сон. А ведь всё могло быть совсем не так.
Этого мы уже не узнаем. Часто людей просто нужно заинтересовать, дать им понять, и у них загораются глаза.
С учетом того, что программирование нужно не всем, то обучение программированию на С++ — это дважды контрпродуктивно.
Те, кто хочет стать программистами, либо сами изучили базу, либо будут обучаться очень неэффективно.
А для тех, кому это не надо, будут просто мучиться очередным тупым предметом.

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

Вспоминаю студенческие годы, ...

Курсовой проект, насколько мне известно, редко бывает (если бывает) на первом курсе. Следовательно, до него явно было несколько специальных предметов, посвящённых обучению программированию. То, что одни не учили, а другие не хотели (не могли) учиться, проблема отнюдь не C++. Я почти уверен, что ваши одногрупники мучились бы так же и с другим языком или технологией.
Sign up to leave a comment.

Articles