Is It Valid for a Lambda To, Essentially, Close Over Itself

Is it valid for a lambda to, essentially, close over itself?

At the point at which you capture g by reference, it has been declared, so the name is available for use:

3.3.2/1 The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer

You are allowed to use objects in limited ways before they are initialised - basically, anything that doesn't depend on the value is OK:

3.8/6 before the lifetime of an object has started but after the storage which the object will occupy
has been allocated [...] any glvalue that refers to the original object may be used but only in limited
ways. [...] using the properties of the glvalue that do not depend on its value is well-defined.

So by my understanding, what you are doing is well-defined.

(Although, being ultrapedantic, I don't think it's specified when the storage for an automatic object is allocated, and 8.3.2/5 says that "a reference shall be initialized to refer to a valid object" without defining "valid", so there's scope to argue that it's not well-defined).

Lambda returning itself: is this legal?

The program is ill-formed (clang is right) per [dcl.spec.auto]/9:

If the name of an entity with an undeduced placeholder type appears in an expression, the program is ill-formed. Once a non-discarded return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements.

Basically, the deduction of the return type of the inner lambda depends on itself (the entity being named here is the call operator) - so you have to explicitly provide a return type. In this particular case, that's impossible, because you need the type of the inner lambda but can't name it. But there are other cases where trying to force recursive lambdas like this, that can work.

Even without that, you have a dangling reference.


Let me elaborate some more, after discussing with somebody much smarter (i.e. T.C.) There is an important difference between the original code (slightly reduced) and the proposed new version (likewise reduced):

auto f1 = [&](auto& self) {
return [&](auto) { return self(self); } /* #1 */ ; /* #2 */
};
f1(f1)(0);

auto f2 = [&](auto& self, auto) {
return [&](auto p) { return self(self,p); };
};
f2(f2, 0);

And that is that the inner expression self(self) is not dependent for f1, but self(self, p) is dependent for f2. When expressions are non-dependent, they can be used... eagerly ([temp.res]/8, e.g. how static_assert(false) is a hard error regardless of whether the template it finds itself in is instantiated or not).

For f1, a compiler (like, say, clang) can try to instantiate this eagerly. You know the deduced type of of the outer lambda once you get to that ; at point #2 above (it's the inner lambda's type), but we're trying to use it earlier than that (think of it as at point #1) - we're trying to use it while we're still parsing the inner lambda, before we know what it's type actually is. That runs afoul of dcl.spec.auto/9.

However, for f2, we cannot try to instantiate eagerly, because it's dependent. We can only instantiate at point of use, by which point we know everything.


In order to really do something like this, you need a y-combinator. The implementation from the paper:

template<class Fun>
class y_combinator_result {
Fun fun_;
public:
template<class T>
explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}

template<class ...Args>
decltype(auto) operator()(Args &&...args) {
return fun_(std::ref(*this), std::forward<Args>(args)...);
}
};

template<class Fun>
decltype(auto) y_combinator(Fun &&fun) {
return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}

And what you want is:

auto it = y_combinator([&](auto self, auto b){
std::cout << (a + b) << std::endl;
return self;
});

What is the difference between a 'closure' and a 'lambda'?

A lambda is just an anonymous function - a function defined with no name. In some languages, such as Scheme, they are equivalent to named functions. In fact, the function definition is re-written as binding a lambda to a variable internally. In other languages, like Python, there are some (rather needless) distinctions between them, but they behave the same way otherwise.

A closure is any function which closes over the environment in which it was defined. This means that it can access variables not in its parameter list. Examples:

def func(): return h
def anotherfunc(h):
return func()

This will cause an error, because func does not close over the environment in anotherfunc - h is undefined. func only closes over the global environment. This will work:

def anotherfunc(h):
def func(): return h
return func()

Because here, func is defined in anotherfunc, and in python 2.3 and greater (or some number like this) when they almost got closures correct (mutation still doesn't work), this means that it closes over anotherfunc's environment and can access variables inside of it. In Python 3.1+, mutation works too when using the nonlocal keyword.

Another important point - func will continue to close over anotherfunc's environment even when it's no longer being evaluated in anotherfunc. This code will also work:

def anotherfunc(h):
def func(): return h
return func

print anotherfunc(10)()

This will print 10.

This, as you notice, has nothing to do with lambdas - they are two different (although related) concepts.

Variable used in lambda expression should be final or effectively final

A final variable means that it can be instantiated only one time.
in Java you can't reassign non-final local variables in lambda as well as in anonymous inner classes.

You can refactor your code with the old for-each loop:

private TimeZone extractCalendarTimeZoneComponent(Calendar cal,TimeZone calTz) {
try {
for(Component component : cal.getComponents().getComponents("VTIMEZONE")) {
VTimeZone v = (VTimeZone) component;
v.getTimeZoneId();
if(calTz==null) {
calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
}
}
} catch (Exception e) {
log.warn("Unable to determine ical timezone", e);
}
return null;
}

Even if I don't get the sense of some pieces of this code:

  • you call a v.getTimeZoneId(); without using its return value
  • with the assignment calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue()); you don't modify the originally passed calTz and you don't use it in this method
  • You always return null, why don't you set void as return type?

