220 24480 <56C6036D.4000406@gmail.com> article
Path: news.gmane.org!not-for-mail
From: Miro Knejp <miro.knejp@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: [tuple] extracting tuples out of a tuple
Date: Thu, 18 Feb 2016 18:46:21 +0100
Lines: 174
Approved: news@gmane.org
Message-ID: <56C6036D.4000406@gmail.com>
References: <CA+wfc1-FFqOJ9OSme_SpJAmGz+cshbMDVi_dLrF1ztbzkTN-WQ@mail.gmail.com>
 <6e35f24a-f728-4ac2-b329-1894206f59cc@isocpp.org>
 <na2rr9$9uf$1@ger.gmane.org> <56C5048D.5020304@gmail.com>
 <na4qtd$75c$1@ger.gmane.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
X-Trace: ger.gmane.org 1455817469 1259 80.91.229.3 (18 Feb 2016 17:44:29 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Thu, 18 Feb 2016 17:44:29 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBC6ONSXJ54LBB5UFTC3AKGQEDFI6CQY@isocpp.org Thu Feb 18 18:44:25 2016
Return-path: <std-proposals+bncBC6ONSXJ54LBB5UFTC3AKGQEDFI6CQY@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-lf0-f69.google.com ([209.85.215.69])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBC6ONSXJ54LBB5UFTC3AKGQEDFI6CQY@isocpp.org>)
	id 1aWScp-0006by-HK
	for gclcip-std-proposals@m.gmane.org; Thu, 18 Feb 2016 18:44:23 +0100
Original-Received: by mail-lf0-f69.google.com with SMTP id j99sf20127725lfi.1
        for <gclcip-std-proposals@m.gmane.org>; Thu, 18 Feb 2016 09:44:23 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=subject:to:references:from:message-id:date:user-agent:mime-version
         :in-reply-to:content-type:content-transfer-encoding
         :x-original-sender:x-original-authentication-results:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=PZJZZFI1xuOkPFBF0vYhkkWXyzt6rH+dlu2m2SPahPs=;
        b=g95/kRIz0fjEHzoYxRf5/FiCQAh5oWu0OM5W3hropHyf1t7LA0UDXNYgSZpZfq8yjo
         qCUMdjMpW8MAyXOYsT0qY11Fm9OBhq0d4sFCBv1U6DOO8OoaJj9F0mZ4sQ818+TbGhNA
         m2tjVZz667eaWVQVvrig3UYYCUE8l7MXM6xmSg479jidqqHx2bVlL/AVVfVNN8q16kPs
         NISKJDuCVq2D55PYIPF0LuwDkVb8bqxQ/durUG/6g/Otf16lqayMrxxudKRTPCps8Qzt
         14DmzRyK+uf1TMavg3VMv0zC7oT9yhFMTT0ULGgfn8lpvu9AwuH5bpSfaoTyd 
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:subject:to:references:from:message-id:date
         :user-agent:mime-version:in-reply-to:content-type
         :content-transfer-encoding:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=PZJZZFI1xuOkPFBF0vYhkkWXyzt6rH+dlu2m2SPahPs=;
        b=jpMcGyISV8qqzSom3KTA+4xI9/Sqac74Tb6xFVuHW2RF9+4faR0Rn7EaMcJnagANYL
         xwY/XUGP39Ri5WBZ4MwAWKBb+/fiKtFDAgqPHuHYTKO2TRvnbajPz/TUWtgRtMxb5Bsa
         0siWWHjBDDLLnbtxhsYvKhWuT+0n1jzK1C/eNeB+eK3Z+mgz8+hIKbBaKy5Kl/c+xe4B
         CgwVBh6MivPaBtZCJjA7Tftsl8xSBnkLAK7fTwFGhW1B/G371B56L1rFXFquIsDecI+/
         ZCvnF9yM4zwPS0438ZdHqStLvwJaiC49Wan9m0tMsZ2TXfZ 
X-Gm-Message-State: AG10YOQnm7IMZlBiFI3ubE9XyoSvrr4XlAhz2UZ1Rzhd5mnooK1sPeP8kDbKh4QYdJhiUA==
X-Received: by 10.112.16.34 with SMTP id c2mr1266596lbd.19.1455817462997;
        Thu, 18 Feb 2016 09:44:22 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.28.63.211 with SMTP id m202ls178392wma.1.canary; Thu, 18 Feb
 2016 09:44:21 -0800 (PST)
X-Received: by 10.28.125.77 with SMTP id y74mr4474656wmc.21.1455817461709;
        Thu, 18 Feb 2016 09:44:21 -0800 (PST)
Original-Received: from mail-wm0-x232.google.com (mail-wm0-x232.google.com. [2a00:1450:400c:c09::232])
        by mx.google.com with ESMTPS id hk5si11891716wjb.22.2016.02.18.09.44.21
        for <std-proposals@isocpp.org>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Thu, 18 Feb 2016 09:44:21 -0800 (PST)
Received-SPF: pass (google.com: domain of miro.knejp@gmail.com designates 2a00:1450:400c:c09::232 as permitted sender) client-ip=2a00:1450:400c:c09::232;
Original-Received: by mail-wm0-x232.google.com with SMTP id c200so39800266wme.0
        for <std-proposals@isocpp.org>; Thu, 18 Feb 2016 09:44:21 -0800 (PST)
X-Received: by 10.194.129.132 with SMTP id nw4mr7826289wjb.165.1455817461532;
        Thu, 18 Feb 2016 09:44:21 -0800 (PST)
Original-Received: from [192.168.42.33] (ppp-93-104-161-134.dynamic.mnet-online.de. [93.104.161.134])
        by smtp.gmail.com with ESMTPSA id u4sm7601169wjz.4.2016.02.18.09.44.20
        for <std-proposals@isocpp.org>
        (version=TLSv1/SSLv3 cipher=OTHER);
        Thu, 18 Feb 2016 09:44:20 -0800 (PST)
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101
 Thunderbird/38.6.0
In-Reply-To: <na4qtd$75c$1@ger.gmane.org>
X-Original-Sender: miro.knejp@gmail.com
X-Original-Authentication-Results: mx.google.com;       spf=pass (google.com:
 domain of miro.knejp@gmail.com designates 2a00:1450:400c:c09::232 as
 permitted sender) smtp.mailfrom=miro.knejp@gmail.com;       dkim=pass
 header.i=@gmail.com;       dmarc=pass (p=NONE dis=NONE) header.from=gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:24480
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/24480>

