mdiep / Logician

Logic programming in Swift
MIT License
194 stars 10 forks source link

Add >> operator for variables #36

Closed ferranpujolcamins closed 5 years ago

ferranpujolcamins commented 5 years ago

I added this operator which IMO comes handy when you need to add constraints to a specific variable. Now you can write:

let x1 = Variable() >> list
let x2 = Variable() >> list
let x3 = Variable() >> list

instead of:

let x1 = Variable()
list.append(x1)
let x2 = Variable()
list.append(x2)
let x3 = Variable()
list.append(x3)

The operator just adds the Variable to the list and returns the Variable, so you can assign it to a swift property in a single line.

ferranpujolcamins commented 5 years ago

Another example:

let solutions = solve { (variables: inout [Variable<Type>]) -> Goal in
    let x = Variable() >> variables
    let y = Variable() >> variables
    let z = Variable() >> variables

    return all(variables.map { $0.in(allTypes) })
        && distinct(variables)
        && x.subtype(of: baseClass)
        && y.subtype(of: baseClass)
        && z.notSubtype(of: baseClass)
}
mdiep commented 5 years ago

I don't love adding an operator for this, but I can definitely see that the ergonomics could be improved.

I was going to suggest a new type instead:

let solutions = solve { (context: Context) -> Goal in
    let x = context.addVariable()
    let y = context.addVariable()
    let z = context.addVariable()

    return all(variables.map { $0.in(allTypes) })
        && distinct(variables)
        && x.subtype(of: baseClass)
        && y.subtype(of: baseClass)
        && z.notSubtype(of: baseClass)
}

But now that I think of it, I don't think you should need to add variables to an array at all. It should be possible to get a list of all variables from the Goal and/or State and remove the static list:

let x = Variable()
let y = Variable()
let z = Variable()

let goal = all(variables.map { $0.in(allTypes) })
    && distinct(variables)
    && x.subtype(of: baseClass)
    && y.subtype(of: baseClass)
    && z.notSubtype(of: baseClass)
let solutions = solve(goal)
ferranpujolcamins commented 5 years ago

Thanks for the feedback!

Both thinks work for me! Shall we close the PR?

mdiep commented 5 years ago

Yeah, sounds good. 👍