September 27, 2006
On Wed, 27 Sep 2006 20:44:05 +0200, Lutger wrote:

> Josh Stern wrote:
>> On Wed, 27 Sep 2006 17:55:03 +0200, Lutger wrote:
>> 
>> I found this comparison of different C++ approaches to signal slots with a web search.
>> 
>> http://slotsig.sourceforge.net/doc/features-compare.html
>> 
>> Can't vouch for the validity of the summary, but it might be a good starting point for further investigation.
>> 
>> 
> 
> Nice list, there are also a few benchmarks there. Depending on
> interpretation of course, my sigslots library scores equal points
> feature-wise as slotsig. There are some features in slotsig which might
> be worth investing, thank you for the link.
>   These lists are always biased, but the biggest advantages of QT are
> not listed: dynamic connections which make it possible to, for example,
> script connections, load from xml resource, etc. This is where string
> based sigslots or - as I understand - Objective C is superior to the
> template-based implementations.

The issues of what has to be decided at design time, compile time, and
run time in order to use signals and  slots are important.
Requiring inheritance from QObject for some things is one kind
of strong restriction, and requiring connections specified at
compile time is another.  There are language vs. library issues
involved here.  A (the?) key language feature seems to be the question of
what kind of support does the language provide for making it easy to
attach a "hook" to a given function (where hook means roughly "now
Mr.Ffunction, from now on, before you exit, please call this other
function I'm about to tell you about with your return value as
its input and maybe some other info like a pointer to your object in case
you are a member function"). I agree with the implicit point made by the
slotsig guy that part of this mechanism ideally should give the user
options about thread-safety and thread-locality. Seems like if the
language provides a really good hook mechanism, a lot of convenient
library stuff can be built on top to taste. Intuitively it seems like D's
system of Boxs and delegates could be put to good use towards finding
attractive possibilities within the library problem design space, and
having GC to eliminate most ownership issues makes many solutions a lot
simpler.





September 27, 2006
Josh Stern wrote:
<snip>
> The issues of what has to be decided at design time, compile time, and run time in order to use signals and  slots are important. Requiring inheritance from QObject for some things is one kind
> of strong restriction, and requiring connections specified at
> compile time is another.  There are language vs. library issues
> involved here.  A (the?) key language feature seems to be the question of
> what kind of support does the language provide for making it easy to
> attach a "hook" to a given function (where hook means roughly "now
> Mr.Ffunction, from now on, before you exit, please call this other
> function I'm about to tell you about with your return value as
> its input and maybe some other info like a pointer to your object in case
> you are a member function"). I agree with the implicit point made by the
> slotsig guy that part of this mechanism ideally should give the user
> options about thread-safety and thread-locality. Seems like if the
> language provides a really good hook mechanism, a lot of convenient
> library stuff can be built on top to taste. Intuitively it seems like D's
> system of Boxs and delegates could be put to good use towards finding
> attractive possibilities within the library problem design space, and
> having GC to eliminate most ownership issues makes many solutions a lot
> simpler.   

Yes, although I would not see requiring connections at compile time as a  restriction, I would file this under 'feature' as it enables compile-time type checking. It's a choice really, connections at runtime are more flexible but less safe and incur performance cost. Requiring inheritance (but more so custom preprocessor) in QT is needed to make up for lack of introspection in C++.
Ideally you'd have both systems available to choose the appropiate one for what you want.
September 28, 2006
Bill Baxter skrev:
> Howdy.
> 
> Fredrik Olsson wrote:
>> How Obj-C Cocoa does it:
>>
>> Each object can have an action and a target. 
> 
> By this you mean each GUI widget can have an action and target, right?
> 
Yes. Or in practice three combination (A = action set, T = target set):
A && T   = Will trigger A in T.
A && !T  = Will trigger A in responder chain.
!A = Will rigger nothing, ignores T.

>> An action is an event that is signaled at run-time, and the target is an object instance to call. If target is nil (null) then the action will be sent to the responder chain, instead of a predestined object.
> 
>> The responder chain is implemented in the NSResponder protocol (Interface) and will send the action down the controllers is logical order acording to how windows are stacked, ending up in the NSApplication instance if no one else is interested. 
> 
> So it forms a kind of tree or funnel with leaves being widgets, and the root being the NSApplication instance.
> 
Yes.

>> This make sure that if a single menu item (OSX == one menu you know :) ) has nil as target, then the topmost window will get a chance to respond first, and yet the same item will work for all windows.
> 
> Don't really follow you there.  Why does the topmost window get the first chance?  Just before you said it went up a chain, so it seems like the immediate container window of the item would get the first chance, and eventually the topmost window will get a chance.
> 
> Anyway, this part of your description seems much more Cocoa than Objective C.  I.e. it seems independent of the language itself, more or less just the classic "chain of responsibility" pattern.  Just something implemented on top of the messaging sys provided by Obj-C.
> 
Yes the responder chain is implemented in Cocoa, but it relies heavily on Obj-C's ability to let objects forward invocations of methods they do not implement themselves.

The topmost window needs the first chance as if for example the user presses Command-B for "make bold", then the first object that needs to know about it is probably on the topmost object, and with the cursor in it. The responder chain sends messages like this:
1. The key window’s first responder and successors, including objects
   added with setNextResponder:
2. The key window itself
3. The key window’s delegate (which need not inherit from NSResponder)
4. The main window’s first responder and successors, including objects
   added with setNextResponder:
5. The main window itself
6. The main window’s delegate (which need not inherit from NSResponder)
7. The application object, NSApp
8. The application object’s delegate (which need not inherit from
   NSResponder)

>> You connect an action/target like this:
>> [obj1 setAction:@selector(valueChanged:)];
>> [obj1 setTarget:obj2];
> 
>> And you can later "emit" the action using:
>> [obj1 sendAction:[obj1 action] to:[obj1 target]];
>> which will cause the valueChanged: method of obj2 to be performed. In reality most classes have shortcuts such as sendAction, and even more so you rarely need to care about sending manually at all.
> 
> Ok, I'm trying to grok these message things now.
> It looks like there's no distinction between method names and call parameters.  Like here:
>  > [obj1 setAction:@selector(valueChanged:)];
> setAction looks sort of like a method with parameter being a selector. But then here:
>  > [obj1 sendAction:[obj1 action] to:[obj1 target]];
> it looks like there are two methods, 'sendAction' and 'to'.
> And I take it [obj1 action] is a named attribute lookup, similar to a QProperty?
> 
Hmm... now this is strange, and it took a while for me to grasp it as well :). Lets take this one:
[obj1 sendAction:[obj1 action] to:[obj1 target]]
It is actually three method calls, two of them nested.
[obj1 action] is calling obj1's method action, and that method returns a selector, a selector is a method.
[obj1 target] is also a method call, but returning an object instance.

