Сложно-рекурсивные стековые эффекты?
USING: accessors html.parser.analyzer io kernel math namespaces
present regexp sequences ;
IN: all-roads-to-wiki
SYMBOL: G
: match-good-pages ( a -- ?/f )
R/ \/wiki\/[^:]*$/ first-match ;
: filter-urls ( tags -- urls )
find-hrefs [ present ] map
[ match-good-pages ] filter
[ match-good-pages seq>> ] map ;
: findpath ( url -- url )
G get =
[
! false
]
[ scrape-html nip
[
dup "title" find-by-name drop 1 + swap nth
text>> R/ - Wikipedia,/ re-split first print
]
[
"bodyContent" find-by-id-between filter-urls [ findpath ] map
] bi
] if ; inline recursive
: allroads-entry ( -- a )
readln "http://en.wikipedia.org/wiki/" prepend G set-global
"enwp.org/Special:Random" findpath ; inline
Приведенный выше код будет повторяться по каждой ссылке в Википедии, пока не найдет ту, которую ищет.
Это нормально, потому что (надеюсь) findpath
в конечном итоге "вернется" (т.е. не вызовет себя снова) и оставит огромную вложенную структуру данных в стеке. Но когда я пытаюсь скомпилировать это, я получаю unbalanced-recursion
ошибка:
В рекурсивном слове "findpath" стек имеет неправильную высоту
unbalanced-recursion
: Брошенный, когда вывод эффекта стека определяет, что у встроенного рекурсивного слова есть неправильное объявление эффекта стека.
Независимо от того, что я делаю, Фактор (понятно) жалуется, что эффект стека не совпадает. Что мне нужно сделать, чтобы это правильно восстановилось?
1 ответ
Посмотри внимательно на find-path
слово. Я добавлю комментарии, чтобы вы могли видеть, что находится в стеке:
: findpath ( url -- url )
! 1 item: { url }
G
! 2 items: { url G }
get
! 2 items: { url value-of-G }
=
! 1: item { t/f }
[
! 0 items!!!!
! false
]
[ scrape-html nip
[
dup "title" find-by-name drop 1 + swap nth
text>> R/ - Wikipedia,/ re-split first print
]
[
"bodyContent" find-by-id-between filter-urls
[ findpath ] map
] bi
] if ; inline recursive
if
комбинатор потребляет последний элемент в стеке, поэтому этот код не может работать. Вот рабочий код для findpath
слово:
: page-title ( seq -- title )
dup "title" find-by-name drop 1 + swap nth
text>> R/ - Wikipedia,/ re-split first ;
: page-links ( seq -- links )
"bodyContent" find-by-id-between filter-urls ;
: scrape-en-wiki-url ( wiki-url -- seq )
"https://en.wikipedia.org" prepend
dup print flush scrape-html nip ;
: found-url? ( wiki-url -- ? )
G get [ = ] [ drop t ] if* ;
: findpath ( wiki-url -- seq/f )
dup found-url?
[ drop f G set f ] [
scrape-en-wiki-url
[ page-title print flush ] [
page-links [ findpath ] map
] bi
] if ; inline recursive
Также взгляните на словарь Википедии, который предназначен для подобных задач.