On 10/15/2014 04:18 PM, George Makrydakis wrote:On 10/15/2014 04:55 PM, Jens Maurer wrote:I'd prefer not to derail N4191 with additional features or depend on other proposals. It seems your suggestions are purely add-on and should be handled in a separate paper.I agree with your observation on the first one on expanding this to type parameters (and why not on template-template type ones) being part of a separate paper (are they going to write it?).Probably not. Ask the author to be sure. Otherwise, feel free to write a paper yourself.
Regardless, for when values are concerned in folding I do not see how N4191 is derailed. Given that (... op args) and (args op ...) where 'op' is to be an operator during folding (as Sutton and Smith argue), allowing a function (constexpr or not) or a lambda to be used in 'op' would seem a rather good idea: (... [](auto x){ /* implementation here */} args) (... function_identifier args) Such a plain substitution of 'op' for allowing any function identifier / lambda with the same context of use as 'op', does not depend on other proposals nor is there an attempt to create another one for what concerns it. It is a legitimate observation for a likely omission.Well, for one, the operators in N4191 are all binary, and that's how the folding is applied. Your lambda above only has one parameter, so I don't know how the folding would work there. Same for functions with more than two parameters. Are there constraints on the function's return type vs. the parameter types?
Second, I'm pretty certain that "..." adjacent to a binary operator, surrounded by parens, is pretty unambiguous grammar-wise. An identifier followed by ... is certainly allowed elsewhere in the grammar, so I'm a bit more cautious there.
Extending this later to arbitrary functions is an add-on that doesn't invalidate existing code. Personally, the source code looks of the "arbitrary function" part of the proposal require a lot more getting-used-to than the corresponding operator case. And there is an actual use case for the operator case in the concepts TS.
On 10/15/2014 09:51 PM, George Makrydakis wrote:On 10/15/2014 09:55 PM, Jens Maurer wrote:On 10/15/2014 04:18 PM, George Makrydakis wrote:separate paper (are they going to write it?).Probably not. Ask the author to be sure. Otherwise, feel free to write a paper yourself.Unlikely to happen not because I am not equipped to do it but because it would serve no purpose doing it since there are working on it. I am not new anymore to how they actually work :)I'm not sure who "they" are in the last sentence. You asked whether the authors of N4191 are going to write a separate paper discussing folding on template-arguments. I said "probably not, ask them to be sure". So, if you want to see this extension happen, yet you refrain from asking the paper authors for a change directly, all that is left is writing the paper yourself or asking someone else to do it. Otherwise, it won't happen.
Well, for one, the operators in N4191 are all binary, and that's how the folding is applied. Your lambda above only has one parameter, so I don't know how the folding would work there. Same for functions with more than two parameters. Are there constraints on the function's return type vs. the parameter types?Such catamorphisms over lists obviously require a binary function, as is the way throughI'm not sure about "obvious". I'm mostly hanging around in the core language working group, and there, we like to have all rules of the C++ language spelled out explicitly. If you want to say that your proposal is limited to functions having two parameters, you should say so. Otherwise, I'm going to ask. The only hint you gave at the actual function signature to be supported was the lambda, which didn't match my expectations, so I was confused.
which we define left and right folds in languages having proper support for them. The omission due to haste was fixed so I think you don't present an argument here for using this in your defense: https://groups.google.com/a/isocpp.org/d/msg/std-proposals/O18-SNExUdw/wxf5VleV6uEJ: (... [](auto x, auto y) { /* implementation here */ } args)I saw this after I sent my e-mail. Ok.
The /correct comment/ in your defense on this would be to ascertainI don't think I need a "defense". All I'm trying to do with my questions is to clarify what the proposal actually is, so that I can form a firmer opinion.
that 'args' has a sufficient number of arguments inside for the fold to occur, without bailing out on the last call, not just function arity.That's indeed a good follow-on question: In the function case, what's the result for 0-argument lists?
The authors deal with this in their own paper (in a way),They expressly prescribe the neutral element as the result for 0-argument lists, for each binary operation supported. Is there something wrong with that?
while it is obvious that there are far too many ways to ascertain that.I'm sorry, I don't understand this part of the sentence.
Also, given that there is a single function identifier to be used there, the type signature is predictable in case of arguments of the same type,So, is there a constraint that all elements of the pack be of the same type? That's not a constraint for the operators (conversions are allowed there). In any case, this would be a further difference for the function case that needs to be spelled out.
or it can even be engineered to be in arguments of different types through function template overloads, to the horror of people not understanding templates (or concepts).Not just template overloads, simple overloads do it. Or even no overloads, if you allow implicit conversions. Example: bool f(short, long); (args f ...) will expand to f(f(f(a1, a2), a3), a4) if I understood the syntax right. And that could be made to work even if a2 would have a different type compared to a1, using implicit conversions. What are the rules here?
In that case you would not just be doing a fold though, you would be entering territory best described by the functional programming paradigm (see Haskell etc) which would be off-topic for us to discuss in here.Why? Implicit conversions happen in C++ all the time.
As for n-ary functions over 2-nary ones as is the case for folds, I remind that we do have default arguments in functions (one case where an n-ary can work in a 2-nary), while it is fairly obvious that not even a beginner would commit the error of calling a function with an improper arity of arguments, regardless of whether the syntax proposed in N4191 existed or not. A lot of algorithms in C++'s <algorithm> do have a requirement for unary functions to be passed for example. I do not think that people cannot relate to this by precedent nor is it responsible for them to omit such trivial knowledge.I'm not sure what you want to say here. Again, I'm asking about the features of your proposal, and if you wish to require that "f" (the function subject to the folding) is a binary function, you should clearly say so, and not assume someone will deduce it from the surroundings.
Finally, forcing a constraint over C++'s current latent typing approach, it can be done either through concepts or sfinae based overload resolution for implementing bounded polymorphism, though the latter option is obviously one the concepts team would like to avoid. I see no issue here other than waiting for people to learn the notion of function arity, which is already in multiple paragraphs of the standard itself and even beginners are familiar with it.I'm not talking about a learning issue, I was asking about the specification itself. To me, there's no question that the concept of a binary function is well-established.
Second, I'm pretty certain that "..." adjacent to a binary operator, surrounded by parens, is pretty unambiguous grammar-wise. An identifier followed by ... is certainly allowed elsewhere in the grammar, so I'm a bit more cautious there.I think you should think more about it. In essence, they are providing a new kind of /"binary operator expression"/ if you think about it with the (... ) and ( ...) semantics. Therefore the domain within which ... is applicable is not ambiguous since there is no identifier prior to the triple dot in the first case where triple-dot is the first, while in the second case of folding the triple dot is last following all identifiers, including those used for inline lambda definition (if ever).I was talking about parsing ambiguities. I'm still feeling uneasy here. Is the "most vexing parse" getting more difficult?
Sure thing, which means that we are in agreement that this does not break existing or future code. For such a little evident omission on their behalf, it is of doubtful value to have to wait at least another 4 years post C++17 to get it as a feature,Why? If you submit the paper now, it certainly has a chance to get into C++17.
given that the only way to go through this using the operators, would be to emulate the result using operator overloading and/or expression template semantics within the proposed syntax over the type sequences involved. I doubt that Sutton would love to encourage such uses.Then you should write an e-mail to the authors, maybe they're sympathetic to your wishes and extend their paper.
On 10/16/2014 12:07 PM, George Makrydakis wrote:On 10/16/2014 08:51 AM, Jens Maurer wrote:That's indeed a good follow-on question: In the function case, what's the result for 0-argument lists?You already reply yourself in the following paragraph. An empty list should by definition return the identity (e.g. additive, multiplicative etc) of the operation involved. Or in context of the paper, the "neutral" element.That's easy for + and * in particular, but, again, what's the result for 0-argument lists in the (general) function case? Or is that supposed to be ill-formed?
Not just template overloads, simple overloads do it. Or even no overloads, if you allow implicit conversions. Example: bool f(short, long); (args f ...) will expand to f(f(f(a1, a2), a3), a4) if I understood the syntax right. And that could be made to work even if a2 would have a different type compared to a1, using implicit conversions. What are the rules here?We are not disagreeing, see previous paragraph.I'm sorry, but I'm not trying to make a counter-proposal of any sort; I'm trying hard to understand your suggestion. N4191 doesn't describe any constraints on the element types of the pack; I'm just asking whether your "function" extension suggestion has any such constraints. If the answer is "no" (for consistency with overloaded operators, to say the least), that's fine and I'm happy.
In that case you would not just be doing a fold though, you would be entering territory best described by the functional programming paradigm (see Haskell etc) which would be off-topic for us to discuss in here.Why? Implicit conversions happen in C++ all the time.See before, It is not about implicit conversions, it is about the fact that folds on heterogeneous lists can have some interesting properties. This should be better discussed in the setting of general catamorphisms. I do not think that discussing it in this setting it would help the discussion. It would confuse people who lack the background (not implying you, I don't know you), and my experience with this list shows that most are blissfully unaware of these things. Implicit conversions are evil here if not properly managed.I'm sorry; now I'm really confused. N4191 shows a syntax expansion of the fold, and, since no further constraints are given, I'd assume that syntax expansion is then interpreted according to the usual C++ rules, including overload resolution and implicit conversions. And yes, implicit conversions might mean all sorts of trouble, including possibly picking a different overload for each step in the fold. Do you suggest to prohibit differing element types in the pack (i.e. having a homogenous list only) to avoid such troubles or not?
It is not my proposal, it is their proposal and I asked why they did not consider this or if they will consider it. By definition, you need a binary function in a such fold (I am not saying to change that),Great. One more question answered.As a library feature, it isn't that this cannot be properly done through code generation either through template/constexpr trickery etc. If one needs "weird syntax" to go with it as well, there is the preprocessor that can help out. So, why bother doing it and going through a process that yields nothing, other than just offering feedback on what is already written in N4191?And maybe it's the right approach to use std::accumulate for (named) functions. The desire for core language support of the operator case in N4191 comes from "requires" expressions in concepts where we can't really call other library functions.
If I were to work on introducing a construct for folding expressions myself, I would have not taken a path that would be limited to values but also to types, making sure that the semantics of both fold (see std::accumulate for example) and fmap (see what std::transform does for example) would be covered equally in all cases. I however do not think that C++ is suitable to such thinking at a language level because some of the people involved in taking decisions have their own ideas on who is allowed to do what - or perhaps are not all well equipped by their background for these things yet.
I do not doubt your motivation. Sorry if I sounded offensive.My understanding is that there are indeed people in EWG that look at the entire picture, even though individual proposals are usually just changing one focused aspect of the language. In general, when someone asks a question, that's usually a genuine question to help understand the workings of a proposed feature (often giving a specific code example), and a short, factual answer is all that is expected. It's helpful to keep in mind that the people attending meetings are from a diverse field of experience and few are experts in the domain being presented. I felt that our discussion above wasn't sufficiently to the point: I have no background in type theory, and all I wanted to know is whether you'd want to support functions with other than two arguments for the foldings, and if so, how that might work. The short answer is "binary functions only, as per the syntax expansion shown in N4191", and that would have saved quite a few bits in the communication. , Jens
(args + ... 0) // foldl args (+) 0
(0 ... + args) // foldr args (+) 0
That is already in the proposal (with a very slightly different syntax).
> --
>
> ---
> 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 email to std-proposal...@isocpp.org.
> To post to this group, send email to std-pr...@isocpp.org.