【发布时间】:2019-05-24 06:00:09
【问题描述】:
我正在尝试将我的 C++ 代码转换为 Racket,因为我正在学习 Racket。我的简化 C++ 代码是:
struct Node
{
char value = '\0';
std::vector<Node> kids;
explicit Node(char ch) : value(ch) {}
};
void ParseTree(const std::string& tokens, size_t& i, Node& root)
{
while (i < tokens.size())
{
const Token& token = tokens[i++];
if (token == '<') // children begin
{
ParseTree(tokens, i, root.kids.back());
}
else if (token == '>') // children end, go up
{
return;
}
else
{
root.kids.emplace_back(token);
}
}
}
Node ParseTree(const std::string& s)
{
size_t i = 0;
Node root('$');
ParseTree(Parse(s), i, root);
return root;
}
非常简单的代码。我对 Racket 的翻译是:
(define (parse-tree tokens)
(if(empty? tokens)
'()
(cond
[(eq? '< (car tokens))
(list (parse-tree (cdr tokens)))]
[(eq? '> (car tokens))
(parse-tree (cdr tokens))] ; no return, how to step up?
[else
(cons (car tokens)(parse-tree (cdr tokens)))])))
这里的问题是我没有返回 (eq?'> (汽车令牌),所以新节点被添加到底部。 一个小测试:
(parse-tree '(1 < 2 < 3 4 > > Z < X >))
应该是:
'(1 (2 (3 4)) Z (X))
它是:
'(1 (2 (3 4 Z (X))))
如何解决?
【问题讨论】:
-
抱歉解析树,我现在就修复它。
-
没有办法让它成为纯函数式的?
-
在这种情况下,我的意思是不可变变量。
-
它可以以纯粹的功能方式完成(见我的回答),你只需要保留一个堆栈来记住我们在解析中的位置。
标签: functional-programming scheme lisp racket