Discussions related to Visual Prolog
Peter Muraya
VIP Member
Posts: 147
Joined: 5 Dec 2012 7:29

Aborting an implementation and continue inheritance

Unread post by Peter Muraya »

Hi,
I often encounter situations when I need to abort an implementation in favor of inheritance as shown in the following code. The gist of the problem is that when the sex of the child is female, I want it to exhibit the mother behavior; otherwise it exhibits its own. The mother behavior is rather simple here, but it can be a complex piece of code, so that code repetition is not an option. I have gone round this issue in more ways than one all of which I don't feel are elegant. Is there are formal mechanism in object-oriented programming for achieving this purpose?

Code: Select all

interface mother      predicates           execute:(). end interface   class mother:mother end class   implement mother      clauses             execute():-console::write("Exhibit the mother "). %            step 1. end implement     interface child supports mother      domains           sex = male; female.      properties            sex:sex. end interface     class child:child      constructors           new:(sex). end class   implement child      facts            sex:sex:=erroneous.      clauses           new(Sex):-sex:=Sex.             execute():-execute(sex).         predicates            execute:(sex).       clauses             execute(female):-                   /*                   How do you abort this implementation and inherit the mother behaviour implemented in step 1?*/                   mother::execute(). %invalid option.               execute(male):-                   console::write("Exhit other behaviour"). end implement     implement main     open core   clauses     run() :-         X = child::new(child::male),         X:execute().   end implement main   goal     console::runUtf8(main::run),     console::readchar()=_.
Mutall Data Management Technical Support
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

In my world it is wrong to let child support mother, because children are not mothers.

The motivation for the question seem to be based on this "wrong" idea.

I find it vey difficult to advise good programming practice for something which is fundamentally bad design.

Your problem/question may be fully reasonable, but it will need another setup for my assistance.
Regards Thomas Linder Puls
PDC
Martin Meyer
VIP Member
Posts: 328
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer »

Yep, children are not mothers. We should always try to choose names in example code as intuitive as possible. To improve it, I propose renaming mother to legalPerson. Legal persons can be juridical persons (for instance joint-stock companies) or natural persons (as for example children). Assuming this renaming one way to get the example working out would be:

Code: Select all

interface legalPerson      predicates           execute : (). end interface   class legalPerson : legalPerson end class   implement legalPerson     clauses         execute() :-             console::write("I am some legal person\n"). end implement   %---   interface child     supports legalPerson       domains         sex = male; female.       properties         sex : sex. end interface   class child : child     constructors         new : (sex). end class   implement child     inherits legalPerson  % Inherit the implementation from legalPerson       facts         sex : sex.       clauses         new(Sex) :-             sex := Sex.       clauses         execute() :-             execute(sex).       predicates         execute : (sex).     clauses         execute(female):-             legalPerson::execute(). % Call the predicate's implementation inherited from legalPerson         execute(male):-             console::write("I am a male child\n"). end implement   %---   implement main     open core   clauses     run() :-         Child = child::new(child::male), % Create a male child         Child:execute(),         Child:sex := child::female, % Reassign child's gender to female         Child:execute().   end implement main
Many regards
Martin
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

I am not sure if the example is better now ;-).

But I am sure it still doesn't help me to understand what kind of construction we are looking for.

The problem seems to be that given some arbitrary property (here whether sex is male or female) we either want to inherit something or use a reimplementation.

But that seems to suggest that we actually want to choose between two completely independent implementations (i.e. where none inherits from the other):

Code: Select all

interface something     predicates         execute : (). end interface something   class kind1 : something end class kind1   class kind2 : something end class kind2   implement kind1 clauses     execute() :- stdio::write("kind1\n"). end implement kind1   implement kind2 clauses     execute() :- doSomehtingDifferent(). end implement kind2   class somethingFactory predicates     mkSomething : (boolean Condition) -> something Something. end class somethingFactory   implement somethingFactory clauses     mkSomething(true) = kind1::new().       mkSomething(false) = kind2::new().   end implement somethingFactory
Regards Thomas Linder Puls
PDC
Peter Muraya
VIP Member
Posts: 147
Joined: 5 Dec 2012 7:29

Unread post by Peter Muraya »

Thanks Thomas and Martin.
I'm not sure I completely understand the issue Thomas is raising, but I think Martin's example solves my problem elegantly. The key is in the 2 statements:

Code: Select all

implement child  inherits legalPerson  % Inherit the implementation from legalPerson
and

Code: Select all

legalPerson::execute(). % Call the predicate's implementation inherited from legalPerson
In my code:-

Code: Select all

implement child
I failed to explicitly state the inheritance (as I had not quite understood its significance for this purpose) and so the compiler raised the error message. Undeclared identifier 'legalPerson::execute/0', the identifier is known as 'execute/0' in the interface 'legalPerson'

Now I understand it. Thanks again.
Mutall Data Management Technical Support
Martin Meyer
VIP Member
Posts: 328
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer »

The construction I've posted comes most close to your initial example. That's why you are happy with it at first sight. However in most cases in praxis such kinda construction imposes unnecessary complications. That's -I think- the issue Thomas is raising.

The complication, which is suspected of being unnecessary, is, that the child implementation contains explicite programming instructions to (conditionally) redirect calls to execute/0 to its parent-object's implementation. However better is, when the distribution of predicate calls to their implementations is accomplished implicitely, solely through the language's object-oriented features, i.e. mainly through supports and inherits qualifications.

Maybe, if you present the intentions of your code in sufficient detail, Thomas (or might be even me) can come up with a more appropriate object design than that of the version I have posted. In the simplest use case the construction, which Thomas has given above already, will be optimal to do the job.

Best regards
Martin
Martin Meyer
VIP Member
Posts: 328
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer »

Below a better version of the example. I suppose the construction is appropriate, provided it's required (for reasons which are not covered by below example code skeleton) that
  • execute/0 predicate of class child inherits its implementation from parent object iff sex is female,
  • property sex has input and output flow, i.e. sex is changeable after a child object has been created.

Code: Select all

interface legalPerson      predicates           execute : (). end interface   class legalPerson : legalPerson end class   implement legalPerson     clauses         execute() :-             console::write("I am some legal person\n"). end implement   %---   interface child     supports legalPerson       domains         sex = male; female.       properties         sex : sex. end interface   class child : child     constructors         new : (sex). end class   implement child     inherits legalPerson       delegate execute/0 to executeLegalPerson_fact       facts         executeLegalPerson_fact : legalPerson.       clauses         new(Sex) :-             sex := Sex.       clauses         sex(male) :-             executeLegalPerson_fact := This.         sex(female) :-             executeLegalPerson_fact := erroneous.       clauses         sex() =             if isErroneous(executeLegalPerson_fact) then                 female             else                 male             end if.       clauses         execute() :-             console::write("I am a ", sex, " child\n"). end implement   %---   implement main   clauses     run() :-         Child = child::new(child::male),         Child:execute(),         Child:sex := child::female,         Child:execute().   end implement main
Best regards
Martin
Martin Meyer
VIP Member
Posts: 328
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer »

It's even possible to have a standard object design, i.e. not delegating/redirecting anything, and at the same time (correspondingly) meet the requirements of the two bullets in my prior post, when object types legalPerson and child are made persistent. For an example of a modifiable vs. a persistent object type check out setM vs. setP in the PFC. This is a version of the example with persistent object types:

Code: Select all

interface legalPersonP      predicates           execute : (). end interface   class legalPersonP : legalPersonP end class   implement legalPersonP     clauses         execute() :-             console::write("I am some legal person\n"). end implement   %---   interface childP     supports legalPersonP       domains         sex = male; female.       predicates         setSex : (sex) -> childP.       predicates         getSex : () -> sex. end interface   %---   class childP_male : childP end class   implement childP_male       clauses         setSex(male) = This.         setSex(female) = childP_female::new().       clauses         getSex() = male.       clauses         execute() :-             console::write("I am a male child\n"). end implement   %---   class childP_female : childP end class   implement childP_female     inherits legalPersonP       clauses         setSex(male) = childP_male::new().         setSex(female) = This.       clauses         getSex() = female.   end implement   %---   implement main   clauses     run() :-         Child_0 = childP_male::new(),         Child_0:execute(),         Child_1 = Child_0:setSex(childP::female),         Child_1:execute().   end implement main
Regards
Martin
Peter Muraya
VIP Member
Posts: 147
Joined: 5 Dec 2012 7:29

Unread post by Peter Muraya »

Hi Martin,
Thanks for the effort you take to understand a partially/poorly specified problem; I think your first example is clearer to me than the alternative, but I always learn something new from your coding, including this construct:-

Code: Select all

sex() =             if isErroneous(executeLegalPerson_fact) then                 female             else                 male             end if.
I guess this is a shorter form of:-

Code: Select all

sex() =X:-             if isErroneous(executeLegalPerson_fact) then                 X=female             else                 X=male             end if.
Mutall Data Management Technical Support
Martin Meyer
VIP Member
Posts: 328
Joined: 14 Nov 2002 0:01

Unread post by Martin Meyer »

yes, if-the-else expressions came as a new feature with build 7401.
I have learned by Thomas' answers to your questions already too.

Regards
Martin
Post Reply