May 19, 2016
On Wednesday, 18 May 2016 at 20:10:09 UTC, Jonathan M Davis wrote:
> So, while we do have enforcement of how ranges _can_ be used, we don't have enforcement of how they _are_ used, and I don't expect that we'll ever get that.

It would help if there was documented standard testing procedure (and used for all algorithms).
May 19, 2016
On Wednesday, May 18, 2016 22:23:45 jmh530 via Digitalmars-d-announce wrote:
> On Wednesday, 18 May 2016 at 20:10:09 UTC, Jonathan M Davis wrote:
> > At this point, if anyone ever calls front with parens, they're doing it wrong.
>
> Is this true of all @property functions? Should this be noted in the spec? Should it be an error? If it shouldn't be an error, is it really such a bad thing?

It makes _no_ sense to use parens on a typical @property function. The whole point of properties is that they act like variables. If you're marking a function with @property, you're clearly indicating that it's intended to be treated as if it were a variable and not as a function. So, in principle, if you're using parens on a property function, the parens should be used on the return value and _not_ the function. That being said, we've never ended up with property enforcement of any kind being added to the language.  So, while the compiler _should_ require that an @property function be called without parens, it doesn't. And without that requirement, @property really doesn't do much. If we want properties to work where the type is a callable like a delegate (e.g. you have a range of delegates, so front returns a delegate), then it's going to need to change so that using parens on an @property function actually uses the paren on the return value, and without that @property is nothing more than documentation. So, right now, @property is pretty much just documentation about how the person who wrote the code expects you to use it. It doesn't really do anything. It does have some affect with regards to typeof, but overall, it does nothing.

Now, that being said, when I was talking about calling front with parens, I wasn't really talking about property functions - though front is frequently a property function. Rather, my point was that isInputRange requires that this code compile:

        R r = R.init;     // can define a range object
        if (r.empty) {}   // can test for empty
        r.popFront();     // can invoke popFront()
        auto h = r.front; // can get the front of the range

If that code compiles with a given type, then that type can be used as an input range. That API is in the API defined for input ranegs. It does _not_ call front with parens nor does it call empty with parens. Rather, it explicitly uses them _without_ parens. So, they could be property functions, or variables, or normal functions that just don't get called with parens, or anything else that can be used without parens and compile with that code. So, if you write a range-based algorithm that uses parens on empty or front, then you're writing an algorithm that does not follow the range API and which will not work with many ranges.  The range API does _not_ guarantee that either front or empty can be used with parens. It guarantees that they can be used _without_ them. So, if your code ever uses parens on front or empty, then it's using the range API incorrectly and risks not compiling with many ranges.

- Jonathan M Davis

May 19, 2016
On Thursday, May 19, 2016 09:05:53 Kagamin via Digitalmars-d-announce wrote:
> On Wednesday, 18 May 2016 at 20:10:09 UTC, Jonathan M Davis wrote:
> > So, while we do have enforcement of how ranges _can_ be used, we don't have enforcement of how they _are_ used, and I don't expect that we'll ever get that.
>
> It would help if there was documented standard testing procedure
> (and used for all algorithms).

We really need solid tools for testing an algorithm with a variety of ranges to verify that it's doing the right thing as well as tools to test that a range behaves how ranges are supposed to behave. The closest that we have to that is that std.range has some internal helpers for testing ranges, but they're not that great, and I don't think that any of it's public. And we don't have anything for testing that a range acts correctly - just that it follows the right API syntactically with the minimal semantic checking that can be done with typeof. So, there's work to be done. I'd started some of it a while back, but I never got very far, and no one else has done anything like it AFAIK.

- Jonathan M Davis

May 19, 2016
On Thursday, 19 May 2016 at 12:10:36 UTC, Jonathan M Davis wrote:
>
> [snip]

Very informative, as always.

I had not realized the implication of front being called without parens, such as front being something that isn't an @property function (esp. variable). Are there any ranges in phobos (you can think of) that do this?
May 19, 2016
On 5/17/16 8:36 PM, H. S. Teoh via Digitalmars-d-announce wrote:
> On Tue, May 17, 2016 at 08:19:48PM +0000, Vladimir Panteleev via Digitalmars-d-announce wrote:
>> On Tuesday, 17 May 2016 at 17:26:59 UTC, Steven Schveighoffer wrote:
>>> However, it's perfectly legal for a front function not to be tagged
>>> @property.
>>
>> BTW, where is this coming from? Is it simply an emergent property of
>> the existing implementations of isInputRange and ElementType, or is it
>> actually by design?
>
> This is very bad. The range API does not mandate that .front must be a
> function. I often write ranges where .front is an actual struct variable
> that gets updated by .popFront.  Now you're saying that my range won't
> work with some code, because they call .front() (which is a compile
> error when .front is a variable, not a function)?