Hope also these tips helps you to improve.

Are Lambda expressions in C# closures?

A lambda may be implemented using a closure, but it is not itself necessarily a closure.

A closure is "a function together with a referencing environment for the non-local variables of that function.".

When you make a lambda expression that uses variables defined outside of the method, then the lambda must be implemented using a closure. For example:

int i = 42;

Action lambda = () => { Console.WriteLine(i); };

In this case, the compiler generated method must have access to the variable (i) defined in a completely different scope. In order for this to work, the method it generates is a "function together with the referencing environment" - basically, it's creating a "closure" to retrieve access to the variable.

However, this lambda:

Action lambda2 = () => { Console.WriteLine("Foo"); }

does not rely on any "referencing environment", since it's a fully contained method. In this case, the compiler generates a normal static method, and there is no closure involved at all.

In both cases, the lambda is creating a delegate ("function object"), but it's only creating a closure in the first case, as the lambda doesn't necessarily need to "capture" the referencing environment in all cases.

can a Common Lisp lambda function return itself?

The easiest thing is to pass the function itself as an argument, which is sort-of the U combinator. So given

(lambda (self ...) ...)

define (I don't have an implementation to hand, so this may be broken)

(defun funcall/U (f &rest arguments)
(apply f f arguments))

and now just call it with funcall/U. In particular if your functions want to recurse they now do it with funcall/U:

(lambda (self ...) ... (funcall/U self ...) ...)

What you describe with (defvar ...) ... (setf ...) is essentially how Scheme's letrec works by the way:

(letrec ((x (lambda (...) ... (x ...)))) ...)

turns into (something like)

(let ((x <illegal>))
(set! x (lambda (...) ... (x ...)))
...)

C++ lambda lexical closure over local variables

    return [&count] () -> int {

This is a capture by reference. The lambda captures a reference to this object.

The object in question, count, is in the function's local scope, so when the function returns, count gets destroyed, and this becomes a reference to an object that went out of scope and gets destroyed. Using this reference becomes undefined behavior.

Capturing by value seems to solve this problem:

    return [count] () -> int {

But your obvious intent is so that each invocation of this lambda returns a monotonically-increasing counter value. And merely capturing the object by value is not enough. You also need to use a mutable lambda:

 return [count] () mutable -> int
{
return ++count;
};

But the pedantical answer to your question "what happens" is that a lambda is essentially an anonymous class, and what a lambda captures are really class members. Your lambda is equivalent to:

class SomeAnonymousClassName {

int &count;

public:
SomeAnonymousClassName(int &count) : count(count)
{}

int operator()
{
// Whatever you stick in your lambda goes here.
}
};

Capturing something by reference translates to a class member that's a reference. Capturing something by value translates to a class member that's not a reference, and the act of capturing lambda variables translates to passing them to the lambda class's constructor, which is what happens when you create a lambda. A lambda is really an instance of an anonymous class, with a defined operator().

In a regular lambda, the operator() is actually a const operator method. In a mutable lambda, the operator() is a non-const, a mutable operator method.

How to get the address of a C++ lambda function within the lambda itself?

It is not directly possible.

However, lambda captures are classes and the address of an object coincides with the address of its first member. Hence, if you capture one object by value as the first capture, the address of the first capture corresponds to the address of the lambda object:

int main() {
int i = 0;
auto f = [i]() { printf("%p\n", &i); };
f();
printf("%p\n", &f);
}

Outputs:

0x7ffe8b80d820
0x7ffe8b80d820

Alternatively, you can create a decorator design pattern lambda that passes the reference to the lambda capture into its call operator:

template<class F>
auto decorate(F f) {
return [f](auto&&... args) mutable {
f(f, std::forward<decltype(args)>(args)...);
};
}

int main() {
auto f = decorate([](auto& that) { printf("%p\n", &that); });
f();
}

Modifying local variable from inside lambda

Use a wrapper

Any kind of wrapper is good.

With Java 10+, use this construct as it's very easy to setup:

var wrapper = new Object(){ int ordinal = 0; };
list.forEach(s -> {
s.setOrdinal(wrapper.ordinal++);
});

With Java 8+, use either an AtomicInteger:

AtomicInteger ordinal = new AtomicInteger(0);
list.forEach(s -> {
s.setOrdinal(ordinal.getAndIncrement());
});

... or an array:

int[] ordinal = { 0 };
list.forEach(s -> {
s.setOrdinal(ordinal[0]++);
});

Note: be very careful if you use a parallel stream. You might not end up with the expected result. Other solutions like Stuart's might be more adapted for those cases.

For types other than int

Of course, this is still valid for types other than int.

For instance, with Java 10+:

var wrapper = new Object(){ String value = ""; };
list.forEach(s->{
wrapper.value += "blah";
});

Or if you're stuck with Java 8 or 9, use the same kind of construct as we did above, but with an AtomicReference...

AtomicReference<String> value = new AtomicReference<>("");
list.forEach(s -> {
value.set(value.get() + s);
});

... or an array:

String[] value = { "" };
list.forEach(s-> {
value[0] += s;
});


Related Topics



Leave a reply



Submit