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