Удобное отображение структур данных

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

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

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

procedure represent(obj)
local acc
acc := ""
case type(obj) of {
    "string" : acc := """ || obj || """
    "cset" : acc := "'" || obj || "'"
    "null" : acc := "&null"
    "list" : acc := represent_list(obj)
    "table" : acc := represent_table(obj)
    "record" : acc := represent_record(obj)
    "set" : acc := represent_set(obj)
    default : acc := image(obj)
}
return acc
end

procedure represent_list(l)
local acc,i
acc := "[ "
every i := !l do {
     if type(i) ~== "list" then {
        acc ||:= represent(i) || " , "
     } else acc ||:= represent_list(i) || " , "
}
if *l = 0 then return "[]" else return acc[1:*acc-1] || "]"
end

procedure represent_table(t)
local acc,i
acc := "{ "
every i := key(t) do {
     if type(i) ~== "table" then {
        acc ||:= represent(i) || " : " || represent(t[i]) || " , "
     } else acc ||:= represent_table(i) || " , "
}
if *t = 0 then return "{}" else return acc[1:*acc-1] || "}"
end

procedure represent_record(r)
local acc,i
acc := "r" || "( "
every i := !r do {
     if type(i) ~== "record" then {
     acc ||:= represent(i) || " , "
     } else acc ||:= represent_record(i) || " , "
}
if *r = 0 then return acc || ")" else return acc[1:*acc-1] || ")"
end

procedure represent_set(s)
local acc,i
acc := "( "
every i := !s do {
     if type(i) ~== "set" then {
        acc ||:= represent(i) || " , "
     } else acc ||:= represent_set(i) || " , "
}
if *s = 0 then return "()" else return acc[1:*acc-1] || ")"
end

procedure print(obj)
write(represent(obj))
end

Функция represent служит для обработки любых типов данных существующих в Icon и генерирует строковое отображение примитивных типов. Другие функции represent_ служат для отображения структуральных типов (список, множество, запись, таблица) в строку. Функция print служит для вывода полученной репрезентации на стандартный поток вывода.

Механизм работы всех функций предельно прост и понятен (я думаю): процедура print получает на вход объект/структуру и отображает его в предельно понятной форме на потоке вывода.

Добавить комментарий