Kryptix
Kryptix

Reputation: 197

Equivalent in Dart

I've just started exploring Dart language and I wanted to test an existing code that I wrote in Java as given:

public interface Condition {

    Condition FALSE = facts->false;

    Boolean evaluate(Fact<?> fact);
    
    default Condition and(Condition other) {
        return fact-> this.evaluate(fact) && other.evaluate(fact);
    }

    default Condition or(Condition other) {
        return fact-> this.evaluate(fact) || other.evaluate(fact);
    }
}

And the caller calls it as:

    @Test
    public void testCondition() {
        String str = "A String";
        Condition a = fact -> !str.isBlank();
        Condition b = fact -> str.contains("A");
        a.and(b);
    }

A complete test class that makes use of this is :

public class AnonymousLoopTest {
    @Test
    public void test() {
        RulesEngine rulesEngine = new InferenceRuleEngine();
        List<Name> names = NamesFactory.fetchNames();
        Rules rules = new Rules();
        Facts facts = new Facts();
        AtomicReference<Integer> countRef = new AtomicReference<>(1);
        names.forEach(personName -> {
            facts.put("name-" + countRef.get(), personName);
            countRef.set(countRef.get()+1);
            Condition condition = fact -> !personName.name().isEmpty();
            //Hack the comparator logic of DefaultRule/BasicRule in order to override its internal logic as below.
            //This is needed to register our Rule with Rules which uses a Set<Rule> to register new Rules
            //with the comparator logic written in BasicRule.
            Rule nameRule = new RuleBuilder((o1, o2) -> personName.name().compareTo(o1.getName()))
                    .when(condition).then(action -> System.out.println("In Action:" + personName)).build();
            rules.register(nameRule);
        });
        rulesEngine.fire(rules, facts);
    }

}

record Name(Integer id, String name){}

class NamesFactory{
    static List<Name> fetchNames(){
        return List.of(new Name(10, "Sara"), new Name(20, "Zara"), new Name(30, ""),new Name(40, "Lara"));
    }
}

The condition is used by when() method. In the given example the blank name will be filtered out. The other three names will be printed.

I was trying to write and equivalent in Dart but I'm just stuck. What is the way to write this code in Dart?

Upvotes: 0

Views: 386

Answers (1)

lrn
lrn

Reputation: 71743

That looks like something I'd do by:

typedef Condition = bool Function(Fact);
bool falseCondition(Fact _) => false;
extension ConditionComposition on Condition {
  Condition operator &(Condition other) => (Fact fact) => this(fact) && other(fact);
  Condition operator |(Condition other) => (Fact fact) => this(fact) || other(fact);
  Condition operator ~() => (Fact fact) => !this(fact);
}

If you insist on having a wrapper class for the function objects, I'd do it as:

class Condition {
  static const Condition falseCondition = Condition(_kFalse);

  final bool Function(Fact) _test;
  const Condition(bool test(Fact fact)) : _test = test;
  
  bool evaluate(Fact fact) => _test(fact);

  Condition operator &(Condition other) => Condition((fact) => 
      this.evaluate(fact) && other.evaluate(fact));

  Condition operator |(Condition other) => Condition((fact) => 
      this.evaluate(fact) || other.evaluate(fact));

  static bool _kFalse(_) => false;
}

but a class seems overkill for something which really is just a simple function. Dart has first class functions.

You can use the former version as:

  test("test Condition", () {
    var str = "A String";
    Condition a = (fact) => str.isNotEmpty();
    Condition b = (fact) => str.contains("A");
    var both = a & b;
    expect(both(someDefaultFact), true);
  }

Upvotes: 2

Related Questions