Applying a tuple to a function (and more)

Philippe Sigaud philippe.sigaud at gmail.com
Mon Sep 20 12:41:14 PDT 2010


On Sun, Sep 19, 2010 at 18:33, Juanjo Alvarez <juanjux at gmail.com> wrote:

> Philippe Sigaud wrote:
>
> > What languages are you used to? You seem to do quite well with genericity
> > :)
>
> What I've done profesionally and personally in the last year would be 90%
> Python, 5% Java and 5% C++. So yes, since Python is like a D with an
> uberauto and everything being runtime templates the real problem I have is
> with generic declarations :)
>

OK, that's why you're using tuples for everything :)
Python's tuples are cool. I think I *learnt* what tuples were while dabbling
in Python a few years ago. (Haskell's ones are great too).

Note that the 'real' D tuples are expression tuples (instantiated
typetuples). The "T..." thingies in templates, once instantiated with  T t;
They know their length, are indexable, slicable, iterable, etc. In a way
they are random-access range with a length, only with heterogeneous types.
But I don't think they were conceived as tuples in other languages, not at
first. I'd guess that, for Walter, they were just a natural
extension/cleaning for templates, based on C++. But they are like Python's
tuples! Except for one blatant limitation: they cannot be returned from a
function :(
But you can return a templated struct. So the basic idea is to wrap them in
Tuple(T...) to be able to return them. Then std.typecons.tuple does its best
to offer a interesting access to the underlying expression tuple. But it's
not a first-class citizen in D: you cannot iterate them nor slice them...
For now, because the situation has improved.

What many people coming from C++/Java do is putting their stuff in
structs/classes. They tend not to use tuples that much.



This is much better, no doubt. I've changued that part too (I'm really
> learning a lot with your posts, you should think about writing a book about
> D too).
>

What I should do is moving my a** and have some code reviewed for Phobos.
But it seems I can't find the time. When I've half an hour, I try to help
here instead :)




> Now I've two new roadblocks:
>
> Roadblock1:
>
> If the tuple is defined in the same file as the code expanding it (with the
> template function in another file), it works. But if I move the tuple
> definition to another file (urls.d) the compiler gives me the error:
>
> Error: Unions with overlapping fields are not yet supported in CTFE
> urls.d(9): Error: cannot evaluate tuple("^/home/$",& index,42,3.14) at
> compile time
> urls.d(9): Error: cannot evaluate tuple("^/home/$",& index,42,3.14) at
> compile time
>
> That is, this works:
>
> // file: bindselector.d
> import std.typecons;
> import views;
>
> void main() {
>     // tuple defined here
>     auto selector_data = tuple( "^/home/$", &(views.index!(int, double)),
> 42, 3.14 );
>     auto sel_regex_var  = selector_data.field[0];
>     auto sel_view_var = selector_data.field[1];
>     sel_view_var(sel_regex_var, selector_data.expand[2..$]);
> }
>
>
> But moving the declaration of "selector_data" to a file urls.d and then
> importing that file from bindselector.d gives me that error... bug?
>

What do you mean, you moved the declaration of selector_data ? You declared
it outside main() in another module? I don't know why, I never declare date
outside functions/objects.

Maybe if you declare it in the 'root scope' of the module (I don't know how
to call that: the basic scope of a module, the one where the module name;
is), it's initialized at compile time. And at compile time, I'm not sure
things like addresses &(...) have a sense.

Did you try to make selector_data a function?

auto selector_data() { return tuple("^/home/$", &(views.index!(int,
double)),42, 3.14 );}



> Roadblock2:
> The next step is to define multiple tuples in urls.d inside some iterable
> data structure, so bindselector.d can import that and do its thing inside a
> foreach.
>
> The problem here is related again with my limitations declaring generics.
> Since every tuple will have a different type signature, I tought that the
> logical structure to group them would be... yes, another tuple :) Then I
> would foreach on that structure and bind the params, etc.
>
> First try (Fail-1):
>
> // ----------------------------------------
> auto selector_data_tuples = tuple(
>                                   tuple( "^/home/$", &(views.index!(int,
> double)), 42, 3.14 )
>                                 );
>
> foreach(selector_data; selector_data_tuples) {
>     auto sel_regex_var  = selector_data.field[0];
>     auto sel_view_var = selector_data.field[1];
>     sel_view_var(sel_regex_var, selector_data.expand[2..$]);
> }
> // ----------------------------------------
>
> Compile error: Error: cannot infer type for selector_data
>
> Logical, since the type of the iterated element in the foreach is fixed,
> and
> I'm iterating over tuples of different types.
>

Oh, but you can iterate on an expression tuple alright, even when all its
elements have different types. I don't know why bearophile doesn't like
that.
It's just, as I've said higher up in this message, that tuple()/Tuple!() is
a struct, not a 'real' tuple: it offers a nice access to the wrapped
expression tuple, but not as much as you'd like. Use .expand to get direct
access:


    auto t = tuple(1, 3.14, "abc");
    foreach(i, field; t.expand) // get index and value
    {
        writefln("field #%s is of type %s and has value
%s.",i,typeof(field).stringof, to!string(field));
    }

If you want to do some type sorcery, you can also iterate on the types. You
can get access to them by the .Types alias in Tuple!().

foreach(i,Type;  t.Types) // will iterate on (int,double,string) and not on
(1, 3.14, "abc")
{...}


Philippe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20100920/ef974141/attachment.html>


More information about the Digitalmars-d-learn mailing list