tags:

views:

54

answers:

2

I have a class that I'm implementing ranges for. I'd like to implement the functions the way the phobos library does, i.e. outside the main class.

void popBack(T)(ref T[] a) if (!is(Unqual!T == char) && !is(Unqual!T == wchar))
{
    assert(a.length);
    a = a[0 .. $ - 1];
}

Here's my version:

void popFront(T)(ref PersistentList!(T) a)
{
    a = a.next();   
}

When I try to compile this code with a forech, I get:

Error   1   Error: no property 'popFront' for type 'stmd.PersistentList!(int).PersistentList'   main.d  

I could move the member code into the main class, but since I'm modifying the input "ref" value I can't use popFront() I really need popFront(ref a).

What am I doing wrong?

+4  A: 

What you're trying to do depends on what the D community calls uniform function call syntax. This is the ability to call non-member functions with the same syntax as member functions. This has been implemented for arrays only for a long time, and there was some debate about how far to take it. It's been decided that it should be implemented for all types, but Walter Bright, the compiler implementer hasn't gotten around to doing this yet because he's been working feverishly on 64-bit support.

Uniform function call syntax is described in Andrei Alexandrescu's book, "The D Programming Language", which is considered the authoritative guide to D2. Its currently lack of implementation is considered a bug. This should be fixed in a few releases.

dsimcha
Thanks for the comment. My classes are immutable, so I can't actually have a popFront member in the class itself. But I did create a "PersistentListRange" subclass so I can do foreach(i; lst.range) and that works just fine.
Timothy Baldridge
+3  A: 

Phobos only implements the range functions outside of the struct/class for arrays. Arrays allow you to call functions on them as if they were member functions. So, if you have this function:

int func(int[] arr)
{
    return arr[0];
}

you can call it like so

auto arr = [1, 2, 3];
auto val = arr.func();

instead of

auto val = func(arr);

Being able to do that with all types is called universal function call syntax, but that's not currently legal in D, though it looks like it's probably going to be added.

There's really no reason to declare your range functions outside of your range type, unless you're looking to share that implementation with other range types, which often wouldn't be possible anyway, since the internal implementation has to deal with how the container type maintains its data. So, you might as well just make them part of your range type. That's what Phobos does in all cases, except for arrays, which obviously can't have them as part of their type and have to use their ability to have functions called on them as if they were member functions in order for it work.

Jonathan M Davis