My goodness no!

People, please, my point is simply that is(typeof(someRange.front) == ElementType!(typeof(someRange))) DOESN'T ALWAYS WORK.

Here is the (long standing) definition of isInputRange:

template isInputRange(R)
{
    enum bool isInputRange = is(typeof(
    (inout int = 0)
    {
        R r = R.init;     // can define a range object
        if (r.empty) {}   // can test for empty
        r.popFront();     // can invoke popFront()
        auto h = r.front; // can get the front of the range
    }));
}

Not there is no check for is(typeof(r.front)) to be some certain thing.

So this is a valid range:

struct AllZeros
{
    int front() { return 0; }
    enum empty = false;
    void popFront() {}
}

Yet, is(typeof(AllZeros.init.front) == int) will be false. This is the line of code from the article that I suggested to add the parens to. Because in that particular case, string.front is a function, not a field. The code in question is NOT GENERIC, it's just showing that string.front is not the same as string[0]. It's very specific to string.

>
> In the old days (i.e., 1-2 years ago), isForwardRange!R will return
> false if .save is not marked @property. I thought isInputRange!R did the
> same for .front, or am I imagining things?  Did somebody change this
> recently?

You are imagining that someInputRange.front ever required that. In fact, it would have had to go out of its way to do so (because isInputRange puts no requirements on the *type* of front, except that it returns a non-void value).

But you are right that save did require @property at one time. Not (In my opinion) because it meant to, but because it happened to check the type of r.save against a type (namely, that .save returns its own type).

At the same time, I fixed all the isXXXRange traits so @property is not required anywhere. In particular, isRandomAccessRange required r.front to be @property, even when isInputRange didn't (again, IMO unintentionally). Here is the PR: https://github.com/dlang/phobos/pull/3276

-Steve
May 19, 2016
On Thu, May 19, 2016 at 09:21:40AM -0400, Steven Schveighoffer via Digitalmars-d-announce wrote:
> On 5/17/16 8:36 PM, H. S. Teoh via Digitalmars-d-announce wrote:
> > On Tue, May 17, 2016 at 08:19:48PM +0000, Vladimir Panteleev via Digitalmars-d-announce wrote:
> > > On Tuesday, 17 May 2016 at 17:26:59 UTC, Steven Schveighoffer wrote:
> > > > However, it's perfectly legal for a front function not to be tagged @property.
> > > 
> > > BTW, where is this coming from? Is it simply an emergent property of the existing implementations of isInputRange and ElementType, or is it actually by design?
> > 
> > This is very bad. The range API does not mandate that .front must be a function. I often write ranges where .front is an actual struct variable that gets updated by .popFront.  Now you're saying that my range won't work with some code, because they call .front() (which is a compile error when .front is a variable, not a function)?
> 
> My goodness no!
> 
> People, please, my point is simply that is(typeof(someRange.front) ==
> ElementType!(typeof(someRange))) DOESN'T ALWAYS WORK.

OK, so the point is, use ElementType!(typeof(range)) instead of
typeof(range.front)? That works for me. Sorry for the noise. :-P


[...]
> > In the old days (i.e., 1-2 years ago), isForwardRange!R will return false if .save is not marked @property. I thought isInputRange!R did the same for .front, or am I imagining things?  Did somebody change this recently?
> 
> You are imagining that someInputRange.front ever required that. In fact, it would have had to go out of its way to do so (because isInputRange puts no requirements on the *type* of front, except that it returns a non-void value).
> 
> But you are right that save did require @property at one time. Not (In my opinion) because it meant to, but because it happened to check the type of r.save against a type (namely, that .save returns its own type).

Ah, so that's where it came from. Now I remember that there were bugs caused by .save returning something other than the original range type, which broke certain algorithms. That's probably where the whole .save requiring @property thing came from.


> At the same time, I fixed all the isXXXRange traits so @property is not required anywhere. In particular, isRandomAccessRange required r.front to be @property, even when isInputRange didn't (again, IMO unintentionally). Here is the PR: https://github.com/dlang/phobos/pull/3276
[...]

