Комментарии 63
Какая-то ностальгия меня настигла по старым временам — захотел чего-то узнать — взял книгу (толстую) умную и напихал в себя знаний, а сейчас прочитал статью на три листа и вроде как все знаешь. Скучно.
ЗЫ: Хотя откровенности ради нужно сказать, что в бытность школьником/студентом мне очень импонировало чьё-то изречение: «Где, те знания, которые потерялись в информации?»
ЗЫ: Хотя откровенности ради нужно сказать, что в бытность школьником/студентом мне очень импонировало чьё-то изречение: «Где, те знания, которые потерялись в информации?»
Это вводный курс, рассчитанный на людей, которые уже что-то знают, но знания которых почему-то не сложились в цельную картинку :)
Много деталей специально опущено, чтобы напомнить главное и побыстрее перейти к практике :)
Много деталей специально опущено, чтобы напомнить главное и побыстрее перейти к практике :)
«Я забыл больше, чем вы знали»
Зачем людям, у которых нет цельной картины, ломать сознание таким вот бредом дальше?
Давайте перейдём в предметную область: приведите список утверждений, которые вам кажутся бредовыми и не забудьте добавить обоснование этого чувства.
> Вся история развития ЯП — это история повышения сладости синтаксического сахара.
Бред номер 1. Ибо вы не понимаете, что такое синтаксический сахар и не отличаете его от семантики. Вот do в Haskell — это синтаксический сахар, потому что скрывает сложный синтаксис последовательного связывания действий в монаде. А for в Си — это никакой не синтаксический сахар. Это оператор, семантика которого может быть реализована множеством способов, и в некоторых случаях, совсем не так, как вам кажется.
Синтаксический сахар — это вообще, по определению, синтаксическая конструкция, которая заменяет собой другую синтаксическую конструкцию того же самого языка программирования. формализация циклов, сборка мусора, карринг, pi-исчисление — это ни разу не синтаксический сахар, а именно некое семантическое развитие языков программирование, под которое потом даже процессоры стали подстраивать.
Всё началось с машинно-зависимых языков — языков, учитывающий структуру и характеристики определённых компьютерных платформ. Те, кто программировал на калькуляторах помнят, как составлялись на них программы.
Бред номер 2. Если вы говорите о программировании вообще, то всё началось именно с машинно-независимых языков, например, языка программирования станков Жаккарда. Если вы говорите о языках программирования, то всё началось с великих и ужасных Fortran и Lisp, которые опять же не машинно зависимые. Если вы говорите о языках машинных инструкций… То с этого ничего не началось, это было где-то посрединке.
Десяток регистров, куда записывались результаты вычислений (где они, эти гигабайты оперативки?), пара регистров смещения (вспомните машину Тьюринга, да-да, регистры обозначали из какого регистра данных брать следующую команду!), и регистр команды, куда нужно было записать очередную операцию (прочитать значение, записать значение, сложить значение двух регистров памяти и т.д.).
Бред номер 3. Вы понятия не имеете, что такое машина Тьюринга, в которой просто по определению нет регистров.
Первой ласточкой стало использование стеков данных. Стек появился для решения задачи временного хранения произвольных данных. Конечно, данные можно сохранять и в регистре, однако в этом случае нужно помнить имя каждого регистра, данные из которого хочется получить.
Бред номер 4. Языки, в которых не использовался стек (тот же Fortran) появились гораздо раньше.
Ну и так далее. Буквально в каждом абзаце бред. У меня, к сожалению, нет времени, чтобы комментировать статью до конца, но я думаю, этих нескольких примеров публике будет достаточно, чтобы понять, что лучше с образовательными курсами вашей компании не связываться :) Успехов вам в чтении книжек. У Непейводы, кстати, неплохо этот материал изложен, можете ознакомиться.
Бред номер 1. Ибо вы не понимаете, что такое синтаксический сахар и не отличаете его от семантики. Вот do в Haskell — это синтаксический сахар, потому что скрывает сложный синтаксис последовательного связывания действий в монаде. А for в Си — это никакой не синтаксический сахар. Это оператор, семантика которого может быть реализована множеством способов, и в некоторых случаях, совсем не так, как вам кажется.
Синтаксический сахар — это вообще, по определению, синтаксическая конструкция, которая заменяет собой другую синтаксическую конструкцию того же самого языка программирования. формализация циклов, сборка мусора, карринг, pi-исчисление — это ни разу не синтаксический сахар, а именно некое семантическое развитие языков программирование, под которое потом даже процессоры стали подстраивать.
Всё началось с машинно-зависимых языков — языков, учитывающий структуру и характеристики определённых компьютерных платформ. Те, кто программировал на калькуляторах помнят, как составлялись на них программы.
Бред номер 2. Если вы говорите о программировании вообще, то всё началось именно с машинно-независимых языков, например, языка программирования станков Жаккарда. Если вы говорите о языках программирования, то всё началось с великих и ужасных Fortran и Lisp, которые опять же не машинно зависимые. Если вы говорите о языках машинных инструкций… То с этого ничего не началось, это было где-то посрединке.
Десяток регистров, куда записывались результаты вычислений (где они, эти гигабайты оперативки?), пара регистров смещения (вспомните машину Тьюринга, да-да, регистры обозначали из какого регистра данных брать следующую команду!), и регистр команды, куда нужно было записать очередную операцию (прочитать значение, записать значение, сложить значение двух регистров памяти и т.д.).
Бред номер 3. Вы понятия не имеете, что такое машина Тьюринга, в которой просто по определению нет регистров.
Первой ласточкой стало использование стеков данных. Стек появился для решения задачи временного хранения произвольных данных. Конечно, данные можно сохранять и в регистре, однако в этом случае нужно помнить имя каждого регистра, данные из которого хочется получить.
Бред номер 4. Языки, в которых не использовался стек (тот же Fortran) появились гораздо раньше.
Ну и так далее. Буквально в каждом абзаце бред. У меня, к сожалению, нет времени, чтобы комментировать статью до конца, но я думаю, этих нескольких примеров публике будет достаточно, чтобы понять, что лучше с образовательными курсами вашей компании не связываться :) Успехов вам в чтении книжек. У Непейводы, кстати, неплохо этот материал изложен, можете ознакомиться.
Синтаксический сахар — это вообще, по определению, синтаксическая конструкция, которая заменяет собой другую синтаксическую конструкцию того же самого языка программирования.
Окэй, а в тексте что написано? Невнимательность вас погубит:
«Синтаксический сахар — общее обозначение дополнений к синтаксису ЯП, которые делают использование языка более удобным, но не добавляют ему новых возможностей.»
В рамках этого добавление команд pop push в ассемблер являлось синтаксическим сахаром по отношению к этому языку. То, что эти команды в дальнейшем входят в синтаксический стандарт языка на суть не влияет. И так практически с каждой языковой фичей. Будете спорить? Тогда конкретный пример синтаксической конструкции, которую имеетязык высокого уровня и которая не появилась ранее в языках-предках, как сахар.
Если вы говорите о языках программирования, то всё началось с великих и ужасных Fortran и Lisp… Если вы говорите о языках машинных инструкций… То с этого ничего не началось, это было где-то посрединке.
Вам не стыдно нести этот бред? В каком году был изобретён фортран? В каком году — лисп? А в каком году был эниак для программирования которого была разработана таблица коммутации, фактически породившая регистровые языки?
Вы понятия не имеете, что такое машина Тьюринга, в которой просто по определению нет регистров.
Вы опять невнимательны.
Языки, в которых не использовался стек (тот же Fortran) появились гораздо раньше.
Если не сложно, напишите реализацию на ассемблере части синтаксиса фортрана:
CALL f(a,b...)
Мне очень интересно понаблюдать, как вы это сделаете без стека.
А, вообще, конечно, учите матчасть. Именно для того, чтобы в спорах старшим товарищам не было так сильно стыдно за младших, мы и читаем курсы молодым программистам.
1. А я не стал просто читать дальше. Но если это действительно про сахар написано ниже, то вы просто сами себе противоречите жёстко. Чем шизофренический текст лучше бредового?
2. pop и push — это инструкции процессора, и это не синтаксических сахар, это изменение семантики ассемблера, который теперь умеет генерировать новый код. Макроассемблер можно называть синтаксическим сахаром. Короче, опять у вас всё тут понамешано в кучу, и кони, и люди, и препроцессоры, и прочее.
3. Бредите вы, потому что вы говорите, в тексте: «Всё началось». Но история программирования началась совсем не с ЭВМ, а с ткацких и токарных станков, и произошло это в более дремучем году, чем вы думаете. Если вы говорите о языках программирования, не ассемблерах, которые не считались языками, а назывались автокодами, то их история началась с Fortran и Lisp. Ассемблеры — это нечто посрединке всего этого праздника программирования.
4. И почему я невнимателен? Я комментирую тот абзац, который вы в этом тексте написали. В котором прямо написано: вспомним машину Тьюринга, там регистры. Это даже не ересь, а именно бред.
5. А чего в этом сложного? Вы просто говорите, запись активации для функции f расположена по адресу FA. И пишете: mov a, FA[1]; mov b, FA[2]; mov ..., FA[X]. Стек, на самом деле, не вызовы и локальные перемнные позволяет организовывать, а рекурсию и прерывания. Именно в этом его важность.
6. И при чём тут ссылка на стековые языки? Forth и Fortran — это абсолютно разные языки.
2. pop и push — это инструкции процессора, и это не синтаксических сахар, это изменение семантики ассемблера, который теперь умеет генерировать новый код. Макроассемблер можно называть синтаксическим сахаром. Короче, опять у вас всё тут понамешано в кучу, и кони, и люди, и препроцессоры, и прочее.
3. Бредите вы, потому что вы говорите, в тексте: «Всё началось». Но история программирования началась совсем не с ЭВМ, а с ткацких и токарных станков, и произошло это в более дремучем году, чем вы думаете. Если вы говорите о языках программирования, не ассемблерах, которые не считались языками, а назывались автокодами, то их история началась с Fortran и Lisp. Ассемблеры — это нечто посрединке всего этого праздника программирования.
4. И почему я невнимателен? Я комментирую тот абзац, который вы в этом тексте написали. В котором прямо написано: вспомним машину Тьюринга, там регистры. Это даже не ересь, а именно бред.
5. А чего в этом сложного? Вы просто говорите, запись активации для функции f расположена по адресу FA. И пишете: mov a, FA[1]; mov b, FA[2]; mov ..., FA[X]. Стек, на самом деле, не вызовы и локальные перемнные позволяет организовывать, а рекурсию и прерывания. Именно в этом его важность.
6. И при чём тут ссылка на стековые языки? Forth и Fortran — это абсолютно разные языки.
pop и push — это инструкции процессора, и это не синтаксических сахар, это изменение семантики ассемблера, который теперь умеет генерировать новый код
pop и push далеко не сразу стали инструкциями процессора, если вы посмотрите на первые машины в архитектуре фон Неймана, то там были регистры, была адресация памяти, но не было стеков. Pop и push появились, как инструкции процессоров в ответ на развитие языковых запросов программистов.
Бредите вы, потому что вы говорите, в тексте: «Всё началось».
Ок, ок — были машины и до Z3, были аналоговые компьютеры, не было разделения памяти и вычислений. В архитектуре фон Неймана всё началось с регистровых языков — такая формулировка вас устроит?
Если вы говорите о языках программирования, не ассемблерах, которые не считались языками, а назывались автокодами, то их история началась с Fortran и Lisp. Ассемблеры — это нечто посрединке всего этого праздника программирования.
Если не сложно, дайте, пожалуйста ссылку, что ассемблеры начались позже. По моим данным, фортран возник в 1954-57 годах как первый практический язык высокого уровня. Разработал язык IBM, он же и выпустил первый компилятор языка в машинные коды.
В котором прямо написано: вспомним машину Тьюринга, там регистры.
Тут я действительно не понимаю вашего возмущения. Регистр — последовательное логическое устройство, используемое для хранения символов и выполнения преобразований над ними. Частным случаем реализацией регистра можно считать ячейку ленты МТ в купе с записывающей головкой. Что не так?
И пишете: mov a, FA[1]; mov b, FA[2]; mov ..., FA[X].
Угу, а возврат из подпрограммы как реализуете? К вопросу о рекурсии, кстати, ага.
И при чём тут ссылка на стековые языки?
Стековый язык — это любой язык, использующий стеки для передачи данных в подпрограммы и возврата из них значений.
pop и push далеко не сразу стали инструкциями процессора, если вы посмотрите на первые машины в архитектуре фон Неймана, то там были регистры, была адресация памяти, но не было стеков. Pop и push появились, как инструкции процессоров в ответ на развитие языковых запросов программистов.
Ну и вот. На этот раз вы правы. Но как теперь это соотносится с тем, что вся история ЯП — это синтаксический сахар?
Ок, ок — были машины и до Z3, были аналоговые компьютеры, не было разделения памяти и вычислений. В архитектуре фон Неймана всё началось с регистровых языков — такая формулировка вас устроит?
А что такое регистровый язык? Нам на сольфеджио про такой рассказывали, а на лекциях по компьютерным наукам — нет :)
Если не сложно, дайте, пожалуйста ссылку, что ассемблеры начались позже. По моим данным, фортран возник в 1954-57 годах как первый практический язык высокого уровня. Разработал язык IBM, он же и выпустил первый компилятор языка в машинные коды.
Так вот именно что в машинные коды. Первый транслятор Fortran пробивал дырочки на перфокартах, и был написан путём пробивания дырочек. Там не было ассемблера. Когда появился первый ассемблер точно я не знаю, но вот Fortran и Ассемблеры долго считались конкурирующими подходами к программированию, пока транслятор фотран не уделал какой-то вручную написанный код по скорости выполнения программы. То есть, неверно считать, что Fortran стал развитием какого-то ассемблера.
Тут я действительно не понимаю вашего возмущения. Регистр — последовательное логическое устройство, используемое для хранения символов и выполнения преобразований над ними. Частным случаем реализацией регистра можно считать ячейку ленты МТ в купе с записывающей головкой. Что не так?
Нет. Главное свойство регистра не то, что оно используется для хранения и обработки (перфокарта, или там магнитная лента, тоже могут использоваться), а то, что у него есть номер (или идентификатор), по которому к нему можно получить доступ (ну, мы о программировании говорим, для программирования это именно так, см. машину Минского). У ячеек машины Тьюринга нет номеров (и их даже очень-очень непросто присвоить), поэтому они не являются регистрами.
Угу, а возврат из подпрограммы как реализуете? К вопросу о рекурсии, кстати, ага.
mov RETHERE, FA[0]; RETHERE:
f: ...; jmp FA[0];
Проблема рекурсии не в возврате, а в том, что функция может быть вызвана повторно.
Стековый язык — это любой язык, использующий стеки для передачи данных в подпрограммы и возврата из них значений.
Не правда. Стековый язык — это язык, в котором каждый оператор операнды берёт из стека. Вызовы функций на них, действительно, очень просто описывать. Но существуют языки, которые не используют стеки для этого. Например, Haskell. Или, допустим, JavaScript. Они напрямую оперируют записями активации, динамически их выделяют и т.д.
Ну и вот. На этот раз вы правы. Но как теперь это соотносится с тем, что вся история ЯП — это синтаксический сахар?
Ок, ок — были машины и до Z3, были аналоговые компьютеры, не было разделения памяти и вычислений. В архитектуре фон Неймана всё началось с регистровых языков — такая формулировка вас устроит?
А что такое регистровый язык? Нам на сольфеджио про такой рассказывали, а на лекциях по компьютерным наукам — нет :)
Если не сложно, дайте, пожалуйста ссылку, что ассемблеры начались позже. По моим данным, фортран возник в 1954-57 годах как первый практический язык высокого уровня. Разработал язык IBM, он же и выпустил первый компилятор языка в машинные коды.
Так вот именно что в машинные коды. Первый транслятор Fortran пробивал дырочки на перфокартах, и был написан путём пробивания дырочек. Там не было ассемблера. Когда появился первый ассемблер точно я не знаю, но вот Fortran и Ассемблеры долго считались конкурирующими подходами к программированию, пока транслятор фотран не уделал какой-то вручную написанный код по скорости выполнения программы. То есть, неверно считать, что Fortran стал развитием какого-то ассемблера.
Тут я действительно не понимаю вашего возмущения. Регистр — последовательное логическое устройство, используемое для хранения символов и выполнения преобразований над ними. Частным случаем реализацией регистра можно считать ячейку ленты МТ в купе с записывающей головкой. Что не так?
Нет. Главное свойство регистра не то, что оно используется для хранения и обработки (перфокарта, или там магнитная лента, тоже могут использоваться), а то, что у него есть номер (или идентификатор), по которому к нему можно получить доступ (ну, мы о программировании говорим, для программирования это именно так, см. машину Минского). У ячеек машины Тьюринга нет номеров (и их даже очень-очень непросто присвоить), поэтому они не являются регистрами.
Угу, а возврат из подпрограммы как реализуете? К вопросу о рекурсии, кстати, ага.
mov RETHERE, FA[0]; RETHERE:
f: ...; jmp FA[0];
Проблема рекурсии не в возврате, а в том, что функция может быть вызвана повторно.
Стековый язык — это любой язык, использующий стеки для передачи данных в подпрограммы и возврата из них значений.
Не правда. Стековый язык — это язык, в котором каждый оператор операнды берёт из стека. Вызовы функций на них, действительно, очень просто описывать. Но существуют языки, которые не используют стеки для этого. Например, Haskell. Или, допустим, JavaScript. Они напрямую оперируют записями активации, динамически их выделяют и т.д.
Но как теперь это соотносится с тем, что вся история ЯП — это синтаксический сахар?
Ну это же элементарно! Вначале фича появляется, как синтаксический сахар в языке, потом она реализуется как синтаксическая особенность языка более позднего поколения.
А что такое регистровый язык?
Язык регистровых машин
Когда появился первый ассемблер точно я не знаю, но вот Fortran и Ассемблеры долго считались конкурирующими подходами к программированию, пока транслятор фотран не уделал какой-то вручную написанный код по скорости выполнения программы.
en.wikipedia.org/wiki/Assembly_language#Historical_perspective
en.wikipedia.org/wiki/FORTRAN_Assembly_Program#FORTRAN_assembly_program
ну и так далее.
Главное свойство регистра не то, что оно используется для хранения и обработки (перфокарта, или там магнитная лента, тоже могут использоваться), а то, что у него есть номер (или идентификатор), по которому к нему можно получить доступ
Собственно, а можно ссылку на определение, где явно указывается, что регистр должен быть именованным? И чем вам не нравится адресация по смещению от текущего положения в МТ?
mov RETHERE, FA[0]; RETHERE:
f: ...; jmp FA[0];
Ага, а теперь цепочку CALL с возвратом управления к вызывающему операнду. Собственно, к вопросу о стековом языке.
Как по мне стековый язык — язык в спецификации которого явно упомянут стек для передачи данных и/или управления (в том же FORTH явно описано два отдельных стека — данных и вызовов). Если же просто предъявляются требования для передачи, но механизм их не описан, то язык стековым не будет, даже если использование стека, пускай даже программного, а не аппаратного (микропрограммного) будет наиболее очевидным и эффективным решением. Другими словами, если описано в, например, описании процесса вызова подпрограммы, что как минимум адрес возврата сохраняется именно в стек, то язык стековый, если же описано что он сохраняется где-то и как-то так, чтобы подпрограмма могла вернуть управление, но где и как неспецифицировано, то язык не стековый, несмотря на то, что все его реализации используют именно стек, чаще всего аппаратный.
Вызов функции без стека, в Фортране? Давайте. Предположим, что у нас процессор вообще без стека. Скажем, PDP 11/70, из которого убрали команды JSR и RTS.
1) Не забываем, что в Фортране рекурсии нет. Поэтому у каждой функции может быть контекст, который никто не испортит.
2) Все аргументы передаются по ссылке. У всех переменных есть адрес. Для каждого вызова функции задается табличка с адресами всех аргументов (да еще и с их числом). Как правило, статическая. В редких случаях (повторная передача параметров) ее приходится менять. Функции передаем только адрес таблички. В регистре R5.
3) Из функции надо будет куда-то возвращаться. Раз стека нет, положим адрес возврата в регистр R6.
Поехали.
Вызывающая функция:
Теперь функция F (к сожалению, не помню точно, как ее оформлять на Фортране):
PROCEDURE F(IA,IB)
IA=IA+IB
END
Как-то так. Возможно, повторная передача параметра велась как-то по-другому. Если ошибки в коде — не судите строго, в последний раз я писал на нем (и на Фортране) 25 лет назад, мог что-нибудь забыть.
1) Не забываем, что в Фортране рекурсии нет. Поэтому у каждой функции может быть контекст, который никто не испортит.
2) Все аргументы передаются по ссылке. У всех переменных есть адрес. Для каждого вызова функции задается табличка с адресами всех аргументов (да еще и с их числом). Как правило, статическая. В редких случаях (повторная передача параметров) ее приходится менять. Функции передаем только адрес таблички. В регистре R5.
3) Из функции надо будет куда-то возвращаться. Раз стека нет, положим адрес возврата в регистр R6.
Поехали.
Вызывающая функция:
;;; локальные переменные
H1$A: .WORD 0
H1$B: .WORD 0
;;; табличка вызова
H1$CALL1: .WORD 2,H1$A,H1$B
;;; место для адреса возврата и для таблички параметров
H1$PARAM: .WORD 0
H1$RET: .WORD 0
;;; сама функция H1:
H1:
MOV R5,H1$PARAM ;;; сохранили блок вызова
MOV R6,H1$RET ;;; сохранили адрес возврата
.... ;;; что-то делаем
;;; собираемся вызвать функцию
MOV #H1$CALL1 ,R5
MOV #H1$CALL1$RET,R6
JMP F
H1$RET:
MOV H1$PARAM,R5
.... ;;; делаем что-то еще
JMP @H1$RET ;;; возвращаемся из функции H1
Теперь функция F (к сожалению, не помню точно, как ее оформлять на Фортране):
PROCEDURE F(IA,IB)
IA=IA+IB
END
;;; блок описывать не будем, предположим, что компилятор его соптимизировал
F:
ADD @4(R5),@2(R5) ;;; двойная адресация (обращение к ячейке, адрес которой лежит в (R5+4))
JMP (R6) ;;; прыжок по адресу, лежащему в R6.
Как-то так. Возможно, повторная передача параметра велась как-то по-другому. Если ошибки в коде — не судите строго, в последний раз я писал на нем (и на Фортране) 25 лет назад, мог что-нибудь забыть.
Ага, уели. Я искренне считал фортран стековым, теперь вижу, что это не так. Добавлю в статью этот факт.
Как молоды мы были, как молоды мы были…
какое-то противопоставление мастеров-на-все-руки жавщиков и недотёп пхпшников. В наше время уважающий себя жавщие понятия не имеет чем GET отличается от POST и на каждый чих молотит мегабайты ненужного кода с конфигами. Такчт противопостовление неверное. Они друг друга стоят.
— чистый полиморфизм (полиморфизм по сигнатуре)
— параметрический полиморфизм (полиморфизм по имени метода)
Поясните, пожалуйста, что значит в вашем случае «по сигнатуре» и «по имени метода»?
— переопределение (абстрагирование, абстрактные классы)
И как же именно метод ПЕРЕопределяется (override?) в случае абстрактного класса?
— перегрузка (неполное замещение метода предка методом потомка)
Неполное это как? В C++, например, перегрузкой (overloading) называется род полиморфизма, ни коим образом не связанный с наличием потомков.
Чистый полиморфизм — это когда когда одна и та же функция выполняется к произвольному списку параметров. В случае чистого полиморфизма есть одна функция (тело кода) и несколько ее интерпретаций.
Другой случай — это когда имеется множество различных методов с одним именем, но разным списком параметров (с разными сигнатурами методов). Собственно, это и называется перегрузкой или полиморфизмом ad hoc. Между этими двумя крайностями лежат переопределяемые методы. А абстрактные классы тут не при чём — они только задают API :)
Другой случай — это когда имеется множество различных методов с одним именем, но разным списком параметров (с разными сигнатурами методов). Собственно, это и называется перегрузкой или полиморфизмом ad hoc. Между этими двумя крайностями лежат переопределяемые методы. А абстрактные классы тут не при чём — они только задают API :)
Грубо говоря разница лишь в том, что считать сигнатурой функции?
Термины, в которых описывается условие match. Используются там типы, или свойства типов, или в предикате фигурируют сами значения. Может быть, в языке вообще типов нет, а есть только void*, или list, или аморфная структура со списком методов…
Но еще вопрос — на каком этапе возможно разрешение полиморфизма — компиляция, или только выполнение.
Но еще вопрос — на каком этапе возможно разрешение полиморфизма — компиляция, или только выполнение.
А заголовок как я понимаю просто для завлечения?
Вы считаете, что это не база? Что же тогда является базой для вас — может быть, структуры данных? Но они появились позже. Может быть, теорию конечных автоматов? Но и они не являются базой по языкам программирования.
Нет, я считаю, что термин «синтаксический сахар» в заголовке для завлечения.
То есть вы утверждаете, что в языках высокого уровня присутствует некие уникальные возможности, нереализуемые с помощью машинных кодов? Или вы утверждаете, что синтаксический сахар не приводит к повышению уровня абстракции и, как следствие, повышению уровня языка?
Да, существуют. Потому что некоторые языки можно компилировать прямо в цифровые схемы, которые не выполняют ни одной машинной инструкции. Ещё раз, вы в одну кучу мешаете синтаксис, семантику и прагматику. Это совершенно разные вещи, мало друг от друга зависят. К повышению уровня абстракции приводит не синтаксический сахар, а семантика языка. Вот в LISP никакого сахара нет, и синтаксис дубовый, однако абстракции в нём можно задрать хоть до уровня почти полноценного AI.
Ответьте, пожалуйста, что такое уровень языка и что такое высокоуровневые языки.
В смысле? Я ничего не говорил об уровне языка. Или это вы экзаменационный вопрос задаёте? Писать лень, вполне согласен с тем, что Википедия по этому поводу думает: ru.wikipedia.org/wiki/Высокоуровневый_язык_программирования
В моём комментарии написано ровно одна тема: «заголовок для завлечения». Это значит, что я не увидел в статье ничего про «синтаксический сахар».
>Вся история развития ЯП — это история повышения сладости синтаксического сахара.
Угу, а интеллект — это просто очень сложный инстинкт :)
Угу, а интеллект — это просто очень сложный инстинкт :)
Непонятно, почему про Тьюринга и Неймана вы написали, а про лямбда-исчисление — нет, коль уж речь и о ФП завели.
Кстати, да. Недоработка, в следующую редакцию обязательно внесу дополнение.
Closure у вас чуть-ли не главное что есть в функциональном програмировании. Думаю этот раздел требует существенной переработки.
Как появилось ООП, лучшего введения чем у Uncle Bob я не видел:
skillsmatter.com/podcast/agile-scrum/uncle-bob-expert-insights
Как появилось ООП, лучшего введения чем у Uncle Bob я не видел:
skillsmatter.com/podcast/agile-scrum/uncle-bob-expert-insights
Статья пригодна для детского сада, не для IT-ресурса. Все комментарии о бредовости некоторых высказываний выше совершенно верны, если учитывать аудиторию, ведь как бы детям на вопрос «почему солнце светит?» не обьясняете принципы протекания ядерных реакций распада, так и айтишникам не надо выдавать тематическую статью, предназначенную, по всей видимости, чтобы заинтересовать школьников младших классов. Ну максимум средних.
Прочитал статью (и предыдущие две) и осталось неприятное впечатление, что автор считает развитие ЯП да и их самих вредным и ненужным. А ведь наверняка на работе не нолики/единички на реле отстукивает, а пользуется именно развитыми ЯП и тем, что на них написано.
Извините, а откуда появилось такое ощущение? Вроде бы я нигде не утверждал, что программирование на высокоуровневых языках — это плохо. Скорее даже наоборот — это позволяет писать код быстрее.
У меня такое чувство тоже появилось. Хотя бы после такого:
Ассемблер так же привязан к архитектуре машины (поскольку его команды повторяют команды процессора), но шаг в пропасть был уже сделан и языки начинали всё больше и больше обрастать кристаллами сахара.
> Класс — прикольная штука
прочитал: «Класс — прикольная шУТка» =)
прочитал: «Класс — прикольная шУТка» =)
«Вся история развития ЯП — это история повышения сладости синтаксического сахара.»
Это, как мне кажется, грубоватая аналогия. Сахар подразумевает, что язык остается тем же, но к нему добавляются альтернативные варианты записи.
У каждого типа машины — свой машинный код (машинный язык), который к ней намертво привязан. Тут вы даже могли бы продолжить свою аналогию о развитии синтаксического сахара в машинных языках.
Так что же тогда получается, С — это одновременно несколько машинных языков?
Тем не менее, сахар — во многом условное определение.
Это, как мне кажется, грубоватая аналогия. Сахар подразумевает, что язык остается тем же, но к нему добавляются альтернативные варианты записи.
У каждого типа машины — свой машинный код (машинный язык), который к ней намертво привязан. Тут вы даже могли бы продолжить свою аналогию о развитии синтаксического сахара в машинных языках.
Так что же тогда получается, С — это одновременно несколько машинных языков?
Тем не менее, сахар — во многом условное определение.
Добавлю и от себя немножко критики:
Вообще разделение на знаковые и беззнаковые было уже в ассемблере (imul, ja/jg). Да и называть их стоило бы в более привычном для «того времени» формате: byte, word, dword, qword, etc. Это хоть гарантирует понимание размера.
Не во всех ЯП true/false приводятся к 0 и 1. Например, в VB они описываются как «False becomes 0 and True becomes -1». Т.е. тут лучше говорить о нуле и не нуле (побитовом НЕ).
Стек также повсеместно используется для произвольного доступа, если мы знаем адрес текущей вершины стека (в нем удобно складывать как раз те самые локальные переменные). Собственно, пролог push ebp; mov ebp, esp; sub esp, N и эпилог ret N функций это и реализуют.
Еще неплохо было бы написать, что массив — это монотонная последовательность ОДНОТИПНЫХ данных, а не просто «склеенные ячейки».
OMG. Это ж уже не массивы, а списки. И null тут можно вытянуть из указателей, но не как обозначение пустой ячейки. Для обозначения пустой ячейки именно в массивах можно было бы добавлять к каждому элементу массива поле «свободно/не задано».
Иногда эти типы могут иметь одинаковый размер, не так ли? Тут бы лучше пример вида записи float для массива byte.
Опять узкий сишный взгляд. Так придумали в погоне за экономией памяти в ущерб скорости работы программы. И так и тащится это «наследие» в некоторых ЯП. В других умно и правильно через хранение длины строки рядом. А еще правильнее (вроде даже в WinAPI есть их поддержка) хранить буфер под строку, и счетчики сколько байт занято и сколько доступно.
Больше лулзов можно получить, если забыть терминальный null :)
Да, косвенная адресация. Появилась явно раньше функций. Но за «ярлычок» и «блочок» ловите + :)
Я что же, не могу передать структуру/массив в функцию по значению? У нас же есть стек.
Про type в pascal бы тоже написали сразу, раз выше вспомнили о таком ЯП. Причем в нем еще и есть полноценная реализация областей описания и реализации, в отличие от C.
В C/C++ с этим как раз боролись, объявляя функции работы прямо в структурах. Вполне себе вариант. В прототипном JS с этим вообще все шоколадно.
Но тут нет рекурсии. У нас есть яблоко и мальчик Вова, который умеет есть яблоки — где тут рекурсия? Тут только инкапсуляция :)
Ну тут скорее взяли количеством, а не качеством.
В целом как-то все наивно, узко и, в общем-то, во многом и не о синтаксическом сахаре, а о причинах, почему C++ выглядит именно так, а не иначе. Многое вообще никакого отношения к синтаксису не имеет.
Стоило бы пойти дальше, к значительно более сладким языкам.
Так появляются целочисленные типы данных без возможности указать являются ли они отрицательным или нет (byte, unsigned integer, unsigned long integer и т.д.)
Вообще разделение на знаковые и беззнаковые было уже в ассемблере (imul, ja/jg). Да и называть их стоило бы в более привычном для «того времени» формате: byte, word, dword, qword, etc. Это хоть гарантирует понимание размера.
тип boolean с двумя значениями true и false (за которыми, в прочем, стояли те же единичка и нолик)
Не во всех ЯП true/false приводятся к 0 и 1. Например, в VB они описываются как «False becomes 0 and True becomes -1». Т.е. тут лучше говорить о нуле и не нуле (побитовом НЕ).
Массив данных кардинально отличался от стека возможностью свободного доступа не только к последнему засунутому элементу, а вообще к любому по номеру
Стек также повсеместно используется для произвольного доступа, если мы знаем адрес текущей вершины стека (в нем удобно складывать как раз те самые локальные переменные). Собственно, пролог push ebp; mov ebp, esp; sub esp, N и эпилог ret N функций это и реализуют.
Еще неплохо было бы написать, что массив — это монотонная последовательность ОДНОТИПНЫХ данных, а не просто «склеенные ячейки».
Но, ведь, ячейки не обязательно бывают заполненными? Так потребовалось обозначение пустой ячейки и возникает тип null
OMG. Это ж уже не массивы, а списки. И null тут можно вытянуть из указателей, но не как обозначение пустой ячейки. Для обозначения пустой ячейки именно в массивах можно было бы добавлять к каждому элементу массива поле «свободно/не задано».
И не дай Ричи тебе записать в массив типа int элемент вида long!
Иногда эти типы могут иметь одинаковый размер, не так ли? Тут бы лучше пример вида записи float для массива byte.
Дабы справиться со строками переменной длины, придумали помечать null-маркером конец строки.
Опять узкий сишный взгляд. Так придумали в погоне за экономией памяти в ущерб скорости работы программы. И так и тащится это «наследие» в некоторых ЯП. В других умно и правильно через хранение длины строки рядом. А еще правильнее (вроде даже в WinAPI есть их поддержка) хранить буфер под строку, и счетчики сколько байт занято и сколько доступно.
ничто не мешало добавить в середину строки null и поиметь с этого кучу лулзов
Больше лулзов можно получить, если забыть терминальный null :)
Ссылка представляет из себя ярлычок (link) на какую-то переменную, под которую выделен блочок памяти.
Да, косвенная адресация. Появилась явно раньше функций. Но за «ярлычок» и «блочок» ловите + :)
Но не тут то было: передача переменных по ссылке дало уникальную возможность конструировать из простых типов данных целые конструкции — структуры данных!
Я что же, не могу передать структуру/массив в функцию по значению? У нас же есть стек.
1. в них есть формальный язык описания структур данных (*.h файлы в C)
Про type в pascal бы тоже написали сразу, раз выше вспомнили о таком ЯП. Причем в нем еще и есть полноценная реализация областей описания и реализации, в отличие от C.
Возможность создавать свои собственные типы данных возбуждает в программистах страстное желание внутри этого типа данных иметь функции для работы с ним.
В C/C++ с этим как раз боролись, объявляя функции работы прямо в структурах. Вполне себе вариант. В прототипном JS с этим вообще все шоколадно.
инкапсуляция, которую определяют как свойство объекта объединять в себе данные и методы работы с этими данными. Философы вообще любят рекурсивные определения.
Но тут нет рекурсии. У нас есть яблоко и мальчик Вова, который умеет есть яблоки — где тут рекурсия? Тут только инкапсуляция :)
Но класс-ориентированное программирование оказалось более удобным для описания API и фреймворков [...], по этому стало более распространённым.
Ну тут скорее взяли количеством, а не качеством.
В целом как-то все наивно, узко и, в общем-то, во многом и не о синтаксическом сахаре, а о причинах, почему C++ выглядит именно так, а не иначе. Многое вообще никакого отношения к синтаксису не имеет.
Стоило бы пойти дальше, к значительно более сладким языкам.
Спасибо, учту ваши комментарии в следующей редакции лекции :)
Насчёт узости — задача такая: быстро напомнить джуниорам откуда вообще пошли языки и что стоит за ООП и языками, на которых они пишут (у нас пишут на Java и PHP).
Рассказывать системно и последовательно про историю программирования — это явно более 2х часов времени.
Следующие курсы — это уже тактика и стратегия написания промышленного кода. Максимум практики, минимум теории.
Насчёт узости — задача такая: быстро напомнить джуниорам откуда вообще пошли языки и что стоит за ООП и языками, на которых они пишут (у нас пишут на Java и PHP).
Рассказывать системно и последовательно про историю программирования — это явно более 2х часов времени.
Следующие курсы — это уже тактика и стратегия написания промышленного кода. Максимум практики, минимум теории.
Какой может быть промышленный код после такой «статьи», или как вы изволите ее называть «лекции»? И вообще, что значит «промышленный код»? и «промышленное программирование»?
Лекция — потому что это — сабскрипт того, что я рассказываю устно. Промышленное программирование — это противоположность программированию спортивному. Промышленное программирование — это вид прикладного программирования, результатом которого являются системы эксплуатируемые в реальном бизнесе. Отличительными особенностями промышленного программирования являются реализация бизнес-требований в согласованные сроки и долгая поддержка сданной в эксплуатацию системы.
Признайтесь, вы сами придумали это понятие?
В официальных документах встречаются термин «индустриальное производство программного обеспечения». Думаю можно считать синонимами.
Какой-то несвязный набор слов.
www.4tivo.com/coders/24845-java.-promyshlennoe-programmirovanie.html
Еще студентом ходил на курсы этого Блинова, печаль печальная… А в этой книге он научит Вас промышленному программированию, ага…
Судя по описанию — обычное программирование за деньги в обычной конторе.
Еще студентом ходил на курсы этого Блинова, печаль печальная… А в этой книге он научит Вас промышленному программированию, ага…
Судя по описанию — обычное программирование за деньги в обычной конторе.
Вот-вот, я тоже искал в интернете и единственный источник, который я нашел по «промышленному программированию» эта сомнительная книга.
www.google.ru/search?client=opera&rls=ru&q=Industrial+programming&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest#sclient=psy-ab&hl=ru&newwindow=1&client=opera&hs=HEx&rls=ru&channel=suggest&q=industrial+programming+CS&oq=industrial+programming+CS&gs_l=serp.3...3545.6524.3.7055.3.3.0.0.0.0.204.373.1j1j1.3.0...0.0...1c.mpG1pfvZVP0&pbx=1&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=3472d2e5c0204a32&biw=1271&bih=685
cs-tusofia.eu/cscience/index.php?option=com_content&view=article&id=232:industrial-programming&catid=54:semester-iii&Itemid=68
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
База по языкам программирования: Синтаксический сахар или история развития языков