Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-08-11 11:31:58


Beman Dawes <bdawes_at_[hidden]> writes:

> At 07:39 PM 8/10/2003, David Abrahams wrote:
>
> >Beman Dawes <bdawes_at_[hidden]> writes:
> >
> >> At 08:06 PM 8/9/2003, David Abrahams wrote:
> >>
> >> >As a user of the filesystem library, I am having the experience that
> >> >obvious things are hard to find, and the docs are much harder to
> >> >understand than they ought to be. The use of creative naming really
> >> >gets in the way. For example, the term "complete" is never defined
> >> >anywhere.
> >>
> >> It is defined by the is_compler() returns clause.
> >
> >I really think you have to do better than burying it in the returns
> >clause of a single function's docs. The term is used all over the
> >library docs.
>
> I've added "complete path" and "relative path" to the Definitions, so
> readers will get introduced to the terms much earlier. Also added a
> FAQ entry to address the "why isn't it called absolute" questions.
>
> To address some of your other comments, I also changed to tutorial to
> no longer use a namespace alias, and to introduce the concept of
> canonical form. The tree/root/branch/leaf naming metaphor is now
> mentioned in several places early on. The organizational structure of
> "lexical operations in path.hpp, filesystem operations in
> operations.hpp" is presented much earlier.
>
> >Oh, and initial_directory points nowhere in operations.html: it's
> >"initial_path".
>
> Fixed. Also fixed in path.htm.

Thanks for all that.

> >> There were lengthy discussions on the list of this and other naming
> >> issues during development, during review, and during the resolution
> >> of review issues. Many people had fairly strong views.
> >
> >I could accept the idea that some of the naming choices were
> >neccessary, but when you add the choice of "basename" into the mix,
> >which flatly contradicts existing practice, it gives the impression of
> >being arbitrarily inventive.
>
> I'm not enamored with "basename". I'd like to hear from Vladimir on
> that, however, as those functions were contributed by him.

We'll have to wait for him to come back from his honeymoon in late
August :o)

> >> IIRC, the idea that is_absolute( "/foo" ) was false on some
> >> operating systems was impeded by long-held beliefs.
> >
> >Err, let's see... strings can be implicitly converted to paths, and
> >the implicit conversion treats the string as a "portable generic path
> >format", right? So when is "/foo" not absolute/complete? Is not foo
> >the name of the root? Oh, after much crawling backwards through the
> >docs, I see what has been done here... I suppose it's needless to
> >say, but I would've chosen a different approach. The idea that
> >is_complete(path(some_string)) returns different values on different
> >systems undermines the notion that paths are portable and generic.
>
> The design attempts to balance the needs of those who wish to write
> portable programs and would prefer totally generic formats, with those
> who need to interact with users, and thus require native formats.

For that, you have native string formatting and construction from
native path strings. I can't understand the point of having a
"portable generic path format" if its portability and genericity is
compromised. Why not just do everything in terms of native paths in
that case? Trying to cater to people who want their portable generic
format to look like their native format just makes everything much
more complicated and finally waters down the distinctions until they
have little value.

> >If I were king, the portable, generic version of windows-native
> >"c:/foo" would be "/c/foo" and the portable generic version of
> >windows-native "/foo" would be *current_path().begin()/"foo". Is
> >there a reason that approach was rejected?
>
> Yes, it had five or six different problems IIRC, although some of
> them can be fixed by adding additional syntax. For example, the
> ambiguity in "/c/foo" - is it a relative path starting with a
> directory named "c" or a complete path to the c drive

Read as a generic path according to my system, it is not a relative
path because it starts with a slash. That's simple and there should
be no confusion assuming you know you're not looking at a native format..

> - can be dealt with via additional syntax.

No additional syntax is needed.

> Early implementations of the library used a lot more inventions for
> design aspects like the generic path grammar. As time went on many
> of them were removed because they just didn't work well in actual
> code.
>
> >...
> >What do you mean by semantic portability? Isn't it undermined by the
> >variability of path("/foo").is_complete()?
>
> Yes, but that gets balanced against the other design goals.

What other goals and how do they balance out?

> >> >The difference between is_empty(ph) and ph.empty() is too slight,
> >> >IMO, for their differing semantics. IMO it's not useful to have
> >> >one function which reports both empty files and empty directories
> >> >- the implications of the two are much too different.
> >>
> >> Early versions of the library did provide the finer granularity of
> >> is_empty_file(ph) and is_empty_directory(ph), but they didn't work
> >> out in practice, and we changed to a simpler set of non-compound
> >> functions. Remember that the library was in private use for quite a
> >> while before the public review, and we got to see what worked and
> >> what didn't. Compound conditional functions definitely fell in the
> >> "didn't" category.
> >
> >It's easy for people that use a library in private for a long while as
> >it evolves to become comfortable with its conventions and
> >philosophy. That doesn't mean it will be approachable to people who
> >haven't seen it before.
>
> Yes, I've seen that many times. What happened with the filesystem
> library however was the reverse. Over time, it became obvious that
> some of the initial conventions and philosophy's didn't work well in
> practice and I became less comfortable with them. There was then a
> long period of simplification resulting in a more basic library that
> seems to work well in practice.
>
> >Regardless, I still think the empty/is_empty thing is very confusable.
> >
> >void f(path p)
> >{
> > if (p.is_empty()) // whoops, syntax error -- how do I fix it?
>
> Yes, that is very deliberate. Thomas Witt pointed out that by using
> somewhat different names, such coding errors turn what otherwise would
> be a silent runtime error into a noisy compile-time error.

I'm not suggesting that the names should be more similar; I'm
suggesting they should be more different.

> > {
> > ... // could be p.empty() or is_empty(p)
> > // but the two predicates mean completely
> > } // different things
> >}
>
> Yes, and hopefully the compile error will cause the user to look at
> the docs to determine which is which.

Hopefully a library is designed so that the chances that the user
will write correct code the first time are maximized.

> By the way, early versions of path didn't supply path::empty(). That
> caused complaints that people had to write p.string().empty(), which
> was seen as too convoluted.

How about operator safe_bool() or p.is_null()...?

> Thanks for all the comments. Hopefully the documentation changes
> have addresses the bulk of them.

I'll take a look.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk