|
From: <dg...@ni...> - 2008-12-12 05:11:18
|
...Revise [package ifneeded] so that...
>> Any package that doesn't have an all lowercase name will
>> automatically make itself available in both original
>> and all lowercase naming variants.
A few loose ends...
This scheme also requires a change in the [package unknown]
contract. This is common to every scheme with aims similar
to TIP 339, because the handler has to conform to the new
expectation that it will seek out [package ifneeded] evaluations
from all case variants before giving up and permitting [package
require] to report "not found". There's no case tolerance scheme
that can escape that. (Well, none other than calling the
[package unknown] handler 2**[string length $name] times with
all the case variants!)
The other hole I can see in what I sketched is the mode where
[package require] succeeds because the requirement is met by an
already loaded package. I *think* that omission is what you're
getting at below. Or maybe the combination of these two matters?
Quoting "Andreas Kupries" <and...@ac...>:
> The only packages not handled by the above are those going through the C
> interface, i.e. Tcl_PkgRequire() and variants, to register themselves.
...but unless I'm missing something, this has nothing at all
to do with C interface vs. Tcl interface.
> These can be handled however as well, by redirecting the
> '::tcl::package::require' implementation.
Following your lead, try this:
proc ::tcl::package::Require {name args} {
set lcname [string tolower $name]
# Required name not all lower case.
# No collision with phony entries possible.
# Use the normal subcommand.
if {$lcname ne $name} {
return [require $name {*}$args]
}
if {[package provide $name] ne {}} {
# Requested package is already provided.
# Whether that's real or phony, the
# normal subcommand can handle it right
return [require $name {*}$args]
}
# Tricky case. $name has not been provided,
# but some case variant might have been, in
# some way that avoided contact with the
# [package ifneeded] wrapping trickery. So
# search for such a thing...
foreach n [lsearch -all -inline -nocase [package names] $name] {
set v [package provide $n]
if {$v ne {}]} {
# Fill in the missing phony entry
package provide $name $v
break
}
}
# Any missing match is now filled in, so
# the normal subcommand is now ok to call,
# and permit it to probe [package ifneeded]
# entries and invoke [package unknown] handlers.
return [require $name {*}$args]
}
[package present] needs the same thing.
As I've sketched this, there's one troubling implication,
and that is there is one group who are measurably
worse off, and that is the authors of packages who
have chosen all lowercase names. Up to now, they've
been in the same situation as any package author. They
need their users to require them by exactly the
correct name, and have to worry about collision with
another author who chose precisely the same name.
After this revision, the packages with all lowercase
names now have to worry about colliding with the
whole case-insensitive set of matching package names,
a bigger potential for collision. ("trofs" has to
worry about collision with "Trofs") In contrast,
everyone else is likely better off, with users
now able to require them in all lowercase form,
so long as their name is unique in that broader
collection ("Itcl" gets all those users who can
only spell "itcl"), but even if there is a collision
preventing that, at least they are no worse off and
the precisely correct requires from before continue
to work.
So the incentives push package authors mildly *away*
from using all lowercase names, while encouraging
[package require] callers to make use of all lowercase
names. I think since the number of package users should
be much larger than package providers, it makes most
sense to give the typing convenience to them. The other
impact is to encourage all package authors to aim for
names that are globally unique even without case to
distinguish. And that's a helpful preparation step
for conversion to Tcl Modules.
DGP
|