So you could rewrite that as:
SEL selector = [obj1 action];
id target = [obj1 target];
[obj1 sendAction:action to:target];
This last statement is a single method call, with two arguments, and no result obviously. The name of the method is "sendAction:to:", so if you wanted the selector for that method you would do:
SEL selector = @selector(sendAction:to:);

Methods with : in their names takes parameters, one parameter after each :, and sometimes a list of parameters after the last :.
You would for example use the "fileExistsAtPath:isDirectory:" method of a NSFileManager object to check if a file exists, and if it then is a directory. Used like this:
id fm = [NSFileManager defaultManager]; // Get the shared instance
BOOL isDir = NO;
BOOL doesExist = [fm fileExistsAtPath:@"/tmp/foo" isDirectory:&isDir];

If this syntax look wierd, then here is the method definition :) :
- (BOOL)fileExistsAtPath:(NSString *)path
        isDirectory:(BOOL *)isDirectory
{
  ...
}


> Fredrik Olsson wrote:
>  > Lucas Goss skrev:
>  >> Bill Baxter wrote:
>  >>
>  >>> Gotta go, but I think some sort of built-in dynamic dispatch
>  >>> mechanism like this would have to be part of my "dream language".
>  >>>
>  >> I think I'm of the same opinion. I'm just starting to learn Obj-C now...
>  >
>  > I want to agree as well. But hmm... how D and Obj-C tackles OOP is so
>  > very different that I can not see any way to merge the two.
> 
> Is it really so difficult?  Maybe I just don't understand how Obj-C works well enough, but in Obj-C you have both regular C function calls (do_something(foo)) and message passing ([obj doSomething:foo]) and the user decides which paradigm to use at what time.  Similarly in an Obj-D you could have regular method calls (obj.do_something(foo)) and messaging calls ([obj doSomething:foo]).
> 
Well... D-methods, and Obj-C methods are invoked in very different ways. Their "bhind the scenes" implementation is vastly different. And I see no easy way to treat a D-method as if it where a Obj-C-method, and vice versa.


> It seems like it could work more or less the way slots do in Qt.  If I have:
> # slot:
> #   void callMeLater(int val);
> 
> In a Qt program, then callMeLater is a valid method that can be called like any other method.  But it is *also* callable via dynamic lookup using QObject's under-the-hood moc-generated mechanisms. I don't see why a similar idea wouldn't work for adding a touch of Obj-C to D.
>
Everything can be done, I just think that if you want interoperability, and syntax compatibility with existing D-methods then you will have to make trade offs. And with those tradeoffs, you lose much of the power from Obj-C. And then a template based S&S solution would be best.

In the end a template based S&S is probably the way to go anyway, D was never intended to use the Smalltalk school of OOP.


