FAQ
Hi,

I need to evaluate logical expressions in my app's configuration
files. For example, I want to evaluate a filter like "Foo.FieldX < 20".

I could build a parser, but this is much work for this IMHO generic
problem. There exists a solution for the PHP web framework Symfony
called ExpressionLanguage, although I never used it. Is there a similar
project in the golang universe? Or other solutions to this problem?

A hacky workaround could be to exploit text/template for this task. I
thought about wrapping the expression in a template and executing it to
check for the result, e.g. "{{if <EXPRESSION>}}t{{else}}f{{end}}" =>
"t"/"f". But then I would have to use the template syntax, which is
rather awkward for logical expressions.

I also thought about creating a simple "ExpressionLanguage"-like
package using the golang yacc tool. But as I'm not that experience with
building parsers, I'm not sure if this is feasible (maybe yacc/lex are
not the best tools to use for this task?). Any suggestions are welcomed.

Regards,
Christian

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Egon at Oct 21, 2014 at 9:10 pm

    On Tuesday, 21 October 2014 23:49:19 UTC+3, datenkarussell wrote:
    Hi,

    I need to evaluate logical expressions in my app's configuration
    files. For example, I want to evaluate a filter like "Foo.FieldX < 20".

    I could build a parser, but this is much work for this IMHO generic
    problem. There exists a solution for the PHP web framework Symfony
    called ExpressionLanguage, although I never used it. Is there a similar
    project in the golang universe? Or other solutions to this problem?
    I've used json to encode filters. (see conf related things
    https://github.com/egonelbre/spexs2)

    But, why do you need it to evaluate in app configuration? Eventually after
    doing a lot of stuff with the hacks with the conf, I realized that using Go
    directly would've been much easier.

    Also there are already multiple languages embeddable in
    Go: https://code.google.com/p/go-wiki/wiki/Projects#Virtual_Machines_and_Languages

    And as usual, I've got no clue what you are trying to use it for, so I
    can't give any better suggestions. See HowToAsk
    <https://code.google.com/p/go-wiki/wiki/HowToAsk> for more info.

    + egon

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Christian Neumann at Oct 21, 2014 at 10:53 pm

    egon wrote:
    But, why do you need it to evaluate in app configuration? Eventually after
    doing a lot of stuff with the hacks with the conf, I realized that using Go
    directly would've been much easier.
    Yes, both ways of configuring your applications have their pros and
    cons (similar to domain specific vs general programing languages). I
    decided against using Go (or a scripting language) to configure the
    whole application. I want the user to be able to solve common problems
    by just writing configuration files, and more complex ones using plugins
    written in Go.
    And as usual, I've got no clue what you are trying to use it for, so I
    can't give any better suggestions.
    I'm developing a CMS for small sites (https://github.com/monsti/monsti)
    where each content is represented by a "node". Site builders should be
    able to easily embed listings of other nodes on a page of the
    website. For example, the site builder might want to list all last
    month's nodes of type "blog-entry" on their front page. The
    configuration of the front page should allow to specify such a
    listing. To keep it simple, assume that the listing configuration
    consists only of the specification of a filter, e.g. "node.type ==
    'blog-entry' && (node.changed > last_month())". As site builders (of
    such simple websites; based loosely on my experience) often need such
    listings (which are most of the time implementable using simple filters
    like these), there should be no need to write any code to accomplish
    this common task.

    The popular CMS Drupal has a similiar possibility to configure listings
    like these. Site builders can configure listings with filters using the
    web frontend, which indicates that this is a common problem and that
    there is a need to solve it without writing any line of code (and in
    this case, even without writing configuration files). I'd like to
    implement a similar solution, but using configuration files and filter
    expressions.

    Thanks,
    Christian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Egon Elbre at Oct 22, 2014 at 7:37 am

    On Wed, Oct 22, 2014 at 1:20 AM, Christian Neumann wrote:
    egon wrote:
    But, why do you need it to evaluate in app configuration? Eventually after
    doing a lot of stuff with the hacks with the conf, I realized that using Go
    directly would've been much easier.
    Yes, both ways of configuring your applications have their pros and
    cons (similar to domain specific vs general programing languages). I
    decided against using Go (or a scripting language) to configure the
    whole application. I want the user to be able to solve common problems
    by just writing configuration files, and more complex ones using plugins
    written in Go.
    And as usual, I've got no clue what you are trying to use it for, so I
    can't give any better suggestions.
    I'm developing a CMS for small sites (https://github.com/monsti/monsti)
    where each content is represented by a "node". Site builders should be
    able to easily embed listings of other nodes on a page of the
    website. For example, the site builder might want to list all last
    month's nodes of type "blog-entry" on their front page. The
    configuration of the front page should allow to specify such a
    listing. To keep it simple, assume that the listing configuration
    consists only of the specification of a filter, e.g. "node.type ==
    'blog-entry' && (node.changed > last_month())". As site builders (of
    such simple websites; based loosely on my experience) often need such
    listings (which are most of the time implementable using simple filters
    like these), there should be no need to write any code to accomplish
    this common task.

    Hugo has pretty good approach, but it would be still too complicated for
    regular users. (http://gohugo.io/)

    Configuration files are also usually too complicated for general users.

    Anyways, how would I do it:

    1. create a set of necessary operators:

    type Accepter interface {
    Accept(n Node) bool
    }

    type And []Accepter
    func (a And) Accept(n Node) bool {
    for _, v := range a {
    if !v.Accept(n) {
    return false
    }
    }
    return true
    }

    type EQ struct {
    Prop string
    Value string
    }

    func (a *EQ) Accept(n Node) bool {
    // use reflect
    }

    type GT struct {
    Prop string
    Value string
    }

    func (a *GT) Accept(n Node) bool {
    // use reflect
    }

    (see template package how to implement that with reflection
    http://golang.org/src/pkg/text/template/funcs.go?s=#L302)


    This now allows to create a structure for your filters, e.g:

       filter := And{EQ{"type", "blog-entry"}, Delta{"changed",
    60*25*time.Minute}}
       if !filter.Accept(node) {
          return
       }

    Or whatever operations you need.


    2. Write some conversion from JSON <-> Nodes. e.g

    {type: "and", "children": [{type:"eq", data:{prop:"type",
    value:"blog-entry"}, ...}] }

    Alternatively, the MongoDB syntax will probably look cleaner, but will also
    probably require more effort.

    3. Write some interface for modifying them (use the same JSON structure)
    (simple JS interface stuff)
    4. Persist the JSON in conf files (easier copying of app setup)
    5. Done

    ###

    This should solve the problem.

    Anyways,
    end-users can quite easily introduce errors to configuration files, it's
    better if they wouldn't have to touch them. Most end-users have no clue how
    to get into their servers.

    + egon

    The popular CMS Drupal has a similiar possibility to configure listings
    like these. Site builders can configure listings with filters using the
    web frontend, which indicates that this is a common problem and that
    there is a need to solve it without writing any line of code (and in
    this case, even without writing configuration files). I'd like to
    implement a similar solution, but using configuration files and filter
    expressions.

    Thanks,
    Christian

    --
    You received this message because you are subscribed to a topic in the
    Google Groups "golang-nuts" group.
    To unsubscribe from this topic, visit
    https://groups.google.com/d/topic/golang-nuts/sRni28TpPuA/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to
    golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Mateusz Czapliński at Oct 22, 2014 at 10:47 am

    On Tuesday, October 21, 2014 11:10:27 PM UTC+2, egon wrote:
    On Tuesday, 21 October 2014 23:49:19 UTC+3, datenkarussell wrote:

    I need to evaluate logical expressions in my app's configuration
    files. For example, I want to evaluate a filter like "Foo.FieldX < 20".

    I could build a parser, but this is much work for this IMHO generic
    problem. There exists a solution for the PHP web framework Symfony
    called ExpressionLanguage, although I never used it. Is there a similar
    project in the golang universe? Or other solutions to this problem?
    But, why do you need it to evaluate in app configuration? Eventually after
    doing a lot of stuff with the hacks with the conf, I realized that using Go
    directly would've been much easier.

    Also there are already multiple languages embeddable in Go:
    https://code.google.com/p/go-wiki/wiki/Projects#Virtual_Machines_and_Languages
    Please note that the above suggestion, given by egon, to go on and embed
    some scripting language, is a highly valuable one.

    This seems to be a common pattern, that configuration files quite often
    tend to evolve into full-fledged scripting languages, and if not noticed
    early enough (and either stopped immediately, or jumped full length to
    embed some already existing one), they like to become hacked together mess.
    For cases in point, see
    http://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule and
    http://www.lua.org/history.html. With that said, I believe Go library's
    template package seems to be a well executed and thought out
    compromise/middle ground, with the caveat that it won't fit all needs (but
    I think it'd be a good rule of thumb, that if package template is not
    enough for your needs, you should immediately start thinking not *whether*
    to embed a Turing-complete scripting language, but rather *which one*; or,
    stop immediately and require people to put any logic back into Go, maybe
    via some sort of plugin infrastructure).

    That said, just my $0.02.
    /M.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Shawn Milochik at Oct 21, 2014 at 9:12 pm
    One possibility is to do it similar to the way evaluations are done in
    MongoDB:
    http://docs.mongodb.org/manual/reference/operator/query/gt/

    For example: {"fieldX": {"lt": 20}}

    Also, to complement Egon's comments, if this is a messy problem, could you
    revisit your decisions that led to this requirement? Maybe you can change
    something somewhere else, making this unnecessary.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tamás Gulácsi at Oct 21, 2014 at 9:20 pm
    Otto (https://github.com/robertkrimen/otto) came to my mind and heka uses some simple expression lang.

    Go-search.org gave https://github.com/alecthomas/expr/blob/master/README.md for example.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Christian Neumann at Oct 23, 2014 at 8:43 am
    Thanks for all the helpful replies. I decided to use the configuration
    files for deployment settings only (dropping YAML for something
    INI-like), and instead try to make the development of plugins (written
    in Go; possibly other languages as I use net/rpc) as comfortable as
    possible.

    Christian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedOct 21, '14 at 8:49p
activeOct 23, '14 at 8:43a
posts8
users5
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase