-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
invoke method is not working #422
Comments
Okay, there are lots of interesting things going wrong here. Starting with the simple and heading towards the complex:
however, genMethods now calls the builtin function methodnames to generate the names of methods. But methodnames returns the internal names of class methods, e.g. "DTest__write". I think this is wrong but, again, what breaks if it's fixed? One would think that a workaround would be to modify genmethods to map the internal names back into external ones. That's not sufficient because invoke(), assuming that's fixed, will die because the table lookup it uses (self.__m[mName]) will fail because the external name, e.g. "DTest::write" won't be found in __m - it needs to be just "write", so a 2nd workaround is needed to map the full external method name into its simple form. Note that fixing the 'wrong' methodnames function to return the simple form of method names would be sufficient unto itself (he claims). |
This is an amazingly insightful reply. Thank you! My current workaround is to use Output:
|
I'm not sure what's causing the "Child::print()" output or even it's the "Right Thing To Do" but one suggestion for your code: in place of upto(cname||""), use find(cname||"") the upto function converts its first argument to a cset and goes up to the first appearance of any character in that cset. You're actually lucky that the class names you've got work with upto. I assume also that this is a test program to explore behavior. Ordinarily, omitting the print method from Child would default a call to print to the Parent's print() [but still output "Child::print()", of course]. However, the run() method won't find the Parent's print method in that case. I suspect you know that and are just experimenting. |
Ah, the reason run() doesn't find the print() method in Parent when the subclass doesn't have it is because methodnames() is only returning the 'local' methods, not any derived from ancestors. This is, he claims, another problem with the methodnames implementation. The __m list has all the methods (included inherited ones) in it but methodnames() only provides the local ones. I ;think fixing methodnames() and invoke() may be non-trivial. |
I played around a bit with your test program and made some changes. The big ones are that the run() method: (a) now takes as a argument the name of the method (e.g. "print") to run. This version doesn't accept any arguments to pass to that method - that should be fixed. (b) now can find a method that exists back in the class hierarchy (it avoids using the broken methodnames) (c) only involkes the first instance of a method from the hierarchy, starting from the 'local' and going up into superclasses Assuming the issue stated in (a) is addressed, I think the run() method points to a viable replacement for the invoke() method. Anyway, the amended code: class Parent(__objects) method print() method run(s) # Pass in name of method to run, should also pass in args but doesn't yet...
end initially class Child : Parent() class Anonymous() procedure main() |
Good morning Ian,
For my purposes, I built a class hierarchy to get around some of the
problems within the library Class/Object that I found. My particular
solution is found in the two files in lib called classobject.icn and
errorsystem.icn.
This is used in utf8.icn (also in lib).
Fundamentally, the problem is that there is no direct correspondence
between the user visible package/class/method names and the internal
names. I am looking at a possible change here, but only after I finish
the new keyword additions.
regards and blessings
Bruce Rennie
…On 17/4/24 21:37, Ian Trudel wrote:
This is an amazingly insightful reply. Thank you! My current
workaround is to use |__m[mname]| but it's not without its flaws. It
requires the receiver object to be passed on as the first parameter,
i.e. |object.__m[nmane](object)|, otherwise it will send it to self.
In the following code example, you will notice that the output is
|Child::print()| instead of |Parent::print()|, which is not a typical
behaviour for OOP. It would most likely require to call
|o.__m[mname](self)| in the run method of the Parent class.
Output:
|Anonymous::print() Child::print() |
|class Parent(__objects) method add(o) put(__objects, o) end method
print() write(classname(self) || "::print()") end method run() local
mname every o := !__objects do { cname := classname(o) every m :=
!methodnames(o) do { m ? { tab(upto(cname || "_")) & move(*cname + 1)
mname := tab(0) } o.__m[mname](o) } } end initially __objects := []
end class Child : Parent() method print() self.Parent.print() end end
class Anonymous() method print() write(classname(self) || "::print()")
end end procedure main() p := Parent() a := Anonymous() c := Child()
p.add(a) p.add(c) p.run() end |
—
Reply to this email directly, view it on GitHub
<#422 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAUUHFKSU7MMIKPSQRVYGBTY5ZNF5AVCNFSM6AAAAABGGMZF4WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANRRGA2TMMJVHA>.
You are receiving this because you are subscribed to this
thread.Message ID: ***@***.***>
|
Here's a potential replacement for the invoke() method in uni/lib/object.icn. It avoids the problem of mapping between internal/external/simple method names. I've only tested it a little, so caveat emptor! method invoke(s, A[])
end |
You can edit a previous post by pressing the three dots at the top right corner of post. |
Thank you for the tip!
I believe this is acceptable considering that Unicon implements multiple inheritance. One could end up with several methods with the same name. The way one would list the parent's methods would perhaps be something like
I tried something like that but couldn't get it to work. Calling
Smalltalk has defined the behaviour of self to be bound by the class it is used in. In Child, self should be the current instance of Child, and, in Parent, self should be the current instance of Parent. For some reason, Unicon seems to flatten the concept of self where there is no class hierarchy. This is the point I was illustrating in the code example.
@brucerennie this is how I figured out how to properly use __m. I would still be stuck without your work. |
I have been writing a unit test framework based on Kent Beck's original SUnit. The idea is to fully embrace Unicon OOP and also better integrate with your CI, where failing tests would result in failed build — then you don't get to wait years before someone shows up with issues like those in objecttests. This is work in progress. I am working on assertions and then a TestReporter. The TestReporter will be a class on its own because someone may someday want to integrate it to the Unicon IDE, they can write their own TestReporter accordingly. Hope this clarifies a few things.
|
@IanTrudel tests are very welcome, thank you for doing the work. FYI, we do have tests run as part of the CI (see Test here). We are close to changing that so that any failed test would fail the CI. We are in the process of fixing the remaining failing tests or at least isolating them. |
My pleasure!
Great work on the CI, by the way! I was surprised to see support for so many targets. |
@StephenWampler Your solution turned out pretty well. It's clean and straightforward.
|
@StephenWampler, wanna go after some of the issues you identified? We should attempt to fix those. If they break any existing applications we can discuss. |
Invoke should be fixed with issue #441. Also, despite multiple inheritance, only one of any duplicated method is ever visible to the subclass. There's a fix in #441 so all of the visible methods available to a subclass are produced by genMethods(). objecttests.icn now produces the expected output. Note that the function (i.e. "builtin") methodnames is still broken. My C is so far in the past the I'm absolutely the wrong person to try and fix it. I know. I looked. It's pretty much greek to me... |
I'm going to close this issue since invoke() now works as expected. I'm also going to open a new issue on the fact that methodnames() doesn't generate inherited methods visible to the subclass. |
The package lang provides the utility method invoke but it does not work. It was confirmed when I ran objecttests. Unicon version 13.3 on Linux.
Output from unicon/tests/lib/objecttests.icn:
The text was updated successfully, but these errors were encountered: