Tuesday, December 8, 2015

Languages HW5

CS4250: Programming Languages
HW5: Eric Buckley – 18148800

12.8) Two problems with abstract data types ameliorated by inheritance are ease of customization and the lack of an organizing taxonomy. Without inheritance, an abstract type must either be modified directly (which may not even be possible in the case where the type is defined in a third-party library) or copied to a new data type and modified, which breaks down the generality of the type. By inheriting the type, derived objects benefit from the common functionality, but are free to augment or override aspects which do not match the application.
Inheritance also provides taxonomy of objects within the model. This is more than mere organization; it specifies what types of operations can or must be supported by which objects. A method that operates on the parent class, should also work on any derived class. Methods and properties of the parent class should also be offered by derived classes. This allows for more general (or even generic) routines to be written which operate on abstract classes higher in the derivation tree to consistently apply operations to related objects.

12.12) A subclass has an “is-a” relationship with its parent class when the subclass represents a more specific case of the parent class. For example, a class of Pane could be a subclass of ScreenObject where the former gave specific implementations of virtual methods for displaying and resizing the object on the screen. While this is the most common Parent-Subclass relationship, it is certainly not the only one. For example, a business object may inherit from an output class to pick up display routines, even though it is in no way a special case of an output device. Many architects believe that interfaces are a better way of handling such situations.

12.16) The primary reason for requiring that all Java objects descend (directly or indirectly) from the root class object is that this enforces the ability to handle any object in a generic sense. For example all objects implicitly have a ToString() method, which is useful in exception handlers where the handler may have little or no information about the nature of the object throwing the exception. Likewise, any object can be placed in a generic container of objects. Implicit methods, such as dereferencing and garbage collection also can be written at the level of the single root object, rather than having to define them for each object type that has no parent.

12.21) Objective-C protocols and Java interfaces serve much the same function and, in practical terms, their use is very similar. Perhaps the most significant difference is the fact that interfaces can be used to type an object. Any object that implements an interface can be cast as an object of that type and passed as parameters or assigned to variables that are typed as the interface itself, rather than a class that implements that interface. This greatly simplifies writing generic routines such as storing, sorting, and searching objects where the underlying structure of the object is irrelevant to the operation as long as the interface can provide enough information to carry out the task.

12.24) C# does, in fact, support non-static nested classes that act like inner classes in Java. The difference is that the reference to the parent class has to be explicitly declared as in the following example:

class OuterClass {
 string s;
 // ...
 class InnerClass {
  OuterClass o_;
  public InnerClass(OuterClass o) { o_ = o; }
  public string GetOuterString() { return o_.s; }
 }
 void SomeFunction() {
  InnerClass i = new InnerClass(this);
  i.GetOuterString();
 }
}

The only difference between this and a Java inner class is that in Java, the reference to the enclosing class, o_,  is both created and applied implicitly. C# commentator Raymond Chen (who provides the above example in his blog on msdn.com) refers to the implicit reference as “syntactic sugar”. It serves a purpose, but the C# design team felt that, since the same effect could be achieved with the explicit declaration, there was no need to make a special scoping rule via an implicit (and unseen) reference.

As for the ability of the enclosing class to access the members of the inner class directly, that is also available in C# by simply making all the members public. This does not violate the nested scoping rules since, as with Java, no aspect of a nested class can be accessed outside of the enclosing class.

15.5) The following Scheme function returns the number of zeroes in a simple list.

(define (zeroes aList)
(cond
((null? aList) 0)
(else (+ (if (= 0 (car aList)) 1 0) (zeros (cdr aList))))
))

The first condition handles an empty list and terminates the recursion. The second condition modifies the count based on the first item of the list and then adds the number of zeroes in the remainder of the list. The function is technically not tail recursive, but most interpreters would be able to optimize this into a loop since it is only a simple arithmetic operation and not a bona fide function call being applied to the recursive result.

15.11) To write a Scheme function that returns the reverse of a simple list, we could simply write a helper function that appends an element to end of a list and then append the head of the list to the reverse of the tail. However, such a function would be very inefficient for a large list since it would involve 2 levels of deep recursion. Instead, we write a helper that builds the reversed list on the way down the recursion by moving the head of the source list to the head of the target list and then returns the completed list from the deepest point.

(define (rev2 source target)
(cond
((null? source) target)
(else (rev2 (cdr source) (cons (car source) target)))
))

This function is tail-recursive, so it should be optimized into a loop. The primary function is then a simple call to the helper, initializing the target list to an empty list.

(define (reverse aList)(rev2 aList '()))

16.7) List representation is similar between Prolog and functional languages such as Scheme and Lisp. However, the processing of lists is fundamentally different. While functional languages specify operations on lists, such as head (CAR) and tail (CDR), Prolog specifies patterns which the list needs to match in order for the predicate to continue towards a goal. This could include matching the entire list, some of its contents, or just the head or tail. The actual breaking and combining of the list is then done by the inference engine as needed to match patterns, rather than specified directly by the programmer.

16.2Prog) Given the Prolog predicates

parent(P, X).     %indicates P is a parent of X
female(X).        %indicates X is female

The following rule determines if X is a sister of Y:

sister(X, Y) :- parent(P, X), parent(P, Y), female(X), (X \== Y).

While the above clause demonstrates the logic, is very efficient, and returns properly when both parameters are bound, it returns duplicates when one or both are unbound and the parent relationship is given for both parents of X and Y. To get around this, the built-in setof/3 predicate can be used to first generate a list of parents common to both and continue only if the list is non-empty:

sisterNoDups(X, Y) :- setof(P, (parent(P, X), parent(P, Y)), _),
female(X), (X \== Y).

As setof/3 fails when the empty set is returned in the third position, this will have the same logical effect as the first two clauses of sister/2, but will not return duplicate rows since the set of parents is being requested once from a single clause, so there will be no backtracking on the first clause and the dups are eliminated.

16.3Prog) The following Prolog rules bind the maximum value in a list to the first parameter. The function fails (returns “no”) on an empty list. The first predicate is the terminating condition. The following two bind either the head or the max of the tail to the result, depending on which is greater.

listmax(Max, [Max]).
listmax(H, [H|T]) :- listmax(TailMax, T), TailMax < H.
listmax(TailMax, [H|T]) :- listmax(TailMax, T), TailMax >= H.


No comments:

Post a Comment