Opa: Iterating through stringmap and forming a new

2019-07-18 08:05发布

问题:

I'm editing the Hello-wiki code from Opa Documentation. I want a wiki-topic to have a list of the existing topics in the database. I have a function which is called on the default topic:

/**
  * Collect all created topics from /wiki 
  * and present them in Markdown format
  */
function collect_topics(page) {
    string collection = "#Available topics\n"

    // Format as a list
    Set.iter(function( topic ) {
        collection = "{collection} *[{topic}](./{topic})\n"
    }, [/wiki])

    save_source(page, collection)
}

...

function start(url) {

    match (url) {

        case {path: [] ... } :
            { collect_topics("Topics") };

        case {~path ... } :
            { display(String.capitalize(String.to_lower(String.concat("::", path)))) };
    }
}

This raises a syntax error: "found a binding as condition", to my understanding because strings are immutable. Is there a way to change a created string? For example:

string x = "foo"
x = x ^ x

In case this is impossible, what would be a better approach?

回答1:

Indeed Opa is a functional programming language, values are not mutable. If you really want a mutable value, use http://doc.opalang.org/module/stdlib.core/Mutable or Cells to handle states (with safe updates) on your app http://doc.opalang.org/value/stdlib.core.rpc.core/Cell/make

Here is how you should write your code:

function collect_topics(page) {

    collection =
        Map.fold(function( key, value, acc ) {
            "{acc}\n *[{key}](./{value})"
        }, /wiki, "#Available topics\n")

    collection
}

Here I use Set.fold instead of Set.iter. The List.fold documentation should help your to understand how "fold" functions works: http://doc.opalang.org/value/stdlib.core/List/fold

Set.iter doesn't return anything (void), it's only used to iterate through the collection and do some side-effects, like printing log in the console, modifying the Dom, etc



标签: opa