I meant to reply to this earlier, but got sidetracked by a sudden need
to reinstall the OS. Better late than never, though...
2006-07-11, at 22.39, Andreas Kupries wrote:
>>>> Yet more tweaking. Start with (take 3) and make these>> additions/revisions:>> Restarting the discussion ...>> I have updated the online TIP #268 at tip.tcl.tk/268 to the take 4 > proposal,> with some consequences which were not mentioned before IIRC (C level> Tcl_PkgRequire changes, changes to the package unknown handler).
It seems to me that the Rationale section of the present proposal is
somewhat lacking: the only sentence in it that says anything about
ranges, multiple requirements, or preferrences really belongs in the
abstract, as it summarises *what* is proposed rather than *why* that is
proposed. The rest of the proposal does very little to provide the
missing information, and referring to the extensive e-mail discussions
about TIP#268 wouldn't be of much help either, as the multitude of
contradicting proposals discussed in parallel made it rather confusing.
I would therefore strongly urge that this lack of a rationale is
rectified before anyone considers calling for a vote on this TIP.
To aid in this, I have below tried to summarise (to the best of my
recollection) what problems these features were meant to address.
Unfortunately (for the TIP implementation) I cannot come to see that
the proposed mechanisms do a particularly good job at accomplishing
this :-(, so for both features the analysis ends up with
counter-proposals :-).
FEATURE 1: [package prefer]
This turned up as a modified form of the original threshold mechanism,
and seems to retain many of the complications suggested for this, even
though noone seems to have explained why. As far as I can tell, the
problem solved by this is simply that
Sometimes you want the bleeding edge version of a package,
and at other times you want something you can depend on.
That is perfectly well satisfied by the change in the package selection
logic, but the TIP also spends several paragraphs specifying that the
[package prefer] setting should be a one-way toggle, changeable from
"stable" to "latest" but not vice versa. Why? As I recall it, this was
suggested for [package threshold] out of a fear that packages would
start to fiddle with this setting to affect the loading of other
packages, but why this would be a plausible scenario was not made
clear. Given the weaker effect that [package prefer] has, I find it
unlikely that this would ever be a problem.
Counter-proposal:
1. Don't make [package prefer] stick in any mode.
Rationale: This is the null alternative. Anything else requires an
explicit reason.
2. Make [package prefer latest] the default setting.
Rationale: This is the current behaviour -- make one pass over the list
of versions, and pick the greatest -- and anyway something that would
either way effectively be the default for the some time to come, as
packages not specifically targetting 8.5 cannot declare themselves as
alphas or betas. It is also IMHO the behaviour which is most likely to
be preferred by Tcl programmers.
3. Don't introduce a environment variable for setting package
preferrence.
Rationale: This, too, is the null alternative. To do something else, an
explicit reason should be given.
I envision [package prefer stable] as a command that would be given by
_applications_ (not packages), especially applications that may be
installed and used by people not aware of the intricacies of the Tcl
package handling. The primary interest in such situations is that the
program should *work*, and the stable package selection logic makes the
optimal choices of packages to meet that end, given the information
available. In more hackerish situations, where the user can be expected
to manage some debugging, it should be OK to use the latest version
anyone has bothered to install.
FEATURE 2: Package requirements
Despite being a very complicated mechanism, this appears to address
only two issues:
(1) The ability to specify several major version as alternatives
in the request.
(2) The need to exclude specific buggy versions from consideration.
(1) does not add any relevant new functionality, as the proposed
package require foo 1.6 2
can just as well be coded
if {![catch {
package require foo 2
}]} then {
# Make definitions appropriate for foo version 2
} else {
package require foo 1.6
# Make definitions appropriate for foo version 1
}
-- certainly more roundabout, but better code, as it provides natural
places in which to handle differences between the two versions. (Since
these are two different major versions, there _should_ be some
incompatibility.)
The combination of ranges and multiple requirements provide a way of
accomplishing (2), but not in a particularly straightforward way. In
order to express "at least foo 1.1, but not 1.2" one has to say
something like
package require foo 1.1-1.2 1.3
which is not easily understood; it requires carefull study of the
[package vsatisfies] documentation to interpret correctly. Moreover,
the construction of requests such as this needs more knowledge about
the package versions than what was in the actual "at least foo 1.1, but
not 1.2" it was meant to express. What if the package author fixes the
1.2 fatal bug in 1.2.1 rather than 1.3 (a reasonable policy, if the
bugfix version does not contain any new features)? The package user
having to construct these requests can't know until the bugfix version
is out, but (s)he may well need to construct the request excluding 1.2
long before that, so effectively the idea of using ranges requires
programmers to take a guess.
Another problem with the proposed range mechanism is that is allows,
even encourages, writing requests that don't make sense unless the
package requested anyway violates normal versioning practices. Why
should anyone want to request a bounded range such as 1.4-1.8 only --
what is wrong with 1.8, 1.9, and *all* subsequent versions? Since they
all carry the same major version they should be backwards compatible!
Allowing requests that only consist of bounded ranges makes less sense
than allowing several "a" and "b" separators in a version.
The *worst* kind of range is however the "min-unbounded" ranges. Recall
that
Major version increments signal incompatible changes to a package.
The "min-unbounded" request by definition selects loading versions of a
package which the author at the time of writing has no knowledge of,
and from which (s)he has no reason to expect compatibility with
anything (s)he has knowledge of, which means making use of this feature
is a plain and simple request for trouble. One might as well equip
[package require] with a "-glob" option such that [package require
-glob foo*] will load the lexicographically largest package whose name
matches the pattern "foo*", because both are equally prone to rendering
the code unportable. (Yes, there is [package require $pkg] without a
version that will load any version whatsoever of a package, but that is
(i) useful in interactive sessions, (ii) a legacy feature, and (iii)
minimalistic. Min-unbounded ranges are none of those things.)
Counter-proposal:
The syntax for [package vsatisfies] shall be left unchanged, except
that it should accept the new forms allowed for package versions. The
[package require] command should have three forms: the normal form
package require $name $version ?option ...?
and the two legacy forms
package require $name
package require -exact $name $version
where the -exact legacy form can be distinguished from a possible
five-word case of the normal form by the fact that the fifth word
begins with a digit.
In order to fulfill (2), it is sufficient to implement the option
-not $version
whose meaning is that the listed $version ([string equal] comparison)
should not be chosen, even if it otherwise would best fit the given
search criteria. The -not option may be given several times, with the
effect that all listed versions are excluded from the request.
[End proposal.]
Example:
package require Tk 8.4 -not 8.4.13
An advantage of this syntax is that it allows for other options that
may control other aspects of package loading. Some possibilities that
come to mind are:
-prefer latest|stable
Override the [package prefer] setting for this [package require].
-exact
Same as the legacy -exact option. Alternatively, one could imagine a
-matching vsatisfies|exact
option, if the "-option value" form is considered preferable.
-or $version
To allow (but IMHO against better judgement) for the loading mechanism
to choose between several major versions. The example above can thus
become
package require foo 1.6 -or 2
-noload
Do everything short of evaluating the [package ifneeded] script, and
return the version it would have loaded. *Despite what the [package]
manpage says*, this would be different from [package present] in that
it would make use of the [package unknown] handler if it cannot
otherwise find the requested package. A suitable "-option value"
variant would be
-load $boolean
A CURIOUSITY: [package vsatisfies] is not transitive
With the Tcl implementation in the TIP, one gets the following:
% {package vsatisfies} 8.5a2 8.5
1
% {package vsatisfies} 8.5 8.5a5
1
Yet:
% {package vsatisfies} 8.5a2 8.5a5
0
I wouldn't consider this a fatal flaw -- I'm not even certain it counts
as a flaw -- but it should probably be pointed out. The catch is that
8.5 counts as 8.5.0 when occurring as a left operand, but as 8.5a0 when
occurring as a right operand.
Lars Hellström
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Tcl-Core mailing list
Tcl-...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tcl-core