Functional programming 将文本解析到Racket/Scheme中的树 我正试图把我的C++代码转换成球拍,因为我在学习球拍。我的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; }

Functional programming 将文本解析到Racket/Scheme中的树 我正试图把我的C++代码转换成球拍,因为我在学习球拍。我的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; },functional-programming,scheme,lisp,racket,Functional Programming,Scheme,Lisp,Racket,它是: '(1 (2 (3 4 Z (X)))) 如何修复它?原始方法的问题在于,您正试图直接移植一个命令式解决方案,该解决方案甚至使用按引用传递来跟踪遍历的状态。这是行不通的,第一步是用函数式编程风格重新思考解决方案 我们必须跟踪嵌套结构中的位置的这类问题,使用堆栈数据结构可以更好地解决。我将使用列表实现列表堆栈,并使用以下帮助程序在最顶端的列表上追加新元素: (define (append-top ele stack) (cons (append (car stack) (list e

它是:

'(1 (2 (3 4 Z (X))))

如何修复它?

原始方法的问题在于,您正试图直接移植一个命令式解决方案,该解决方案甚至使用按引用传递来跟踪遍历的状态。这是行不通的,第一步是用函数式编程风格重新思考解决方案

我们必须跟踪嵌套结构中的位置的这类问题,使用堆栈数据结构可以更好地解决。我将使用列表实现列表堆栈,并使用以下帮助程序在最顶端的列表上追加新元素:

(define (append-top ele stack)
  (cons (append (car stack) (list ele))
        (cdr stack)))
现在来看看实际的解决方案。假设输入列表格式良好,具有相同数量的
,且顺序正确(未执行错误检查):

(定义(解析树标记)
(让我们分析([tokens tokens][stack'(())]))
(cond[(空?令牌)
;解决方案位于堆栈顶部,返回它
(汽车组)]
[(eq?(汽车代币)]
;弹出堆栈的顶部元素,将其附加到上一个
;框架,继续我们留下的解决方案
(解析(cdr令牌)(追加顶部(汽车堆栈)(cdr堆栈))]
[其他
;将当前元素添加到堆栈顶部
(解析(cdr令牌)(追加顶部(汽车令牌)堆栈))))
它按预期工作

(parse-tree '(1 < 2 < 3 4 > > Z < X >))
=> '(1 (2 (3 4)) Z (X))
(解析树(1<2<34>>Z)
=>'(1(2(34))Z(X))

对不起,解析树,我现在就修复它。没有办法让它成为纯函数式的?在这种情况下,我指的是不可变的变量。它可以用纯函数式的方式完成(请参见我的答案),您只需保留一个堆栈,以记住我们在解析中的位置。
'(1 (2 (3 4 Z (X))))
(define (append-top ele stack)
  (cons (append (car stack) (list ele))
        (cdr stack)))
(define (parse-tree tokens)
  (let parse ([tokens tokens] [stack '(())])
    (cond [(null? tokens)
           ; solution is at the top of the stack, return it
           (car stack)]
          [(eq? (car tokens) '<)
           ; start new sublist at the top of the stack
           (parse (cdr tokens) (cons '() stack))]
          [(eq? (car tokens) '>)
           ; pop top element of the stack, append it to previous
           ; frame, continue with solution where we left it
           (parse (cdr tokens) (append-top (car stack) (cdr stack)))]
          [else
           ; add current element to top of stack
           (parse (cdr tokens) (append-top (car tokens) stack))])))
(parse-tree '(1 < 2 < 3 4 > > Z < X >))
=> '(1 (2 (3 4)) Z (X))