[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Which ObjC2.0 features are missing in the latest GCC?
From: |
David Chisnall |
Subject: |
Re: Which ObjC2.0 features are missing in the latest GCC? |
Date: |
Mon, 25 Nov 2019 17:46:28 +0000 |
On 25 Nov 2019, at 14:07, H. Nikolaus Schaller <hns@goldelico.com> wrote:
> I am not sure that this is the only way to implement it.
>
> First of all the callMethodOn returns some block which is a data structure
> knowing that it should take the parameter x and do some function.
> Let's call it NSBlock. NSBlock can be an ordinary object like any other so
> that it can follow the same memory management rules as used otherwise.
That’s shifting the goalposts somewhat. It is not news that objects and
closures are equivalent. Smalltalk implemented blocks as BlockClosure objects,
Ian Piumarta’s Composite Object-Lambda Architecture, and C++ lambdas (which are
just shorthand for C++ objects that implement `operator()`). You can always
express anything that uses blocks with objects.
There are two issues:
1. If you want to be compatible with existing APIs that use blocks, you need to
be ABI compatible with blocks.
2. The reason that most languages that have objects also have blocks is that
the shorthand syntax is very convenient.
The following are roughly equivalent:
```
@interface Delegate : NSObject
- (void)invoke;
- (instancetype)initWithCapture: (id)someObject;
@end
@implementation Delegate
{
@private
id obj;
}
- (instancetype)initWithCapture: (id)someObject
{
if ((self = [super init]) == nil) return nil;
obj = [someObject retain];
return self;
}
- (void)invoke
{
[obj doSomething];
}
- (void)dealloc
{
[obj release];
[super dealloc];
}
@end
// At construction site:
[[Delegate alloc] initWithCapture: x];
// At use site:
[delegate invoke];
```
And this, with blocks:
```
// At construction site:
^() { [x doSomething]; };
// At use site:
delegate();
```
At use, these are similar complexity for the programmer. At the point of
construction, one is one line of code (two or three if you put lambda bodies on
their own lines), the other is 26. As a programmer, I don’t want to write 26
lines of code for a one-line callback.
In C++98 you could probably template that and provide a generic class that took
a struct containing the captures and a C function, so you’d get a lot less
boilerplate. Assuming you had fudged ARC like this (as above, this code is
typed into a mail client and probably doesn’t compile):
```
template<typename T>
struct ObjCObjectWrapper
{
ObjCObjectWrapper(T x) : obj(objc_retain(x)) {}
ObjCObjectWrapper(const ObjCObjectWrapper &other) :
obj(objc_retain(other.obj) {}
ObjCObjectWrapper(ObjCObjectWrapper &&other) : obj(other.obj)
{
other.obj = nil;
}
ObjCObjectWrapper()
{
objc_release(obj);
}
operator=(T x)
{
objc_storeStrong(&obj, x);
}
T operator()
{
return obj;
}
private:
T obj;
};
```
You could then define a generic capture structure and invoke method like this:
```
template<typename Capture, typename Ret, typename... Args>
struct BlockImpl
{
using invoke_t = Ret(*)(Capture &, Args...);
void operator()(Args... args)
{
inv(capture, std::forward<Args>(args)…);
}
Block(Capture &&c, invoke_t fn) : capture(c), inv(fn) {}
private:
Capture capture;
invoke_t inv;
};
```
This is then generic and you could use it as follows:
```
struct CaptureOneObject
{
ObjCObjectWrapper<id> o;
};
void invoke(CaptureOneObject &c)
{
[(id)c.o doSomething];
}
// At construction site:
std::function<void(void)> block(BlockImpl<CaptureOneObject, void>({x}, invoke));
// At use site:
block();
```
I *think* you could get the same ABI as blocks if you worked on the generic
templated boilerplate a bit.
Of course, if you were using C++ then you could also write it using lambdas as:
```
// At construction site
ObjCObjectWrapper<id> capture(x);
auto block = [=capture]() { [(id)capture.o doSomething]; };
// At use site:
block();
```
And with this you don’t need the invoke function or the capture class. Again,
much less boiler plate for users, though we don’t have ABI compatibility with
blocks.
If you were using ARC and C++, then this reduces even further to:
```
auto block = [=]() { [x doSomething]; };
```
And now we’re back with different syntax for the same thing, though with a
different ABI (I think Clang has support for implicitly converting C++ lambdas
to blocks, but it’s been a few years since I tried)
David
- Re: Which ObjC2.0 features are missing in the latest GCC?, (continued)
- Re: Which ObjC2.0 features are missing in the latest GCC?, H. Nikolaus Schaller, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, Gregory Casamento, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, H. Nikolaus Schaller, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, Gregory Casamento, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, H. Nikolaus Schaller, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, Maxthon Chan, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, Gregory Casamento, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, H. Nikolaus Schaller, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, David Chisnall, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?, H. Nikolaus Schaller, 2019/11/25
- Re: Which ObjC2.0 features are missing in the latest GCC?,
David Chisnall <=
- Re: Which ObjC2.0 features are missing in the latest GCC?, Gregory Casamento, 2019/11/26
- Re: Which ObjC2.0 features are missing in the latest GCC?, Max Chan, 2019/11/26
- Re: Which ObjC2.0 features are missing in the latest GCC?, Pirmin Braun, 2019/11/26
- Re: Which ObjC2.0 features are missing in the latest GCC?, H. Nikolaus Schaller, 2019/11/26
- Re: Which ObjC2.0 features are missing in the latest GCC?, Andreas Fink, 2019/11/26
- Re: Which ObjC2.0 features are missing in the latest GCC?, Pirmin Braun, 2019/11/26
- Re: Which ObjC2.0 features are missing in the latest GCC?, Umberto Cerrato, 2019/11/26
- Re: Which ObjC2.0 features are missing in the latest GCC?, hasebastian, 2019/11/26
- libobjc2 build issue, Andreas Fink, 2019/11/26
- Re: libobjc2 build issue, Johannes Brakensiek, 2019/11/26