In this example, what sort of predicate would you expect to be the result? Should it take three terms? Where should the output term go? These are things that an ffi will have to figure out if you don’t want to specify them yourself.
For sure, it is possible to create rust macros that will generate the required code to do what you want (assuming what you’d want here is automatic conversion from input term arguments to values, and automatically inferring output terms), but I don’t think that is a good thing. It means the ffi does a lot of implicit stuff, makes a lot of assumptions of how your foreign predicates should look and behave.
Furthermore, by eliminating unification altogether, it’d be impossible to do things like ‘unify this value, see if that works, and if not do something else’. Or, ‘unify these 3 terms to these 3 things, but roll back these unifications if any one of them fail’. Or, ‘take these two partially grounded terms and unify them’ which simply has no equivalent in terms of pure input-output functions. Or, ‘do x if this term reference contains a variable, but do y in case it is ground’, which, again, requires one to know something about term references, and not just the values they contain. Or, ‘do x if this term contains an atom, but y if this term contains a number’, which wouldn’t really work if the ffi did all value conversions for you. Etc.
Like it or not, term manipulation is at the heart of SWI-Prolog (and I assume other prologs as well) and hiding that means crippling the interface. I don’t know how GNU Prolog or SICStus get away with it, but I really don’t see the point. I rather stick closely to what actually happens, which means term manipulation.
That said, if you want something simpler, it is completely possible to use the ffi as it stands and build a macro layer on top of it which lets you specify functions without ever talking about terms or unification. I’ll leave that as an exercise for anyone motivated enough to do so.