I also found that wrapping the function inside of another function makes your original code almost work, though you’ll need the dot between “func” and the arguments into it:
No dot returns the same warning that you received.
Strangely though ~e.class is an Event, not IdentityDictionary. So perhaps the difference is in the fact that the know arg defaults to true in Event, but false in the IdentityDictionary. …Nope, I just tried using an IdentityDictionary with know: true and no difference.
There doesn’t appear to be any documentation for IdentityDictionary.doesNotUnderstand? But even if it works, that’s an incredibly ugly way to call a function.
If no matching method is found in any class in the superclass chain, the receiver is sent the message doesNotUnderstand:; the argument is the offending message.
And on p.95
respondsTo: aSymbol. Answer whether the method dictionary of the receiver’s class or one of its superclasses contains the argument, aSymbol, as a message selector.
e = ( f: {|self, a| a + 1 } );
e.respondsTo('f') == false;
e.f(5) == 6 // courtesy doesNotUnderstand
x = { |self, a = 1| a + 5 }
x.class // -> Function
z = (\func: { |self, a = 1| a + 5 }) // -> ( 'func': a Function )
z.func.class // -> Integer
Seems like the Event is attempting to resolve the function. Maybe that’s why wrapping it in an extra set of curly braces works? (Though not in pseudo-method syntax).
z = (\func: {{ |self, a = 1| a + 5 }})
z.func.class // -> Function
z.func.(a: 5)
Okay I understand where the message is coming from and what it means… but still, why doesn’t e respond to f? I think you’ve just restated my problem, or have I misunderstood?
I had the same question few times ago. I’ve messed a bit with it but didn’t really understand what was going on. The double function enclosure does the trick anyway.
I ended up finding that both Environment and IdentityDictionary do not respond to .addUniqueMethod, which I though might be related to this problem, but it also might not.
doesNotUnderstand { arg selector ... args;.... has no keyword ‘f’. So args is an empty array in the function body… so nothing is passed through at all, and this is because the following line doesn’t attempt to pass the arguments on somehow, and this can’t be altered in SCLang because of this one line in c++.
It would be nice to be able to defer the keywords as an Environment until the instance method has been found and then call performWithEnvir on it. I’d have a go at altering the c++, but its particularly nasty, in fact, it doesn’t look like anyone has modified this function seriously since James McCartney’s Initial revision commit in 2002!!
Anyway, thanks for pointing to the code, I am really unfamiliar with smalltalk (kinda hate it) particularly the terminology, but reading the code is always easier!