Поругайте недоязычок описания и преобразования данных

Dasar

Назначение языка:
 Описание деревьев данных и преобразование одних деревьев в другие. Аналог xml-я и xslt в одном флаконе. Отдаленный аналог: json, s-expression, sql-я, xquery, linq(и его аналогов в других языках).
 Объектные графы тоже описываются и преобразуются, но требуют нормализации в деревянный вид: обратные ссылки, приводящие к циклам, оформляются по особому.
Основные принципы:
- лаконичность
- единообразие (унификация)
- конвейерная запись преобразований
- текстовая сериализуемость: произвольные данные или код должны уметь преобразоваться в текстовое представление (максимально приближенное к коду, который пишет программист) для передачи по произвольному каналу
- толерантность к неполноте информации: код может обработать дерево, имея лишь частичное представление о его структуре и смысле
- заточенность под исполнение O(1)/O(log n)
- гибкость
Пример описания данных

description
{
family
{
ml
{
title:'Серия 1';
module
{
k8{title:'к8'},
m8{title:'м8'},
//m5_1{title:'м5_1'},
}
},
sl
{
title:'Серия 2';
module
{
k8{title:'к8'},
m8{title:'м8'},
//m5_1{title:'m5_1'},
ntu{title:'нту'},
f5_4{title:'ф5.4'},
}
},
}
},
version
(
8
{
module
{
sl
{
ntu{changed, main},
k8{changed},
m8{changed},
f5_4{changed, main},
};
},
date:'24.12.2013',
comment:' Улучшена стабильность работы Нту.
Ф5.4 устранена проблема zzz.';
}



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

description family
ml
title 'Серия 1'
module
k8 title к8
m8 title м8
sl
title 'Серия 2'
module
k8 title к8
m8 title м8
ntu title нту
'f5_4' title 'ф5.4'
version
8
module sl
ntu
changed
main
k8 changed
m8 changed
f5_4
changed
main
date '24.12.2013'
comment ' Улучшена стабильность работы Нту.
Ф5.4 устранена проблема zzz.'

преобразование приведенных данных в html-вид

(
include{ext:htmling3};
#versions %version.?;
#description %description;

(
(@versions.reverse ->
html:body
{
css:text:'
table {border-collapse:collapse;font-size:90%}
table td {padding:2px 2px 2px 2px;vertical-align:top;border:1px solid black; text-align:center;vertical-align:middle}
table th {padding:2px 2px 2px 2px;vertical-align:top;border:1px solid black; text-align:center;vertical-align:middle;font-size:80%}
';
div{style:font-size:'80%'}
{
text:"Условные обозначения:", br,
text:"! исправлена ошибка", br,
text:"+ новая функция", br,
div{nbsp, style{width:'20px';background-color:lightgray;display:inline-block;}}, text:' рекомендована для установки',
br,
},
table
{
tr
{
th{colspan:2, text:''},
@description.family.? -> th{text:.title.?; colspan:(.module.?).count};
th:text:''
},
tr
{
th:text:'Дата', th:text:'Версия',
@description.family.?.module.? -> th:text:.title.?;
th:text:'Изменения'
},
%? #version -> tr
{
#module-view=>(text:(.changed -> '+' (.main -> style:background-color:lightgray;

td:text:.date.?;
td:text:%$;
@description.family.? #family ->
{
.module.? #module ->
{
td{@version.module.?[%$ == @family %$].?[%$ == @module %$] -> .module-view};
}
};
td{style:text-align:left;.comment.?.text-to-html};
}
}
}
).to-html-string.?;
)

выходной html

<html ><body ><style >
table {border-collapse:collapse;font-size:90%}
table td {padding:2px 2px 2px 2px;vertical-align:top;border:1px solid black; text-align:center;vertical-align:middle}
table th {padding:2px 2px 2px 2px;vertical-align:top;border:1px solid black; text-align:center;vertical-align:middle;font-size:80%}
</style>
<div style="font-size:80%;" >Условные обозначения:<br />
! исправлена ошибка<br />
+ новая функция<br />
<div style="width:20px;background-color:lightgray;display:inline-block;" >&#160;</div>
рекомендована для установки<br />
</div>
<table ><tr ><th colspan="2" ></th>
<th colspan="2" >Серия 1</th>
<th colspan="4" >Серия 2</th>
<th ></th>
</tr>
<tr ><th >Дата</th>
<th >Версия</th>
<th >к8</th>
<th >м8</th>
<th >к8</th>
<th >м8</th>
<th >нту</th>
<th >ф5.4</th>
<th >Изменения</th>
</tr>
<tr ><td >24.12.2013</td>
<td >8</td>
<td />
<td />
<td >+</td>
<td >+</td>
<td style="background-color:lightgray;" >+</td>
<td style="background-color:lightgray;" >+</td>
<td style="text-align:left;" >&#160;&#160;Улучшена стабильность работы Нту.<br />
&#160;&#160;Ф5.4 устранена проблема zzz.<br />
</td>
</tr>
</table>
</body>
</html>


6yrop

средства декомпозиции где?

VitMix

средства декомпозиции где?
Вот же:
include{ext:htmling3}
:)

apl13

9001st Tree Markup Language?

khachin

Можно комментарий по поводу круглых скобок после version? В остальных местах фигурные.
Питон-вариант вызывает дискомфорт без двоеточия в конце строки перед новым блоком отступа.

Dasar

средства декомпозиции где?
декомпозиции чего? и по какому принципу?

Dasar

Можно комментарий по поводу круглых скобок после version? В остальных местах фигурные.
Фигурные скобки и круглые скобки, при использовании в качестве выделения блока - взаимозаменяемые.
Отчасти это сделано для удобства, чтобы можно было одни блоки отделять от других.
Отчасти из-за того, что у меня пока не сформировалось хорошего принципа по которому можно блоки разделить на несколько видов.
Питон-вариант вызывает дискомфорт без двоеточия в конце строки перед новым блоком отступа.
если хочется, то двоеточие можно там указывать для эстетики - парсер это пережует. Но, вообще, как раз хотелось сделать максимально "чистое" представление, чтобы глаз не мылился лишними символами.

Maurog

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

Dasar

9001st Tree Markup Language?
это тоже есть, но в большей степени это 9001st Tree Processing Language.
еще он язык вида "давайте опишем мир в виде дерева" (в очень сыром виде когда ФС, БД, интернет, произвольный объектный граф внешним образом описывается как ориентированный граф без циклов, что позволяет над миром делать всякие преобразования через единый синтаксис.

Dasar

предположу, что имеются в виду переменные\константы, функции\процедуры, модули. есть ли возможность их использовать?
переменные есть.
Из вышеприведенного кода, это, например, объявление двух переменных

#versions %version.?;
#description %description;

или маркировка "на лету"

.family.? #family

функции тоже есть (из-за конвейерного подхода считается, что у функции всегда есть один параметр, который "пришел слева", и внутри функции он текущий)

#module-view=>(text:(.changed -> '+' (.main -> style:background-color:lightgray;

функцию можно запихнуть в узел дерева - будет недо-объект
модули есть, но халявные.

Ivan8209

Что тут можно ругать, если нет даже формальной грамматики,
не говоря уж о семантике?
---
"История не учительница, она классная дама: сама она никого
и ничему не учит, но больно наказывает за невыученные уроки."

Dasar

Основные противоречия, которые решались в синтаксисе или семантике
1. Деление на элемент, аттрибут, значение (при этом один вид не может быть заменен на другой) В xml - есть все три. В универсальных ЯП обычно сведено до двух: элемент(объект) и аттрибут(свойство).
Здесь принято решение, что всё есть элемент.
2. Деление: структура, коллекция, атомарное значение.
Решение: всё есть дерево(лес).
4. Литерал или терминальный символ?
Решение: всё и то, и другое одновременное. Кавычки имеют смысл только для синтаксического парсера, чтобы можно было строку с произвольными символами представить в виде единого литерала.
5. Терминальный символ или переменная?
Решение: Если не указано явно, то, по умолчанию, терминальный символ. Обращение к переменной явно выделяется символом '@' спереди.
6. При обращении к элементу дерева выбирается сам элемент или его внутреннее содержимое?
В ФС, xml принято, что выбирается сам элемент. В ЯП выбирается содержимое при обращение к свойству, и сам элемент при обращени к коллекции.
Решение: всегда выбирается сам элемент

a{b:1, c:2} -> .b ==> b:1
a{b:1, c:2} -> .b.? ==> 1

7. Выбор идет на текущем уровне, или на уровень ниже?
Решение: на уровень ниже через символ '.', на том же уровне через символ '%'

(a{b:1, c:2}, a2{b:21}) -> .b ==> (b:1, b:21)
(a{b:1, c:2}, a2{b:21}) -> %a2 ==> a2{b:21}

8. Дерево целиком или только значение узла?
Решение: дерево целиком - символ '$", значение узла - '%$'

a{b:1, c:2} -> $ ==> a{b:1, c:2}
a{b:1, c:2} -> %$ ==> a

9. Конкретный элемент или произвольный?
Решение: конкретный элемент - через имя, мультивыбор - через список, произвольный - через '?'

(a{b:1, c:2}, a2{b:21, d:4}) -> .b ==> (b:1, b:21)
(a{b:1, c:2}, a2{b:21, d:4}) -> .(c,d,e) ==> (c:2, d:4)
(a{b:1, c:2}, a2{b:21, d:4}) -> .? ==> (b:1, c:2, b:21, d:4)

Dasar

формальной грамматики,
какой-то вариант грамматики

query := expression;
expression := S* semicolon-expression S*;
semicolon-expression := comma-expression ( S* ';' S* comma-expression)* (S* ';')?;
comma-expression := (match-expression ( S* ',' S* match-expression)* (S* ',')?);
match-expression := (switch-expression / or-expression) ( S* match-op S* match-expression) *;
or-expression := and-expression ( S* or-op S* and-expression) *;
and-expression := equal-expression ( S* and-op S* equal-expression) *;
equal-expression := sum-expression ( S+ equal-op S+ sum-expression) *;
sum-expression := multiply-expression ( S+ sum-op S+ multiply-expression)*;
multiply-expression := not-or-else-expression ( S+ multiply-op S+ not-or-else-expression) *;
not-or-else-expression := not-expression / colon-expression;
not-expression := ('!' S* colon-expression);
colon-expression := query-expression (S*':' S* colon-expression)?;
query-expression := (atom-expression (S* (check-expression / function-expression / property-expression / axis-expression / square-expression / named-expression*);
atom-expression := var-expression / lambda-expression / declare-expression / construct-expression / check-expression / function-expression / property-expression / axis-expression / round-expression / figure-expression/ square-expression / lexem;
var-expression := '@' identifier;
declare-expression := '#' identifier S* match-expression;
lambda-expression := (identifier / round-expression) S* '=>' S* match-expression;
construct-expression := (lexem / round-expression) (S* named-expression)? (S* figure-expression)+;
named-expression := '#' (identifier / spec-identifier);
switch-expression := ( S* '|' S* match-expression)+;
function-expression := '.' lexem S* round-expression;
check-expression := '%' condition;
axis-expression := '^' condition;
property-expression := '.' condition;
condition := switch-condition / lexem;
switch-condition := '(' S* lexem (S* ',' S* lexem S*)* S* (',' S*)? ')';
round-expression := '(' (expression / S*) ')';
square-expression := '[' expression ']';
figure-expression := '{' (expression / S*) '}';
lexem := (command-identifier / number / literal / identifier / spec-identifier);
and-op := '&&';
or-op := '||';
equal-op := !'<-' ('*==*' / '*=*' / '*=' / '=*' / '==' / '!=' / '<=' / '>=' / '<' / '>' );
multiply-op := '*' / '/';
sum-op := '+' / '-';
match-op := '->' / '<-' / ':=' / '-=' / '+=';
identifier := [a-zA-Z_]([a-zA-Z0-9-_]*);
command-identifier := '::'[a-zA-Z_]([a-zA-Z0-9-_]*);
spec-identifier := '$' / '?' / '~' / '^';
number := [0-9][0-9]*;
literal := ('""' ('""""' / (!'""' .* '""') / (""'"" (""''"" / (!""'"" .* ""'"");
S := comment / [ \t] / line-break;
comment := '//' (!line-break .)* line-break;
line-break := ([\r][\n]) / [\r] / [\n];

в формальной записи семантики я не силен. Могу своими словами рассказать при наличии примера, что и как стоит рассказать.

Papazyan

еще он язык вида "давайте опишем мир в виде дерева" (в очень сыром виде когда ФС, БД, интернет, произвольный объектный граф внешним образом описывается как ориентированный граф без циклов, что позволяет над миром делать всякие преобразования через единый синтаксис.
Спасибо, но Лисп давно уже изобрели.

Dasar

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

Ivan8209

> в формальной записи семантики я не силен.
Вот и разберись с этим, чтобы не надо было "при наличии примера."
И, кстати, если ты используешь очень новый и не до конца
разработанный способ записи грамматики, надо это указывать,
так как не всегда очевидно, что обозначается знаком "/":
толи это обычный выбор, толи зависимый.
А ещё, это, конечно, круто, что ты закодировал приоритеты операций
в грамматике, но грамматика от этого становится очень тяжеловесной.
Если ты хочешь, чтобы что-либо "покритиковали," не надо этого делать.
---
"История не учительница, она классная дама: сама она никого
и ничему не учит, но больно наказывает за невыученные уроки."

Ivan8209

>> Спасибо, но Лисп давно уже изобрели.
> он под списки заточен. Деревья на нем не удобно записываются
Гон.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."

Dasar

Гон.
как минимум их надо во что-то преобразовывать, или делать какие-то дополнительные допущения, чтобы был возможен быстрый поиск конкретного элемента по именованому пути (быстрее, чем full-scan в глубину)

6yrop

декомпозиции чего?
больших задач
 
и по какому принципу?

это уже ты должен придумать.
понятно что должно быть аналоги передачи параметра и колбеки.

Dasar

колбеки
это зачем? ужасный же вариант декомпозиции.

6yrop

это зачем? ужасный же вариант декомпозиции.
как ты будешь делать общую конву на сайте — частный случай колбеков

Dasar

делать общую конву
в смысле, переиспользуемый каркас?

kill-still

Отдаленный аналог: jsont, s-expression, sql-я, xquery, linq
опечатка?

Dasar

получается аналог и того, и другого

karkar

Паттерн-матчинг? Ветвления? Циклы? Абстрагирование генерации схожих деревьев в функции?

Ivan8209

Хотел написать это раньше, и раз уж ты всё равно здесь...
Я бы даже сказал, что пять страниц кода, пестрящего $$$, <<<, >>>, и т.п.
было более осмысленно критиковать, чем то, что выше.
---
"Это проявление Аль-Хагг.
Те, кто знают это, знают..."

Dasar

Паттерн-матчинг?
полноценного нет. я не определился с базовым набором примитивов и функционала под это.
Паттерн-матчинг? Ветвления?
есть конструкция вида

| <condition1> -> <code1>
| <condition2> -> <code2>
...
| <conditionN> -> <codeN>

condition-ы проверяются последовательно,
 если <condition-i> не пустой, то в, качестве, результата всего выражения берется результат <code-i>,
 иначе (если пустой то проверяется следующее условие
примитивный паттерн-матчинг на такой конструкции получается организовать.
Циклы?
нет, и не будет.
есть, возможность, сгенерить бесконечный список, и есть понятие волны, которая движется по списку и на каждой итерации вызывает обработчик, передавая текущий элемент. Обработчик на каждой итерации может вернуть произвольный лес и/или передать произвольный лес на следующую итерацию. Этакая помесь: map и aggregate.
Абстрагирование генерации схожих деревьев в функции?
что имеется ввиду?

Dasar

А ещё, это, конечно, круто, что ты закодировал приоритеты операций
в грамматике, но грамматика от этого становится очень тяжеловесной.
согласен.
К сожалению, под вариант грамматики с отдельным описанием приоритетов у меня не получилось сходу сделать универсальный парсер.

karkar

что имеется ввиду?

Когда есть <code1> и <code2>, совпадающие по большей части, но имеющие некоторые отличия, и хочется DRY.

Marinavo_0507

как минимум их надо во что-то преобразовывать, или делать какие-то дополнительные допущения, чтобы был возможен быстрый поиск конкретного элемента по именованому пути (быстрее, чем full-scan в глубину)
а разве по твоей записи можно сделать поиск быстрее, чем прочитать всё дерево?
чтоб было быстрее, нужен бинарный формат типа как в базах данных

karkar

И, кстати, если ты используешь очень новый и не до конца
разработанный способ записи грамматики, надо это указывать
Мне показалось, это обыкновенный PEG, он в 21 веке ни у кого вопросов вызывать не должен.

Ivan8209

> Мне показалось, это обыкновенный PEG, он в 21 веке ни у кого вопросов вызывать не должен.
Мне тоже так показалось, но у меня они всё равно вызывают некоторые вопросы.
(Кстати, про 21-й век не надо, они и появились, емнип, только в 21-м веке.)
---
"Математика --- лучший способ водить самого себя за нос."

Dasar

а разве по твоей записи можно сделать поиск быстрее, чем прочитать всё дерево?
Если дерево уже прочитано, и при наличии условия, что узлы на одном уровне отсортированы, то можно быстрее.
на списках, конечно, можно тоже самое (изоморфные преобразования никто не отменял но придется тогда в список вложить ту же самую семантику, что есть у дерева.
есть следующее дерево (сортированность узлов есть изначально, или делается при прочтении)

a
b1 x
c2
fa
fr 5
d
e 1
..
b
..

тогда следующее выражение %a.c2.fr.? с помощью бинарного поиска отрабатывается за O(log N)
тоже самое, конечно, можно сделать и на списках

(a, (b1, (x (c2, (fa (fr, (5 (d (e, (1 (b, ..)

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

Marinavo_0507

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

Dasar

то есть преобразовать в бинарный формат таки надо
да, надо
ps
если говорить аккуратнее, то требуется преобразование во внутренний формат, потому что этот внутренний формат можно хранить и в виде текста при очень большом желании

Dasar

Когда есть <code1> и <code2>, совпадающие по большей части, но имеющие некоторые отличия, и хочется DRY.
можно применить общий подход:
- либо делается "жирная" функция, которая принимает флажок "первый вариант это, или второй", и в места различий вставляются if-ы на основе флажка
- либо делается "каркасная" функция, которая принимает в качестве параметров набор отличий и их расставляет по "местам".
ps
чтобы привести более конкретные инструменты необходима более конкретная задача.

rosali

Что-то я не догоняю, чем отличается ; от , и зачем нужно :
разве k8{changed} это не то же самое что k8:'changed' ?
.(c,d,e)

О! Давно ждал такой язык ;) А там что-нибудь позабористее можно?
.(c.d, e {f.g, h})

Ivan8209

>> .(c,d,e)
> О! Давно ждал такой язык
Пролог, что ли?
---
...Я работаю антинаучным аферистом...

rosali

Да при чем тут пролог =) просто синтаксическая возможность писать после точки что угодно. Вместо [x.a, x.b, x.c.d] ты пишешь x.[a, b, c.d] и т.п. Особенно это удобно, когда x не переменная, а временные данные. Вместо x=f(y); x.a+x.b ты просто пишешь f(y).(a+b)

karkar

Волшебное слово with еще в паскале было.
Вот так в D работает:
struct S { int a, b; }
S f(int x) { return S(x, x+1); }
int g(int x) { with(f(x return a + b; } // <---

VitMix

With, по крайней мере в паскале, не работает внутри выражений. С помощью него не сделаешь аналог
f(x).(a+b)*f(y).(a+b)

apl13

он под списки заточен. Деревья на нем не удобно записываются
WAT
(define omg '(1 2 3 (4 5 (6 7) (8 9) 10) 11

Лиспосписок это и есть дерево.

Dasar

Что-то я не догоняю, чем отличается ; от , и зачем нужно :
разве k8{changed} это не то же самое что k8:'changed' ?
для отделения выражения друг от друга - ';' тоже самое, что и ','. внутри точки работает только ','
k8:changed тоже самое, что k8{changed}
первое сделано для того, чтобы скобок было как можно меньше.
что-нибудь позабористее можно
можно.

#f=>p{x:10, y:4};
.f -> .x+.y

выдаст 14

Dasar

Семантика:
Язык, по умолчанию, иммутабельный.
Каждая конструкция языка на вход принимает лес и на выход возвращает лес.
1. одиночный терм или литерал
вход игнорируется. на выходе - лес из одного узла, содержащего терм

tr ==> tr
1 ==> 1
'tr' ==> tr
'1 2' ==> '1 2'

1.1. блок (список выражений, склейка в длину)
expr1; expr2; ..; exprN.
может заключаться в круглые или фигурные скобки. вместо ';' может использоваться ','. Сепаратор после последнего выражения может ставиться, а может не ставиться.
каждое из expr-i принимает на вход тот же лес, что и весь блок. Результат блока есть склейка результатов expr-i
2. декларация переменной отдельным выражением внутри блока
#name expr;
expr вычисляется и присваивается переменной name
переменная видна до конца блока.
имя переменной может переиспользоваться, но физически это будет новая переменная.
2.1. переменная (обращение к переменной)
вход игнорируется. на выходе - содержимое переменной

(#x 1;@x; @x;) ==> (1, 1)

3. дерево (склейка в глубину)
expr1 {expr2}.
также возможен вариант записи expr1:expr2.
запись expr1:expr2:expr3 раскрывается как expr1{expr2{expr3}}
оба выражения на вход принимают то же, что всё выражение в целом.
результат expr2 вклеивается на один уровень ниже в результат выражения expr1

div{text{1}} ==> div:text:1
(div:text:1){text:2} ==> div{text:1, text:2}
(div, div){text:1} ==> (div:text:1, div:text:1)
{1, 2} ==>

4. выбор по имени
%<term>
из входного леса выбираются деревья у которых головной терм совпадает с term

(a, b, c, b:2) %b ==> (b, b:2)
(a, b, c, 'b 1':2) %'b 1' ==> 'b 1':2

5. выбор по имени на уровень ниже
.<term>
из входного леса из всех поддеревьев уровнем ниже выбираются такие у которых головной терм совпадает с term

p{x:1, y:2}.x ==> x:1
(div:text:1, p{text:2, br, text:3}).text ==> (text:1, text:2, text:3)

6. выбор головного узла
%$
из входного леса выбирает только головные узлы

p{text:1} %$ ==> p
(div, p:text:2) %$ ==> (div, p)

7. выбор всех элементов на уровень ниже
.?
выбираются все поддеревья на уровень ниже

p{text:1} .? ==> text:1
(div, p:text:2) .? ==> text:2

8. конвейер
->
фактически ничего не делает. используется для ввода блока в выражение, или для визуального отделения

p{text:1} -> .? <==> p{text:1} .? ==> text:1
p{text:1} -> (%$, .?) ==> (p, text:1)
(div:text:1, p:div:text:2) -> (.text, .?.text) ==> (text:1, text:2)

8.1 текущий лес
$
результат равен входу.

1 -> $ ==> 1
div{text:1} -> $:text:2 ==> div{text:1, text:2}

9. where
[<cond>]
из входных деревьев выбираются такие для которых <cond> не пустой

(div:text:1, div, p:text:2) [.text] ==> (div:text:1, p:text:2)

10. switch
| <condition1> -> <expr1>
| <condition2> -> <expr2>
...
| <conditionN> -> <exprN>
condition-ы проверяются последовательно,
если <condition-i> не пустой, то результат <condition-i> передается в <expr-i> и в, качестве, результата всего выражения берется результат <expr-i>,
иначе (если пустой то проверяется следующее условие
11. декларация функции
#<name>(<args>) => <expr>;
у функции есть один неявный аргумент, значение которого передается на вход <expr>
12. вызов функции
.<name>(<expr-s>)
в функцию передается значение входа и значения выражений <expr-s>

(
#add-text(text)=> $ {text:@text};
div.add-text(1).add-text(2 p.add-text(3);
) ==> (div{text:1, text:2}, p:text:3)

6yrop

навигация по коду есть?

Dasar

навигация по коду есть?
нет, нету

6yrop

нет, нету
и нельзя сделать?

Dasar

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

6yrop

открытый вопрос - насколько часто он будет ошибаться.
так не пойдет, должна быть 100% верность, хотя бы теоретическая

Dasar

так не пойдет, должна быть 100% верность, хотя бы теоретическая
Что выдавать, например, для следующего кода?:

#author author{id: 1, Fio:'И.И. Карнаух'};
#book book {id:1, name:'Bla-bla'};

#item |[.rand < 0.5] -> @author | @book;
@item.id;

что должна делать навигация при нажатии на id в последней строке?
ps
Данный код может быть статически-типизирован, при этом тип переменной item: некая структура, имеющая поле id.

Bibi

лень вникать.
про edn вспоминали? http://github.com/edn-format/edn

6yrop

что должна делать навигация при нажатии на id в последней строке?
список из двух элементов. При этом про каждый элемент выдается инфа: какой проект, неймспейс, класс, файл, метод, строка.
Оставить комментарий
Имя или ник:
Комментарий: