В процессе написания каких-то программ или скриптов на 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 получает на вход объект/структуру и отображает его в предельно понятной форме на потоке вывода.