Please include the following corrections to the core standard.
divF(x,y) = resultF(x/y),rndF) if y\=0 = undefined if x=0,y=0 = zero_divisor if x\=0,y=0This mistake is apparently inherited from the first LIA standard.
I have been told that these changes cannot be put into the corrigendum because they would make existing conforming implementations non-comforming. It is, however, the whole point of a "corrigendum" to correct mistakes, and inevitable that implementations may have to change to implement the corrections.
In the new section on min/2 and max/2, please do not refer to float_overflow when talking about to the case that an integer is not exactly representable as a float! As defined in 18.104.22.168, float_overflow occurs when a result is greater than fmax, which is not the case we want to capture here.
See 2006 Mailing list discussion for a previous discussion on that topic.
Whether such an error is needed is debatable. In the suggested case of the open/3 predicate being called with an instantiated output argument, the need for a new error goes away when we imagine that the check is performed after the new stream has been created, and just before it is unified with the result argument. Without check, this unification would fail, and it is this failure that we want to supplant with an approriate error. Elsewhere, such a situation would be signaled via a type_error (if types are different) or a domain_error (if types match, but value differs from what's expected). So why not
% newly opened stream would be unified with 99 -> type error ?- open(f1, read, 99). type_error(stream, 99) % newly opened stream would be unified with other stream -> domain error ?- open(f1, read, S), open(f2, read, S). domain_error(stream, $stream(f1))
It has been argued that in some implementations open(t,write,S), close(S), open(t,write,S2), S==S2 may succeed, and thus the error case does not replace a failure. I hope it is undisputed that the intended semantics in that case is indeed a failure (even though the standard leaves it unspecified), and not to implement this failure is merely an oversight.
A case for the "uninstantiation" error can be made, however, in a completely different situation, where a variable is used as a quasi-identifier in a quantifier-like construct, e.g.
?- Y=foo, setof(X, Y^p(X,Y), L).One could argue that this is likely to be a mistake and should be flagged by an "uninstantiation" error for Y. In this context, however, the name "uninstantiation" is unhelpful. A type_error(variable) would be quite appropriate, since these variables are not meant to ever become instantiated, so being a "variable" is their final destiny or, arguably, their "type".
Another (non-ISO) argument that has been made for why we need this error is a predicate that attaches attributes to variables, but is called with a non-variable, e.g. put_attr(foo,attrname,attrval). There is, however, no reason why this should not be equivalent to put_attr(X,attrname,attrval),X=foo and behave accordingly, i.e. succeed or fail according to the semantics of the attribute.
The pi/0 arithmetic function is problematic because of its return type. In a basic ISO system, the return type is simply float. A system that provides more than one representation for real numbers (e.g. different floating-point representations, or both floats and intervals) must settle for one of these types as the return type for pi (because it is argument-less, it cannot be polymorphic). It would have to be the one with the highest precision because it then can be converted to a lower-precision type as needed (whereas missing precision cannot be recovered later).
What this means, however, is that a multi-representation system cannot really commit to pi/0 returning the float-type (which may not have enough precision). Or, if it did, it would have to provide additional variants to return the higher precision representations (pi_binary_128/0, pi_decimal_64/0 etc).
A similar problem exists with regard to the type of literal constants such as 1.0. In a system with multiple representations, possible solutions are
For the case of pi, the easiest way to solve the problem is to provide a function pi/1, where pi(X) is equivalent to pi*X computed with the precision of X (but at least the smallest floating point precision, to avoid biblical surprises like 3=:=pi(1)).
I assume this is meant to be a difference-list version of term_variables/2. Difference-list-variants of list-constructing predicates can be a good idea (findall/3 comes to mind, but also atom_codes/2 etc), but as the standard does not systematically provide these, it seems there should be a special reason for providing it in this case - what is it?
Apparently, the use case is the implementation of bagof/setof. The arguments made below still hold.
As opposed to the other examples quoted above, a difference-list version of term_variables/2 is a particularly bad idea because
term_variables(T1, Vs, Vs1), term_variables(T2, Vs1, ).is not the same as
term_variables(T1-T2, Vs).because it is supposed to return a duplicate-free variabe list. The predicate invites bugs by suggesting a usage that is unlikely to give the expected results.
Note that the correct way to augment a term-variable-list is
term_variables(T1, Vs1), term_variables(Vs1-T2, Vs).
% top.pl :- include('somedir/include_p'). % somedir/include_p.pl :- ensure_loaded(p). % somedir/p.pl p.and we compile top.pl. What current directory should we expect when encountering the ensure_loaded(p) directive in somedir/include_p.pl? With pure include-semantics, the above code does not work: the ensure_loaded behaves as if it occurred within top.pl directly. SWI Prolog, YAP and ECLiPSe behave that way. SICStus (and similar directives in C) behave the other way, i.e. certain pathnames in included files are relative to the includee's not the includer's location. However, the current directory is still the includer's, so the situation is a bit confusing. A discussion from the ECLiPSe point of view is in bug 678.