Архив автора

Bash как mainstream-язык

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

Теория крючков

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

  1. На младших курсах все студенты изучают математический анализ. Это очень непростой для неокрепших умов предмет, и самое непростое в нем то, что когда его изучаешь, ты абсолютно не понимаешь, зачем все это нужно. Понять доказательство теоремы Вейерштрасса или разложение в ряд Тейлора в принципе можно, но должно пройти немало времени, прежде чем может быть у кого-то возникнет дежа вю — «Кажется, что-то такое я учил на первом курсе… Но уже нифига не помню». Хуже всего, если эти знания действительно нужны, и приходится открывать учебники и учиться заново. Во второй раз изучать получается быстрее, но все равно время жалко.
  2. На младших курсах многие студенты изучают еще и разнообразную физику. Это вообще труба, потому что используемый в лекциях матаппарат студенты еще не проходили. В результате физику никто не знает, а когда приходит время изучать тот матаппарат, то параллели провести тоже не получается — едва ли кто-то воскликнет «Так вот что, оказывается, имел в виду наш физик год назад, когда говорил о линейных операторах!».

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

Мне придумалась образное объяснение, почему так происходит — теория крючков. Она состоит из следующих постулатов:

  1. Поглощаемые человеком знания ищут в мозгу крючки, за которые могут зацепиться. Чем больше таких крючков, за которые зацепилось некоторое знание, тем дольше оно останется в мозгу.
  2. Крючки типизированные: определенным знаниям нужны определенные крючки. Нельзя зацепить знания о языке Фортран за крючки, относящиеся к плаванию кролем.
  3. Хотя некоторые уникумы умудряются нарушать типизацию крючков, проводя смелые аналогии в различных областях знаний.
  4. Закрепленные в мозгу новые знания сами начинают создавать крючки. Больше знаний — больше крючков — проще усваиваются новые знания.

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

  • Когда знаешь много языков программирования (или иностранных языков), изучить еще один — гораздо более простая задача, чем изучить первый. Новый язык цепляется за множество крючков, выращенных уже изученными языками.
  • Система крючков гуманитария кардинально отличается от оной у технаря. Поэтому технические понятия гуманитарии воспринимают с трудом — крючки не подходят!
  • Проводить аналогии между программированием и постройкой домов, литературой, живописью, вышиванием крестиком или выращиванием цветов — нарушение типизации крючков. Но кто сказал, что это плохо?
  • Теория, пересыпанная примерами, изучается куда проще, чем сначала куча теории, а потом куча примеров. Поглощая знания маленькими кусочками, мы цепляем их друг к другу, не давая им успеть забыться. С большими кусками сложнее. Это все равно как есть очень длинную колбасу — пока доедаешь ее конец, начало уже давно переварилось и путешествует по канализации.
  • В этом посте неимоверное, зашкаливающее количество употреблений слова «крючок».

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

УжасноПлохоНормальноХорошоОтлично (4 голосов, средний: 4,75 из 5)
Loading ... Loading ...

Определить, поддерживает ли компилятор C вложенные комментарии

Такая вот классическая задача, которая которую я когда-то увидел в книжке «C Traps and Pitfalls». Для современных компиляторов ответ однозначен: вложенные комментарии вида /*…/*…*/…*/ не поддерживаются, см. п. 6.4.9-1 стандарта C99. Но во времена динозавров, говорят, некоторые компиляторы все-таки поддерживали. Собственно, задача формулируется так:

Написать программу на C, компилирующуюся без ошибок (warning-и не в счет), которая при запуске выводит «YES», если вложенные комментарии поддерживаются, и «NO», если это не так.

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

/* всегда в комментарии /* всегда в комментарии */ какой-то-код */

Если вложенность поддерживается, какой-то-код — всего лишь часть комментария. Но если вложенности нет, то комментарий кончается на первом же «*/», а какой-то-код будет выполнен. Проблема только в одном: что делать с остающимися в хвосте «*/»? Наверное, нужно где-то раньше поместить парные «/*», но тогда код станет некорректным в случае, если вложенность поддерживается. Нетрудно видеть, что написание комментариев с еще большей глубиной вложенности лишь усугубляет проблему.

(Здесь самое время прекратить читать и попытаться придумать решение самостоятельно.)

Ключ к решению — различная лексическая трактовка символов в зависимости от контекста. Я придумал три способа:

  1. Использовать двойные кавычки. Символы между парными кавычками становятся частью строкового литерала. Конечно, придется использовать два набора вложенных комментариев.
  2. Использовать символ «*», в зависимости от ситуации, как оператор разыменования или оператор умножения. Опять нужно два набора комментариев.
  3. Поглотить «*/», сделав эту строку содержимым символа препроцессора. Здесь нужно также вспомнить, что комментарии обрабатываются препроцессором до обработки макродиректив.

Код выглядит немного странно, но разобраться несложно:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// file: nestcomm.c?
#include <stdio.h>
void method1(){
    printf("Method 1: ");
    printf("%s\n", /*/**/"  NO\0*/"/*YES\0"/**/"*/"+2);
}
void method2(){
    int a = 1;
    printf("Method 2: ");
    printf("%s\n", /*/**/2*/*(&a)+/**/2==4?"NO":"YES");
}
void method3(){
    printf("Method 3: ");
    /*/**/#define A */
    printf("%s\n",
           #ifdef A
               "NO"
           #else
               "YES"
           #endif
            );
}
int main(){
    method1();
    method2();
    method3();
    return 0;
}

Компилятор с поддержкой вложенных комментариев уже не найдешь, но можно его сымитировать, написав на flex небольшой препроцессор:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  // file: snc.lex
%option noyywrap
%{
int comm = 0;
%}
%x STRING COMMENT
%%
<INITIAL>{
    \"         { BEGIN(STRING); ECHO; }
    "/*"       { comm++; BEGIN(COMMENT); }
    .          { ECHO; }
}
<COMMENT>{
    "/*"   { comm++; }
    .      { }
    "*/"   { comm--; if (!comm) BEGIN(INITIAL); }
}
<STRING>{
    \"     { BEGIN(INITIAL); ECHO; }
    .      { ECHO; }
}
%%
int main()
{
    yylex();
    return 0;
}

Ну, и чтобы два раза не вставать, Makefile для автоматического прогона:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.PHONY: all
all: nest_yes nest_no
	@echo "With nested comments support:"
	./nest_yes
	@echo "Without nested comments support:"
	./nest_no
 
nest_yes: nestcomm.c snc
	./snc < $< > tmp.c
	cc -o $@ tmp.c
	rm -f tmp.c
 
snc: snc.lex	
	flex -o $(subst .lex,.c,$<) $<
	cc -o $@ $(subst .lex,.c,$<)
 
nest_no: nestcomm.c
	cc -o $@ $<
 
.PHONY: clean
clean:
	rm -f snc.c snc nest_yes nest_no

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

УжасноПлохоНормальноХорошоОтлично (2 голосов, средний: 4,50 из 5)
Loading ... Loading ...

Удивительное рядом

Уличил сам себя в бессовестном разбазаривании вычислительных ресурсов. У меня запущен urxvt, в котором запущен tmux, в котором через ssh запущен screen, в котором запущен minicom, в котором видна консоль суровой отечественной железки. Остается только запустить это все в виртуальной машине.

SRM 504: epic, just epic

Стоило мне впервые успешно решить 1000-бальную задачу из SRM 504 Div 2, как результаты матча аннулировали из-за технических неполадок на сервере. Я, конечно, горжусь собой, но моя радость была бы более полной, если бы мои успехи отразились в рейтинге.

А первые две задачи во втором дивизионе вот уже второй матч подряд совсем простые. Или дело во мне?..

Наука и жизнь

Еду, стало быть, в метро. Изучаю налепленные на стены вагонов творения неизвестных рекламщиков. Оказывается, средство от аллергии N не вызывает сонливости! Волшебно! Но впечатление смазывается циферками-сносками. Что обычно пишут в сносках к рекламному тексту? Например, что N не вызывает сонливости, если его не принимать. Или что сонливостью считается только мгновенное погружение в сон не менее чем на 10 часов. Но нет!

В сносках были ссылки на научные статьи. Такие дела.

Я аж всплакнул от счастья.