Am 18.02.2016 um 17:18 schrieb Matthew Woehlke:
> On 2016-02-17 18:38, Miro Knejp wrote:
>> Am 17.02.2016 um 23:22 schrieb Matthew Woehlke:
>>> On 2016-02-17 16:30, Miro Knejp wrote:
>>>> I somehow can't shed the feeling that what we really need here is
>>>> support for multiple return values.
>>>>
>>>> having this ability makes writing tuple unpacking trivial:
>>>>
>>>>     template<class... Ts> auto... unpack(tuple<Ts...> x);
>>> First off, you meant:
>>>
>>>     template <typename T> auto... unpack(T);
>> No, I didn't. The example I provided was for std::tuple explicitly to
>> demonstrate how MRVs come into the picture. People can obviously
>> customize unpack() in addition to get<>() using ADL as necessary.
> Does assignment unpacking use std::unpack, then? If so, then you've just
> changed the customization point. (If not, I object to requiring
> different customization points for such similar operations.)
>
> That said, I'm not convinced that std::get isn't the superior
> customization point. (Keep in mind I also objected to having to
> specialize std::tuple_size, always.)
If `get()` is the superior customization point you obviously don't need=20
to customize `unpack()`. However that is a library issue and there is no=20
point in arguing over the library interface while the necessary language=20
feature is still undecided.
>
>>> TBH, as much as I argued this previously, I have to say that at this
>>> point I'm inclined to see U2PP=C2=B9, and possibly P0222, as the best
>>> solution to MRV's.
>> (do you have a link to P0222? I couldn't find anything with that number)
> It hasn't been published yet AFAICT, but should be in the Feb 2016
> mailing whenever that does get published.
>
> Meanwhile:
> https://github.com/mwoehlke/cpp-proposals/blob/master/p0222r0-anonymous-s=
truct-return.rst
> (be aware that github strips the markup for standardese edits; check the
> raw reST for these, though in this case the edit may be obvious).
Thanks
>
>> In my head MRVs are a transient construct only existent as the type of a
>> call expression. If you need to capture it assign the values to
>> varaiables (like in P0144R1) or forward as parameters to another call
>> expression (like make_tuple). Under this assumption, that MRVs are their
>> own kind of entity, folding becomes possible as (0 + ... + foo()) if
>> their special nature is considered. Therefore folding a tuple becomes (0
>> + ... + unpack(tpl)).
> So... basically, an MRV *is* a parameter pack? In that case, I don't see
> much difference between "true MRV's" and U2PP.
Call it whatever you want, I don't care. At this stage I'm interested in=20
the functionality not bikeshedding of syntax or classification.
>
>>>> Given the proper handling of lvalue-refs, rvalue-refs, reference_wrapp=
er
>>>> etc, this should also make the example tail(ref(tpl1)) =3D tpl2 work.
>>> How would this be different from / better than:
>>>
>>>     std::tie([1:]tpl1...) =3D tpl2;
>>>
>>> ...?
>> It uses words that actually describe what it does.
>>
>> Without MRVs you cannot hide "[1:]tpl1..." effortlessly behind a named
>> function.
> You can't?
>
>    auto tail(auto tuple) { return make_tuple([1:]tuple...); }
>
> (Simplified for illustrative purposes; usual caveats about proper
> reference handling, forwarding, etc.)
Yes, that is how I would implement `tail()` even with MRVs because=20
`tail()` has the signature `(a_0, a_1, ..., a_n) -> (a_1, ..., a_n)`. A=20
better name for the example would have been `unpack_tail(tpl)` or=20
similar, my bad. Basically it needs the signature `(a_0, a_1, ..., a_n)=20
-> a_1, ..., a_n`.

But yet, those two are not equivalent. I cannot substitute the=20
expression `[1:]tpl...` with the expression `unpack_tail(tpl)` using=20
only the tools given in this thread and get the same semantics. Or am I=20
wrong? That's what I mean with you can't `hide` it. A full substitution=20
is `[:]unpack_tail(tpl)...` but that is a leaky abstraction because in=20
order to get the same semantics you have to apply additional operators.
>
>> *Every single time* someone needs to unpack the tail of a
>> tuple they have to write out the same sequence of punctuation. DRY
>> anyone?
> That's like saying "every time someone needs to add two numbers they
> have to write '+'". Yes, every time you do something you have to write
> something. DRY is when you are writing the same *non-trivial* code
> repeatedly. Seven characters (`[1:]...`) is not non-trivial, especially
> as your example uses a minimum of six (`tail()`, assuming that you are
> `using namespace std;`, which not everyone wants to do!).
Calling a function is not a violation of DRY. It's not about writing=20
"something" or "counting characters", it's about not repeating the same=20
implementation but give the repeatedly used abstraction or operation a=20
meaningful name. The triviality doesn't matter. `tail()` is obviously a=20
very trivial example, but even there I'd prefer a descriptive name=20
instead of wading through a forest of consecutive punctuation characters=20
(eight(!) in the previous example) over and over again.

So instead I'd like to hide `[1,5:a,y*3:photon_torpedo()~~^3]tpl...`=20
behind `federation_unpack(tpl)` which should have the signature `(a_0,=20
a_1, ..., a_n) -> x, y, z`. It doesn't return a `tuple<x, y, z>` because=20
it's called "unpack" and the expression I want to substitute with it is=20
not of type `tuple<x, y, z>` but of `x, y, z`. But an implementation=20
without MRVs is forced to the signature `(a_0, a_1, ..., a_n) -> (x, z,=20
y)` which I then have to additionally apply the actual unpacking to.=20
That's not really abstracting the "unpacking" part, is it? It's as if we=20
had to dereference references...
>
>> Even languages with this kind of syntax come shipped with
>> utility functions like tail() because they're more descriptive.
> I could argue that. If I'm not familiar with it, I need to check the
> documentation to know if 'tail' means `[1:]` or `[-1]`, because it could
> mean either one. With U2PP slicing, there is no such ambiguity. (And
> anyway, as shown above, there is nothing stopping us having a
> `std::tail()` with U2PP.)
`tail()` is a ubiquitous operation in basically every language that has=20
some form of builtin list or tuple type. How it is implemented doesn't=20
usually matter. What does matter is that I don't have to copy the=20
implementation around, may it be as trivial as it is in the case of=20
`tail()`. If the C++ committe manages to make `tail()` do something=20
tremendously different then congratulations on confusing everybody!
>
>> In order to hide it inside a function you have to return a tuple
>> (maybe containing references) and then use the awkward inversion of
>> "apply(f, something(x))" when using the result.
> Ah... no? Why? Huh?
> U2PP makes std::apply superfluous.
Well OK, either `apply(f, [:]something(x)...)` or=20
`f([:]something(x)...)` are equivalent, and both are leaking the fact=20
that I actually wanted a list of values but got a tuple instead.
>
>> Compare that to "f(something(x))" and tell me which one you'd prefer
>> to write and read.
> I'm not thrilled that I can't tell there that `something(x)` is a
> parameter pack. In that sense, I prefer the clarity of
> `f([:]something(x)...)`. (Note that this is also how e.g. Python works.
> Despite often being used as the poster child for MRV's, Python actually
> has no such thing... just lots of syntax sugar a la P0144 and U2PP that
> makes it seem as if it does.)
I call that paranoia, as is the case with every new language feature.=20
Soon we won't be able to tell whether `void foo(X x)` is the definition=20
of a function template or not. Are you also not going to avoid that? For=20
how long? But as noted in a previous response to Vicente, the unpack=20
operator *may* be necessary if we want to allow the different nesting=20
levels known from parameter pack expansions. I don't like it as it=20
suffers from the same problems as I described above, and I still hope it=20
can be omitted for the most common case of immedate unpacking. That may=20
be wishful thinking though.
>
> Oh! Here's a fun point... if we *did* have true MRV's, how long until
> people start writing unary operator* as a synonym for unpack? Would that
> be a good thing?
>
People define their own operators for DSLs or convenience all the time.=20
If it gets established as common practice then there's no point in=20
trying to stop it. But you know how it goes: new language features are=20
always heavily abused until people shoot themselves in the foot enough=20
times and figure out what the "good" versus the "bad" abuses are :)

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-propos=
als/.

.