>  > So just as you can not seamlessly mix C++ classes and Obj-C classes in
>  > Objective-C++, I can not see how D classes and Obj-C classes could be
>  > mixes seamlessly in any practical way.
> 
> Maybe I'm just not seeing the full scope of how Obj-C works yet.  But nothing I've heard so far seems like an insurmountable hurdle.
> 
> It just doesn't seem a very attractive proposition to me to have to decide at initial design time whether my class will have regular methods or use dynamic messaging.  I may know I want to start out with one or the other, but then I want my static class to recieve a particular message from a GUI.  I guess these guys at Apple have given it some thought with Obj-C++, but my initial reaction was that keeping the types of classes completely separate must be some kind of corner cutting to get the thing out the door quickly, or perhaps having something to do with preserving C++ compatibility.
> 
Objective-C++ does not touch any of the ++ parts of C. Just as Objective-C does not touch anything of how C works. Objective-C is a pure superset on top. So Objective-C++ is in reality a programming language with two OOP implementations. One from the Simula school; the untouched C++, and one from the Smalltalk school; the very same superset as used in Objective-C.

The ++-classes have no clue that the Objective-classes exists, and vice versa.

"Objective" do only add one syntactic element to C (Or C++); message passing, to invoke methods. And for this it uses the [object message] syntax. For the rest of "Objective" the preprocessor roots can very easily be seen; for one all keywords begin with the @ character.
@selector(foo)
@interface MyClass : SuperClass
@end
etc.
And all they do is constructing constants, and "hidden" functions calls to setup the run-time at program start. Something that could easily be stuffed away in static constructors of each module in D.


// Fredrik Olsson

September 28, 2006
> Hmm... now this is strange, and it took a while for me to grasp it as
> well :). Lets take this one:
> [obj1 sendAction:[obj1 action] to:[obj1 target]]
> It is actually three method calls, two of them nested.
> [obj1 action] is calling obj1's method action, and that method returns a
> selector, a selector is a method.
> [obj1 target] is also a method call, but returning an object instance.

The best explanation is that Objective-C is modelled after Smalltalk. A method in C might be:

int AddAToX(int& a, int x);

where as in Objective C it would be:

- (int) Add: (int) a To: (int) x;

where the Method signature is Add:To:. Smalltalk would use almost the same structure.



October 01, 2006
Hey there,

Fredrik Olsson wrote:
> Bill Baxter skrev:
>>  > [obj1 sendAction:[obj1 action] to:[obj1 target]];
>> it looks like there are two methods, 'sendAction' and 'to'.
>> And I take it [obj1 action] is a named attribute lookup, similar to a QProperty?
>>
> Hmm... now this is strange, and it took a while for me to grasp it as well :). Lets take this one:
> [obj1 sendAction:[obj1 action] to:[obj1 target]]
> It is actually three method calls, two of them nested.
> [obj1 action] is calling obj1's method action, and that method returns a selector, a selector is a method.
> [obj1 target] is also a method call, but returning an object instance.

That's very interesting.  Can you also reverse the order of arguments in the call, like to:sendAction:?  Or is that a different method?
   [obj1 to:[obj1 target] sendAction:[obj1 action]]

--bb
October 02, 2006
Bill Baxter skrev:
> Hey there,
> 
> Fredrik Olsson wrote:
>> Bill Baxter skrev:
>>>  > [obj1 sendAction:[obj1 action] to:[obj1 target]];
>>> it looks like there are two methods, 'sendAction' and 'to'.
>>> And I take it [obj1 action] is a named attribute lookup, similar to a QProperty?
>>>
>> Hmm... now this is strange, and it took a while for me to grasp it as well :). Lets take this one:
>> [obj1 sendAction:[obj1 action] to:[obj1 target]]
>> It is actually three method calls, two of them nested.
>> [obj1 action] is calling obj1's method action, and that method returns a selector, a selector is a method.
>> [obj1 target] is also a method call, but returning an object instance.
> 
> That's very interesting.  Can you also reverse the order of arguments in the call, like to:sendAction:?  Or is that a different method?
>    [obj1 to:[obj1 target] sendAction:[obj1 action]]
> 
> --bb
That would be a different method. The full method declaration is:
- (void)sendAction:(SEL)action to:(id)target;
But the method signature is always typeless and is thus:
sendAction:to:
In practice the type SEL is a char*, and @selector(sendAction:to:) will be a char* to the null terminated string "sendAction:to:". What the @selector() "macro" does is to guarantee that there is only a single pointer to each method signature string so that
if ([item action] == @selector(removeUser:)) { ... }
is guaranteed to work.

Would be nice if you could rearrange the arguments though. But well, they are part of the method signature, not named arguments.


// Fredrik Olsson
1 2
Next ›   Last »