Date: Sun, 11 Apr 2021 16:38:42 +0200
Martin,
on Sun, 11 Apr 2021 12:55:13 +0000 you ("Uecker, Martin"
<Martin.Uecker_at_[hidden]>) wrote:
> > No `auto` parameters are need for such a thing. For the proposed C
> > feature (without `mutable`) this would be
> >
> > #define foo(x) \
> > [&, yy = (x)] { /* type generic argument */ \
> > auto y = yy; \
> > ... arbitrary code using y ... \
> > }()
> >
> > This may not be pretty, but here also no `auto` parameters are
> > needed and the full functionality is already there.
>
> Ok, this is fine, but only further confirms that we create
> a problem for parsers for no good reason.
I don't follow. If not tg, this has only minor problems with parsing
and perfectly replaces the compound expression feature with a feature
that is more flexible and better controllable. (I don't have to use
the `[&]` default of compound expression, for example.)
And for C, the problem is not the adoption of the lambda feature or
the attribute features alone. The sin has already been committed when
we integrated the attribute feature with its crude syntax. I was and I
am still am against that, but WG14 decided otherwise. A convenience
macro à la `__attribute__` would avoid all of these difficulties.
> > The only real and new purpose of type-generic macros with `auto`
> > parameters is the second usage for them, namely the conversion into
> > function pointers. A type-generic lambda macro
> >
> > #define mysin [](auto x){ \
> > /* implement a tg formula for the sinus function */ \
> > return val; \
> > }
> >
> > double (*sin)(double) = mysin;
> >
> > is not so easily emulated by gcc's compound statement plus nested
> > functions, if at all.
>
> I agree and this is very nice. Here the parsing problem also does
> not arise as the type of the pointer converted to is also already
> known before the lambda is parsed.
yes, exactly
> > > In contrast, with type-generic lambdas:
> > >
> > > #define foo [](auto y){ \
> > > ... arbitrary code using y ... \
> > > }
> > >
> > > the code needs to be parsed without knowing the type of 'y'
> > > and only then is the argument is parsed which yields this
> > > information.
> >
> > If used in a call expression, yes, in a sense.
>
> Yes. But with the syntax it must be possible to parse such
> expressions. If we can outlaw this, i.e. calling tg lambda
> directly, this would also solve the problem.
>
> > But that problem can also be solved with lookahead for a ballanced
> > token sequence, finding the arguments to the call (if this is a
> > call), doing the type inference for the parameters, and then
> > scanning the body of the lambda for real.
> >
> > So yes, this has a cost, but I think that this cost is limited.
>
> It is certainly doable. The problem is that this requires unbounded
> lookahead and also recursively if tg lambdas are nested.
Not much more than the attribute feature, which also parses for
ballanced token sequences.
> One could implement this as another preprocessing step that shuffles
> around the tokens before the parser even sees it.
> But alls this seems like this would be a natural fit for the
> preprocessor which suffles around tokens anyway.
You mean something like a new pseudo-macro directive similar to `_Pragma`?
If we suppose that we'd have non-tg lambdas (just to have a syntax)
λ([capture, ...] (auto A, int B, auto C) [[attribute, ...]] { body ... })
Used without following () this could dump the contents in place
[capture, ...](auto A, int B, auto C) [[attribute, ...]] { body ... }
such that it can be converted to a function pointer (or a wide
function pointer if we have that some day). So a tg-lambda as defined
in the current paper needs only to be allowed for conversion and not
for function call.
With () and arguments such as `(a, b, c)` this would then expand to
something like
[capture, ..., auto A = a, int B = b, auto C = c] [[attribute, ...]] { body ... }()
I don't know if I'd want this, but at least this gives a nice mental
picture of what is happening, here.
> > The big advantage is that this would bring us feature-complete
> > type-generic math library (or similar) that enables us to provide
> > function pointers where they are needed.
>
> I agree about the advantages of the general concept.
> I just point out the very unfortunate choice of syntax.
That's the whole reason I started this thread, so we are in sync,
here.
Thanks
Jens
on Sun, 11 Apr 2021 12:55:13 +0000 you ("Uecker, Martin"
<Martin.Uecker_at_[hidden]>) wrote:
> > No `auto` parameters are need for such a thing. For the proposed C
> > feature (without `mutable`) this would be
> >
> > #define foo(x) \
> > [&, yy = (x)] { /* type generic argument */ \
> > auto y = yy; \
> > ... arbitrary code using y ... \
> > }()
> >
> > This may not be pretty, but here also no `auto` parameters are
> > needed and the full functionality is already there.
>
> Ok, this is fine, but only further confirms that we create
> a problem for parsers for no good reason.
I don't follow. If not tg, this has only minor problems with parsing
and perfectly replaces the compound expression feature with a feature
that is more flexible and better controllable. (I don't have to use
the `[&]` default of compound expression, for example.)
And for C, the problem is not the adoption of the lambda feature or
the attribute features alone. The sin has already been committed when
we integrated the attribute feature with its crude syntax. I was and I
am still am against that, but WG14 decided otherwise. A convenience
macro à la `__attribute__` would avoid all of these difficulties.
> > The only real and new purpose of type-generic macros with `auto`
> > parameters is the second usage for them, namely the conversion into
> > function pointers. A type-generic lambda macro
> >
> > #define mysin [](auto x){ \
> > /* implement a tg formula for the sinus function */ \
> > return val; \
> > }
> >
> > double (*sin)(double) = mysin;
> >
> > is not so easily emulated by gcc's compound statement plus nested
> > functions, if at all.
>
> I agree and this is very nice. Here the parsing problem also does
> not arise as the type of the pointer converted to is also already
> known before the lambda is parsed.
yes, exactly
> > > In contrast, with type-generic lambdas:
> > >
> > > #define foo [](auto y){ \
> > > ... arbitrary code using y ... \
> > > }
> > >
> > > the code needs to be parsed without knowing the type of 'y'
> > > and only then is the argument is parsed which yields this
> > > information.
> >
> > If used in a call expression, yes, in a sense.
>
> Yes. But with the syntax it must be possible to parse such
> expressions. If we can outlaw this, i.e. calling tg lambda
> directly, this would also solve the problem.
>
> > But that problem can also be solved with lookahead for a ballanced
> > token sequence, finding the arguments to the call (if this is a
> > call), doing the type inference for the parameters, and then
> > scanning the body of the lambda for real.
> >
> > So yes, this has a cost, but I think that this cost is limited.
>
> It is certainly doable. The problem is that this requires unbounded
> lookahead and also recursively if tg lambdas are nested.
Not much more than the attribute feature, which also parses for
ballanced token sequences.
> One could implement this as another preprocessing step that shuffles
> around the tokens before the parser even sees it.
> But alls this seems like this would be a natural fit for the
> preprocessor which suffles around tokens anyway.
You mean something like a new pseudo-macro directive similar to `_Pragma`?
If we suppose that we'd have non-tg lambdas (just to have a syntax)
λ([capture, ...] (auto A, int B, auto C) [[attribute, ...]] { body ... })
Used without following () this could dump the contents in place
[capture, ...](auto A, int B, auto C) [[attribute, ...]] { body ... }
such that it can be converted to a function pointer (or a wide
function pointer if we have that some day). So a tg-lambda as defined
in the current paper needs only to be allowed for conversion and not
for function call.
With () and arguments such as `(a, b, c)` this would then expand to
something like
[capture, ..., auto A = a, int B = b, auto C = c] [[attribute, ...]] { body ... }()
I don't know if I'd want this, but at least this gives a nice mental
picture of what is happening, here.
> > The big advantage is that this would bring us feature-complete
> > type-generic math library (or similar) that enables us to provide
> > function pointers where they are needed.
>
> I agree about the advantages of the general concept.
> I just point out the very unfortunate choice of syntax.
That's the whole reason I started this thread, so we are in sync,
here.
Thanks
Jens
-- :: INRIA Nancy Grand Est ::: Camus ::::::: ICube/ICPS ::: :: ::::::::::::::: office Strasbourg : +33 368854536 :: :: :::::::::::::::::::::: gsm France : +33 651400183 :: :: ::::::::::::::: gsm international : +49 15737185122 :: :: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::
Received on 2021-04-11 09:38:49