Thanks for the info!


T

-- 
"Maybe" is a strange word.  When mom or dad says it it means "yes", but when my big brothers say it it means "no"! -- PJ jr.
May 19, 2016
On Tuesday, 17 May 2016 at 14:06:37 UTC, Jack Stouffer wrote:
> http://jackstouffer.com/blog/d_auto_decoding_and_you.html
>
> Based on the recent thread in General, I wrote this blog post that's designed to be part beginner tutorial, part objective record of the debate over it, and finally my opinions on the matter.
>
> When I first learned about auto-decoding, I was kinda miffed that there wasn't anything in the docs or on the website that went into more detail. So I wrote this in order to introduce people who are getting into D to the concept, it's benefits, and downsides. When people are confused in Learn why typeof(s.front) == dchar then this can just be linked to them.
>
> If you think there should be any more information included in the article, please let me know so I can add it.

I ran into an auto decoding problem earlier. Honestly I was upset, and I think I was rightly upset. The programming language moved my cheese without telling me. I tend to believe in the route of least surprise. if as a newbie I am doing something stupid and find out i was wrong, that is one thing. but if i continue to do something wrong and find out that the programming language thinks I am stupid that's another thing.

If people want auto coding behavior shouldn't they just use or convert to dchar?
May 19, 2016
On Thursday, 19 May 2016 at 17:16:54 UTC, Taylor Hillegeist wrote:
> If people want auto coding behavior shouldn't they just use or convert to dchar?

No, they need to _decode_ to dchar. I don't know if you miss-typed, but if you didn't, this is exactly what I was talking about in the article:

> "Unicode is hard. Trying to hide Unicode specifics helps no one because it's going to bite you in the ass eventually."
May 19, 2016
On Tuesday, 17 May 2016 at 14:06:37 UTC, Jack Stouffer wrote:
> http://jackstouffer.com/blog/d_auto_decoding_and_you.html

>> There are lots of places where invalid Unicode is either commonplace or legal, e.g. Linux file names, and therefore auto decoding cannot be used. It turns out in the wild that pure Unicode is not universal - there's lots of dirty Unicode that should remain unmolested because it's user data, and auto decoding does not play well with that mentality.

As a slightly tangential aside.....

https://lwn.net/Articles/686392/

There exists a proposal for a linux kernel module to render the creation of such names impossible.....

I for one will install it on all my systems as soon as I can.

However, until then, my day job requires me to find, scan and analyze and work with whatever crud, the herd of cats I work with, throws into the repo.

And no, sadly I can't just rewrite everything because they (or some tool they use) doesn't understand UTF8.
May 20, 2016
On Thursday, May 19, 2016 13:11:47 jmh530 via Digitalmars-d-announce wrote:
> On Thursday, 19 May 2016 at 12:10:36 UTC, Jonathan M Davis wrote:
> > [snip]
>
> Very informative, as always.
>
> I had not realized the implication of front being called without parens, such as front being something that isn't an @property function (esp. variable). Are there any ranges in phobos (you can think of) that do this?

I'm not aware of any, but there might be some. I think that most of use pretty much always use @property functions, though the usual reasons for that don't really apply to Voldemort types. The usual reason to use an @property function instead of a public variable is that while property functions emulate variables, they really aren't the same (e.g. taking its address doesn't have the same semantics, and stuff like incrementing doesn't normally work with property functions). So, unfortunately, you can't transparently swap between @property functions and variables, even though that's theoretically one of the reasons that property functions exist in a language. But when using a range that's a Voldemort type, you don't even ever see the type's declaration, and you're only ever supposed to use the range API on it, so the semantics of variable vs function don't really matter, since you're not supposed to be doing any of the stuff where it would matter (e.g. it makes no sense to take the address of front, because what that means is not specified by the range API and will do different things with different range implementations).

So, it's arguably better to just use public variables with ranges if
functions like front or empty are just going to return a value, but many of
use just use @property functions out of habit given that in the general
case, it's problematic to use public variables instead of @property
functions (though it _would_ be a nice language enhancement IMHO if
using @property on a variable made it illegal to do anything on it that you
couldn't do on an @property function, since then you could make it a public
variable until refactoring required that it become a function, and changing
it wouldn't break code, whereas now, it might).

- Jonathan M Davis