# Simple Rule Engine

**URL:** https://discourse.julialang.org/t/simple-rule-engine/59125
**Category:** General Usage
**Tags:** functions
**Created:** [April 12, 2021, 4:47pm UTC](https://discourse.julialang.org/t/simple-rule-engine/59125 "2021-04-12T16:47:16Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Dustin\_Hess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dustin_hess/32/11957_2.png) [@Dustin\_Hess](https://discourse.julialang.org/u/Dustin_Hess)
#### Post date: [April 12, 2021, 4:47pm UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/1 "2021-04-12T16:47:16Z")

</div>

Hi All  
I am teaching myself some design patterns currently I am trying to build a simple Rule Engine. I ran upon an issue where I would like to call many functions ( rule set) while passing them the same parameters. In C# I could just define an IRule interface, then List methods subscribing to the interface. Since in Julia objects and their behavior very decoupled I am not sure how to do this. I thought about storing the function in an array then looping over them, but reading this post [Type Inference From a List of Functions](https://discourse.julialang.org/t/type-inference-from-list-of-functions/24538) means I need to store function references in a tuple( immutable) to loop over so I don’t loose the type info ( I don’t want dynamic dispatching on the rule set).  
What would be the Julia way to have list of functions that can be called depending on a whole set of behaviors to apply to an object. I would also like the modify the list of Rules depending on what is acting on the object. See a contrived example below. I have no structs here. You could imagine this in the context of game, lets say where you want modify a players health based on various interactions with other player, world, enemys etc…

```julia
function foo(x::Int, y::Int)
    return x + y
end

function foo1(x::Int, y::Int)
    return x * y
end

function calc_health(x::Int, y::Int, health::Int)

    func_arr = [foo, foo1]

    for i in eachindex(func_arr)
        health += func_arr[i](2,3)

    end
    return health
end

function calc_health2(x::Int, y::Int, health::Int)

    func_arr = (foo, foo1)

    for i in eachindex(func_arr)
        health += func_arr[i](2,3)
    end
    return health
end

@time begin
    calc_health(2,3,0)
end

@time begin
    calc_health2(2,3,0)
end

@time begin
    foo(2,3) + foo1(2,3)
end
```

---

<div class="post-metadata">

### Author: ![zgornel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zgornel/32/217487_2.png) [@zgornel](https://discourse.julialang.org/u/zgornel)
#### Post date: [April 13, 2021, 10:04am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/2 "2021-04-13T10:04:15Z")

</div>

> [@Dustin\_Hess](#):
>
> You could imagine this in the context of game, lets say where you want modify a players health based on various interactions with other player, world, enemys etc…

This seems like functionality that can be handled better by automata or [behavior trees](https://github.com/fabid/BehaviorTree.jl), rule engines usually just check for the validity of the rule set (i.e. all or some of the rules have to be matched). Perhaps [MLStyle](https://github.com/thautwarm/MLStyle.jl) may help, it supports advanced pattern matching functionality and dynamic behavior (apply function based on the type of match) can be implemented quite easily.

---

<div class="post-metadata">

### Author: ![Dustin\_Hess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dustin_hess/32/11957_2.png) [@Dustin\_Hess](https://discourse.julialang.org/u/Dustin_Hess)
#### Post date: [April 21, 2021, 2:00am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/3 "2021-04-21T02:00:59Z")

</div>

Thanks for the reply. I was busy at work so I am just now revisiting. I will check out the packages you mentioned and report back.

---

<div class="post-metadata">

### Author: ![Dustin\_Hess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dustin_hess/32/11957_2.png) [@Dustin\_Hess](https://discourse.julialang.org/u/Dustin_Hess)
#### Post date: [April 30, 2021, 2:47am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/4 "2021-04-30T02:47:15Z")

</div>

Thanks for the reply things were simple enough I implemented a barrier function pattern to construct the Tuple of rules that I can call from a Dict that store references to each function type. This barrier function with then passes this Tuple to correct function to loop over. Works well is quite optimized.

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [April 30, 2021, 4:45am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/5 "2021-04-30T04:45:37Z")

</div>

You’re essentially describing how [DynamicGrids.jl](https://github.com/cesaraustralia/DynamicGrids.jl) works, given that you want to write a list of rules that are applied to some object in sequence. DynamicGrids.jl applies each rule to every cell in an array, one rule after the other. But the principle is general.

From my experience writing it, you don’t want rules to be an array of functions, but a tuple of _objects_ that hold rule parameters and define the same common method that runs them. You then apply each rule in the tuple to the main object, using recursion instead of a loop. This will be type stable with different objects, a loop wont be.

Defining a new rule is then defining a struct and a method that dispatches on it. This is the most reusable, Julian way to do this kind of thing. Using an object, if your rule has parameters, they can be modified. If you use a function, they can’t - and your rules are problem-specific rather than generic.

---

<div class="post-metadata">

### Author: ![Dustin\_Hess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dustin_hess/32/11957_2.png) [@Dustin\_Hess](https://discourse.julialang.org/u/Dustin_Hess)
#### Post date: [April 30, 2021, 5:16am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/6 "2021-04-30T05:16:32Z")

</div>

@Raf Thanks I will take a look at DynamicGrids.jl. Would you mind posting a toy example? That said yes the rules were very specific and short by design. My application is pretty small so I think mostly it doesn’t matter for my use case. However, I may go rewrite in more general as you describe above. Any small contrived example would be welcome. In the mean time I will check out your pkg.

---

<div class="post-metadata">

### Author: ![mschauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mschauer/32/13946_2.png) [@mschauer](https://discourse.julialang.org/u/mschauer)
#### Post date: [April 30, 2021, 5:19am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/7 "2021-04-30T05:19:52Z")

</div>

Might that you can use FunctionWranglers as in [Event handler - #5 by tkf](https://discourse.julialang.org/t/event-handler/59937/5)

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [April 30, 2021, 5:23am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/8 "2021-04-30T05:23:53Z")

</div>

If you use functions, still make it a `Tuple` of functions, and use recursion. Unless you don’t care about performance.

Here’s a toy example.

```julia
function applyfuncs(obj, funcs::Tuple) = 
    newobj = funcs[1](obj)
    applyfuncs(newobj, Base.tail(funcs))
end
applyfuncs(obj, funcs::Tuple{}) = obj

obj = ... # the object you want to update with rules
updated_obj = applyfuncs(obj, (func1, func2))

```

I would also make this functional, in that each function returns a new object, instead of writing to the existing object. Then everything can be immutable and fast, and you don’t have to think about state.

And with objects:

```julia
function applyrules(obj, rules::Tuple) = 
    newobj = runrule(obj, rule[1])
    applyrules(newobj, Base.tail(rules))
end
applyrules(obj, rules::Tuple{}) = obj

struct Rule1 end
runrule(obj, rule::Rule1) = 2 * obj # Some fixed rule

struct Rule2{P}
    param::P
end
runrule(obj, rule::Rule2) = obj * rule.param # A rule with a parameter

obj = ... # the object you want to update with rules
updated_obj = applyrules(obj, (Rule1(), Rule2(0.5)))

```

---

<div class="post-metadata">

### Author: ![Dustin\_Hess](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dustin_hess/32/11957_2.png) [@Dustin\_Hess](https://discourse.julialang.org/u/Dustin_Hess)
#### Post date: [April 30, 2021, 5:33am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/9 "2021-04-30T05:33:43Z")

</div>

@Raf Very nice! Thanks! your example is nice and clear. I will rewrite in this manor as you describe. I will post back and let you know how it goes. I am still learning quite a bit on designing things. Cheers have a nice weekend.

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [April 30, 2021, 5:35am UTC](https://discourse.julialang.org/t/simple-rule-engine/59125/10 "2021-04-30T05:35:43Z")

</div>

No problem! I just added an example above with objects as well. I recommend objects 🙂
