Практика мультипарадигмального программирования, 02 лекция (от 19 февраля)

Материал из eSyr's wiki.

Перейти к: навигация, поиск

Предыдущая лекция | Следующая лекция

Основная тема — способы сочетания нескольких парадигм.

Содержание

Tcl

Мультипарадигмальный язык (?)

Запуск

$tclsh

Это оболочка. Понимает внешние команды.

Вывод строки: puts «Hello»

Без перевода строки: nonewline

Установка переменной: set myvar val

Получение значения: $myvar

Ассоц массивы: set myarray(27) {val}

Внутри фиг скобок обратный слеш не действует, подстановки не действуют

Квадратные скобки — подставление результата (почти то же, что обратные кавычки в шелле, но не то, что печатают, а действительно результат)

Математика

есть expr. Склеивает все аргументы и воспринимает как арифм выражение

Допустим, есть переменная, которая получает значение извне (от пользователся, по сети). Что в такой ситуации может получиться:

% set userinput {[puts DANGER!]}
[puts DANGER!]
%expr {$userinput == 1}
0
%expr {$userinput == 1}
%expr $userinput == 1
DANGER!
0

Почему так происходит: происходит подстановка и вычисляется значение внутри квадратных скобок. Правило: внутри expr лучше всегда использовать фигурные скобки.

Арифметические операции как в Си. Числа бывают с плавающей точкой и целые. Есть побитовые операции, логические связки. Кроме того, есть:

  • eq — сравнение строк на эквивалентность
  • ne — на неэквив
  • in — в списке
  • ni — не в списке

Есть математические функции

Управляющие конструкции

if

if <условие> then <oper> else

условие вычисляется так же, как expr, then необязателен, else тоже

В реальной жизни делают иначе:

if {$x == 1} {
...
} {
...
}

При этом многие не понимают, что фигурные скобки это не операторные скобки. В качестве условия может дать число (0 ложь, 1 истина), строки «yes»/»no», «true»/»false», остальные слова вызывают ошибку.

switch

switch <expr> {
<expr> { ... }
<expr> { ... }
default { ... }
}

На самом деле, switch можно записать совсем иначе:

switch $x "one" "puts 1" \
"two" "puts 2" "three" "puts 3" \
default "puts Unknown"

Если первое выражение не воспринимается, как список, то оно идёт дальше до дефолт (?)

while

while <усл> <body>

for

for <start> <condition> <next> <body>

Если это написать вот так:

for {set i 0} {$i < 10} {set i [expr $i+1]}

то будет совсем похоже на Си.

Процедуры

proc <name> <params> <body>

Пример:

proc sum  {x y} {
   return [expr {$x+$y}]
}

Объявление переменных

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

Глобальная переменная:

global z — будет глобальная
upvar — связывает с переменной, которая в том контексте, в котором определена процедурах

Комментарии

# ...

Комментарии не от начала строки, а от начала оператора. То есть, если хотим на той же строчке комментарий, то надо поставить точкой с запятой.

Списки

В последних версиях Tcl есть своё внутреннее представление (например, число хранится как число), поэтому он эффективнее шелла. Посему, так как списки хранятся как списки, то работа с ними эффективна.

Работа со списками

Задание списков

set lst {{item 1} {item 2} {item 3}}
set lst [split "Item1.Item2.Item3" "."]
set lst [list "Item1" "Item2" "Item3"]

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

Индексирование

lindex <list>  <index>

Выделяет элемент. Индексы с 0.

Длина

llength <list>

Объединение

concat

Добавление элементов

lappend <list> <...>

Вставка в середину

linsert <list> <index> <arg> ...

Замена

lreplace <list> <first> <last> <...> <...>

Установить такому элементу списка такое значение

lset <listName> <index> <newValue>

Работа со строками

Есть команда string, которая со строкаим делает всё. На самом деле, она состоит из двух слов, и второе обозначает команду.

string length <str> — длина
string compare
string bytelength — размер в байтах
string trim — отбросить незначащие пробелы
string topupper
string tolower
string range
string index
string match <pattern> <str>— берётся строка и сравнивается с образцом. В образце могут быть "*", "?"

[glob /usr/bin/*] — список всех файлов в /usr/bin/

Решулярные выражения

Единственный командный язык, в котором нет регулярных выражений, известный лектору, это bourne shell.

regexp пытается сопоставить строку целиком
regsub пытается сопоставить произвольную подстроку

Массивы

Есть ассоциативные массивы. Для них есть всеобъемлющая комманда array

array exists — есть ли значение
array names — все существующие индексы данного массива
array size
array get — из списка массив
array set — из массива список

В списке идёт "индекс значение ..."

Работа с файлами

Чуть ли не лучше, чем в шелле

  • open <filename> <access> <permissions (по умолчанию 0666)>
    • access — r, w, r+, w+, a+, a
    • Возвращает нечто, являющее файловым дескриптором
  • close — единственный прааметр — результат open

read, write, tell, eof ...

read возвращает пустую строку в обоих случаях, eof позволяет различить ситуацию

fconfigure позволяет сконфигурировать для работы с бинарными файлами

Парадигмальный аспект

Здесь абсолютно всё является строкой. И for, while — обычная процедура, которую можно переопределить. В отличие от лиспа, создатели tcl умудрились обойтись без специальных форм.

Tcl не получил бы широкого распространения, если бы не его свойства: может встраиваться, может расширяться, самое интересно, если встраивать, предварительно расширить. Пример:

IRCII. Прямой потомок BitchX. Оба содержат интерпретатор Tcl. причём, очень интнресно: в далёков 94 году IRC был безумно популярен. Тогда был IRCII, и тогда была такая вещь, как скрипты, можно было разные действия, например, устраивать войны, как то захват канала. И лектор пытался разобраться в скриптах, и пытался узнать у коллег, где взять ман, но никто не раскололся. Позже, в 2002 году, когда лектор начал программировать на Tcl, он это понял.

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

Имеется н-е количество сишных функций для работы с интерпретатором Tcl. Пример:

#include <stdio.h>
#include <tcl.h>
int main() {
  Tcl_Interp * interp = Tcl_CreateInterp();
  Tcl_Eval(interp, "proc p1 {arg1} {list $arg1 $arg1 $arg1}");
  Tcl_Eval(interp, "p1 foobar");
  printf("%s\n", Tcl_GetStringResult(interp));
  Tcl_DeleteInterp(interp);
  return 0;
}

Как компилировать:

gcc -Wall -g -ltcl embed.c -o embed



Практика мультипарадигмального программирования


01 02 03 04 05 06 07 08


Календарь

пн пн пн пн пн
Февраль
12 19
Март
12 19 26
Апрель
02 09 16


Эта статья является конспектом лекции.
Личные инструменты
Разделы