After thinking a lot about this, thank you so much for this suggestion !
It was right under my nose, but I could not see it.
I have pushed a new version with the following fix:
- resulting quantities have now the form
Value*Quantity[Unit]
.
That means your example now works:
?- qeval(Speed is metre / second ), Speed = Value*Units.
Speed = 1*kind_of(isq:length/isq:time)[si:metre/si:second],
Value = 1,
Units = kind_of(isq:length/isq:time)[si:metre/si:second].
I continue to use dicts for the internal of the libraries because they are very convenient to work with as an implementor.
But I think I was reluctant to let users interact with dicts because of the usual pitfalls around dicts.
Now, it remains that reverting the two statements: Speed = Value*Units, qeval(Speed is metre / second )
does not work, because I can’t know when parsing Value*Units
that Units
should be a unit and not a value.
Currently, I disambiguate by wrapping the variables with functors like this:
?- Speed = Value * unit Unit, qeval(Speed is metre / second ).
Speed = 1*unit (si:metre/si:second),
Value = 1,
Unit = si:metre/si:second.
?- qeval(quantity Speed =:= metre / second ).
Speed = 1*kind_of(isq:length/isq:time)[si:metre/si:second].
I’m not sure I fully understand your suggestion.
The problem I see is that would introduce nondeterminism during parsing, and that is not an option.
When encountering a variable, I would not know if the variable is a:
- value
- unit
- quantity[unit]
- value*quantity[unit]
Those are the 4 possibilities.
First of all, I have removed the use of u:
or q:
qualifiers.
For units and quantities like si:metre
or isq:speed
, the original libraries organized them using c++ namespaces, so that users could selectively import the units they wanted.
I thought of doing the same by piggy backing on swi-prolog module system, but I have not yet really implemented this.