discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Which ObjC2.0 features are missing in the latest GCC?


From: Andreas Fink
Subject: Re: Which ObjC2.0 features are missing in the latest GCC?
Date: Tue, 26 Nov 2019 15:15:01 +0100


> On 26 Nov 2019, at 15:06, H. Nikolaus Schaller <address@hidden> wrote:
> 
> 
>> Am 26.11.2019 um 11:09 schrieb Pirmin Braun <address@hidden>:
>> 
>> I'd suggest a fork, i.e. "Gnustep2" with LLVM, Clang, libobjc2 
> 
> just came to my mind: ClangSTEP?


what a tong breaker. FreeStep sounds better to me :)
Drop the "GNU" and break free.


> 
>> 
>> On Tue, 26 Nov 2019 04:55:43 -0500
>> Gregory Casamento <address@hidden> wrote:
>> 
>>> I'd really like some resolution on this topic.   There seem to be a lot of
>>> reasons for and against.
>>> 
>>> GC
>>> 
>>> On Mon, Nov 25, 2019 at 1:04 PM David Chisnall <address@hidden>
>>> wrote:
>>> 
>>>> On 25 Nov 2019, at 14:07, H. Nikolaus Schaller <address@hidden> 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
>>>> 
>>>> 
>>>> 
>>> 
>>> -- 
>>> Gregory Casamento
>>> GNUstep Lead Developer / OLC, Principal Consultant
>>> http://www.gnustep.org - http://heronsperch.blogspot.com
>>> http://ind.ie/phoenix/
>> 
>> 
>> -- 
>> Pirmin Braun address@hidden +49 261 92199400 +49 174 9747584 
>> Geschäftsführer der Pirmin Braun GmbH www.pirmin-braun.de 
>> Im Palmenstück 4 - 56072 Koblenz - www.facebook.com/PB.ERP.Software
>> Registergericht: Koblenz HRB 26312 UStID: DE319238613 Steuernummer: 
>> 22/656/03918
> 
> 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]