Programming Languages: Final Exam Review

Ace your homework & exams now with Quizwiz!

What is the accessibility rules for C++ inheritance classes for example, class circle:protect shape { ....... }

C++ allows members of a class to be designated as Public, Private, or Protected. Public members are visible anywhere the class declaration is in scope. Private members are only visible inside the class's method. Protected members are visible inside methods of the class or its descendants. ------------------------------------------ Visibility rules - Public and Private parts of an object declaration/definition - 2 reasons to put things in the declaration • so programmers can get at them • so the compiler can understand them - At the very least the compiler needs to know the size of an object, even though the programmer isn't allowed to get at many or most of the fields (members) that contribute to that size • That's why private fields have to be in declaration • C++ distinguishes among - public class members • accessible to anybody - protected class members • accessible to members of this or derived classes - private • accessible just to members of this class • A C++ structure (struct) is simply a class whose members are public by default • C++ base classes can also be public, private, or protected ------------------------------------------ • Example: class circle : public shape { ... anybody can convert (assign) a circle* into a shape* class circle : protected shape { ... only members and friends of circle or its derived classes can convert (assign) a circle* into a shape* class circle : private shape { ... only members and friends of circle can convert (assign) a circle* into a shape*

Discrete types and scalar types (Examples)

Discrete Data Type - represents items that can be counted. They can be classified as integers, Booleans, characters, enumerations, or subranges. Must have a clear successor and predecessor. Scalar Type - It is a simple single numeric value (i.e. 1, 2/3, 3.14, etc.) usually an integer, fixed point, or float, as opposed to an array, structure, object, or complex vector which contain more than one single numeric value.

Strings.

In many languages, a string is simply an array of characters. In other languages, strings have special status, with operations that are not available for arrays of other sorts. They are often special-cased, to give them flexibility (like polymorphism or dynamic sizing) that is not available for arrays in general. It's easier to provide these things for strings than for arrays in general because strings are one-dimensional and (more important) noncircular. Pascal and C/C++ implement strings in different ways. Pascal uses length+array. C/C++ uses null-terminator to indicate the end of a string.

Prologue and epilogue of function/procedure calling.

Maintenance of stack is responsibility of calling sequence and subroutine prologue and epilogue. space is saved by putting as much in the prologue and epilog as possible. Tasks that must be accomplished on the way into a subroutine include passing parameters, saving the return address, changing that stack pointer to allocate space, saving registers that contain important values and that may be overwritten by the callee, changing the frame pointer to refer to the new frame, and executing initialization code for any objects on the new frame that require it. Time may be saved by putting stuff in the caller instead, where more information may be known. • e.g., there may be fewer registers IN USE at the point of call than are used SOMEWHERE in the callee • Common strategy is to divide registers into caller-saves and callee-saves sets -caller uses the "callee-saves" registers first -"caller-saves" registers if necessary •Common strategy is to divide registers into caller-saves and callee-saves sets -caller uses the "callee-saves" registers first -"caller-saves" registers if necessary •Local variables and arguments are assigned fixed OFFSETS from the stack pointer or frame pointer at compile time -some storage layouts use a separate arguments pointer • Caller -saves into the temporaries and locals area any caller-saves registers whose values will be needed after the call -puts up to 4 small arguments into registers $4-$7 (a0-a3) •it depends on the types of the parameters and the order in which they appear in the argument list -puts the rest of the arguments into the arg build area at the top of the stack frame -does jal, which puts return address into register ra and branches •note that jal, like all branches, has a delay slot After call, Caller -moves return value from register to wherever it's needed (if appropriate) -restores caller-saves registers lazily over time, as their values are needed •All arguments have space in the stack, whether passed in registers or not •The subroutine just begins with some of the arguments already cached in registers, and 'stale' values in memory

Name equivalence and structure equivalence.

Name Equivalence - based on declarations. Two types are the same is they have the same name. Each type declared introduces a new type distinct from all others. Used in Java and Ada. Structural Equivalence - Based on some notion of meaning behind those declarations. Two types are equivalent if they have the same structure. Used in Algol-68, Modula-3, and ML. Depends on simple comparison of type descriptions substitute out all names - expand all the way to built-in types

Reference variables and value variables.

Reference Variable - It provides an alias (alternative name) for a previously defined variable. References cannot be null because every reference refers to some object. Ex: int foo; int& bar = foo; bar is now a reference which means that bar holds the location of memory where foo lies. Value Variable - d = a; a = b + c; In the first statement, the right hand side of the statement refers to the value of a, which we wish to place into d. In the second statement, the left hand side refers to the location of a, where we want to put the sum of b and c. •Variables as values vs. variables as references -value-oriented languages •C, Pascal, Ada -reference-oriented languages •most functional languages (Lisp, Scheme, ML) •Clu, Smalltalk -Algol-68 kinda halfway in-between -Java deliberately in-between •built-in types are values •user-defined types are objects - references

Row and column major order. Why you need to know it?

Row-Major Order - In RMO, consecutive locations in memory hold elements that differ by one in the final subscript. A[2, 4], for example, is followed by A[2, 5]. It makes it easier to define a multidimensional array as an array of subarrays. • Row pointers - an option in C - allows rows to be put anywhere - nice for big arrays on machines with segmentation problems - avoids multiplication - nice for matrices whose rows are of different lengths • e.g. an array of strings - requires extra space for the pointers ----------------------------------------- Column-Major Order - In CMO, consecutive locations hold elements that differ by one in the initial subscript: A[2, 4] is followed by A[3, 4]. The elements of a subarray in CMO would not be contiguous in memory.

Strong typing and weak typing. Static typing and dynamic typing. (Examples. Why).

Strong Typing - a language is said to be strongly typed if it prohibits, in a way that the language implementation can enforce, the application of any operation to any object that is not intended to support that operation to any object that is not intended to support that operation. (e.g., Java, C++,) Ruby is strongly typed because once it knows the type of an object, it expects you to do something that makes sense with it. Ex: x = "3" y = x + "ho!" #=> "3ho!" but x = "3" y = x + 3 will produce an error. ------------------------------------------Weak Typing - a language that is being lenient about what you can do with your typed variables. Javascript, however, is dynamically but weakly typed because it lets you mix types together in your expressions without throwing an exception. The danger? If you're not careful you will get weird results. ---------------------------------------- Statically Typing - a language is said to be statically typed if it is strongly typed and type checking can be performed at compile time.language has a type system that is checked at compile time by the implementation (a compiler or interpreter) and it is strongly typed. (e.g. Ada, Pascal, Lisp) ------------------------------------------ Dynamic Typing - Dynamic type checking is a form of late binding, and tends to be found in languages that delay other issues until run time as well. (e.g., Python, Ruby, Lisp) Some languages have both static and dynamic type checking. - Pascal, Java etc are mostly static typing. - Python, PHP, and most script languages are dynamic typing. - C++ are combined (support dynamic casting)

Type conversion and coercion.

Type Conversion (Explicit) - Converting one type of data to another type. It is also known as type casting. It can be used to pass a value to a function where the parameter is of a different data type or to return a value from a function where the function return type is of a different data type. Implicit - performed whenever one fundamental data type is expected but a different fundamental data type is supplied and the user does not explicitly tell the compiler how to perform this conversion. ----------------------------------------- Type Coercion (Implicit) - it is the conversion of one type of object to a new object of a different type with similar content. A common example is the coercion of string "5" into an integer 5 or a double 5.0. Coerces an expression to be of the proper type - Coercion can be based just on types of operands, or can take into account expected type from surrounding context as well - Fortran has lots of coercion, all based on operand type • C has lots of coercion, too, but with simpler rules: - all floats in expressions become doubles - short intand charbecome intin expressions - if necessary, precision is removed when assigning into LHS

Type equivalence and compatibility.

Type Equivalence - Type Compatibility - A compatible type is one that is either legal for the operator, or is allowed under language rules to be implicitly converted, by compiler-generated code, to a legal type. Compatibility is the more useful concept, because it tells you what you can DO. Name Compatibility - two variables can have compatible types only if they are in either the same declaration or in declaration that use the same name. It is highly restrictive and easier to implement. Used in Ada. Structural Compatibility - two variables have compatible types if their types have identical structures. Two types are structuarally compatible if (1)T1 is name with T2 or (2)T1 and T2 are defined by applying the same type constructor to structurally compatible corresponding type components. It is more flexible, difficult to implement (must compare entire structure, not just names). Used in C.

What is the different between virtual and non-virtual methods in C++.

Virtual method can be used to specify which particular methods should use dynamic binding by labeling as virtual. Calls to virtual methods are dispatched to the appropriate implementation at run time, based on the class of the object, rather than the type of reference. In C++, the keyword virual prefixes the subroutine declaration. class person{ public: virtual void print_mailing_label(); . . ------------------------------------------ • Virtual functions in C++ are an example of dynamic method binding - you don't know at compile time what type the object referred to by a variable will be at run time • If a virtual function has a "0" body in the parent class, then the function is said to be a pure virtual function and the parent class is said to be abstract • You can't declare objects of an abstract class; you have to declare them to be of derived classes • Moreover any derived class must provide a body for the pure virtual function(s) • Non-virtual functions require no space at run time; the compiler just calls the appropriate version, based on type of variable - Member functions are passed an extra, hidden, initial parameter: this

Prolog: a. Write a Prolog program to solve the following problems: i. john is taller than josh ii. josh is taller than kim iii. josh is taller than sam iv. sam is taller than Edward v. Find all people that is taller than sam. b. Write a Prolog program to do simple arithmatics (see slides) c. Write a Prolog program to calculate Fibonacci series.

a. relations.pl: taller (john, josh). taller (josh, kim). taller (josh, sam). taller (sam, edward). b. start:- sum,nl. sum:- write('X= '),read(X), write('Y= '),read(Y), S is X+Y, write('Sum is '),write(S). c. fib(0, 0). fib(1, 1). fib(X, Y) :- X > 1, X2 is X - 2, fib(X2, Y2), X1 is X - 1, fib(X1, Y1), Y is Y1 + Y2.

Type casting in C++.

• C++ has 4 types of casting: - static_cast: • Almost equivalent to type conversion in C. No type checking. - dynamic_cast: • Can cast pointers or objects with type checking. • If type checking fails, return null pointers or throw exceptions. - reinterpret_cast: • Can convert any pointers or objects to any other types pointers or objects. Very dangerous. - const_cast: • Set or remove constness of a variable.

Does C++ support multiple inheritance? How about Java? What are potential problems for multiple inheritance?

• In C++, you can say class professor : public teacher, public researcher { ... } Here you get all the members of teacher and all the members of researcher - If there's anything that's in both (same name and argument types), then calls to the member are ambiguous; the compiler disallows them Java provides a limited, "mix-in" form of multiple inheritance, in which only one parent class is permitted to have fields. basically you inherit from one real parent and one or more interfaces, each of which contains only virtual functions and no data • this avoids the contiguity issues in multiple inheritance above, allowing a very simple implementation When inheriting from multiple base classes that implement the same function or field it's the compiler has to make a decision about what implementation to inherit. This get's worse when you inherit from multiple classes that inherit from the same base class.

Alignment of struct/record data types.

• ORTHOGONALITY is a useful goal in the design of a language, particularly its type system. It means that features can be used in any given combination, the combinations all make sense, and the meaning of a given feature is consistent, regardless of the other features with which it is combined. - A collection of features is orthogonal if there are no restrictions on the ways in which the features can be combined (analogy to vectors) - Pascal is more orthogonal than Fortran, (because it allows arrays of anything, for instance), but it does not permit variant records as arbitrary fields of other records (for instance) • Orthogonality is nice primarily because it makes a language easy to understand, easy to use, and easy to reason about

Scheme Language

•One of two dialects of LISP language (the other one is Common Lisp) •It is a functional programming language •It was developed at the MIT AI Lab by Guy Steele and Gerald Gussman. •The language is case insensitive •Its theoretical foundation is Lambda-calculus •It uses recursion heavily •It uses prefix convention •There is no iteration in Scheme. You have to use recursion to implement iteration ---------------------------------------- •"hello" →"hello" •42 → 42 •22/7 → 22/7 •3.141592653 → 3.141592653 •+ → #<procedure> •(+ 76 31) → 107 •'(a b c d) →(a b c d) •(a b c d) → undefined. (lambda (n) (* n n))) • car: return the first item in the list. • (car '(a b c)) → a • cdr: return the tail of a list. • (cdr '(a b c)) → (b c) • cons: return the concatenation of two lists. • (cons 'a '(b c)) → (a b c) • (cons (car '(a b c)) (cdr '(d e f))) → (a e f) • (cons '(a b) '(c d)) → ((a b) c d) •(define fact (lambda (n) (if (< n 1) 1 (* (fact (- n 1)) n))))

Value and reference parameter passing.

•Parameter passing mechanisms have three basic implementations -value -value/result (copying) -reference (aliasing) -closure/name •Many languages (e.g., Pascal) provide value and reference directly •C/C++: functions -parameters passed by value (C) -parameters passed by reference can be simulated with pointers (C) void proc(int* x,int y){*x = *x+y } ... proc(&a,b); -or directly passed by reference (C++) void proc(int& x, int y) {x = x + y } proc(a,b); Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value. public void badSwap(int var1, int var2){ int temp = var1; var1 = var2; var2 = temp; } When badSwap() returns, the variables passed as arguments will still hold their original values. The method will also fail if we change the arguments type from int to Object, since Java passes object references by value as well.

Writing Scheme Programs to do the following tasks: (1) Calculate 3+4*(5-6) (2) Define a function that calculates 4x^2+3x-6. Use the function to calcualte f(2), f(1/2), f(0.5). (3) Write code to get the third element of a list. You code must be able to apply to the list '(a b c d e) and return c. (4) Write code to get the list that removes the first two items of the input argument. In other words, you code must be applied to '(a b c d) and return (c d). (5) Write code to define fibonacci function: f(0) = 0, f(1)=1, f(2)=f(1)+f(0), f(3)=f(2)+f(1) ..... (6) Write a function that accept low and high as input and print from low to high (include both low and high). For example, if low is 4, high is 7, your program should print 4, 5, 6, 7.

(1) (+ 3(*4 (- 5 6))) (2) (define (solve-equation x) (define a (^ 4x + 2 - 3x 6) (display a)) (3) (define (third list) (map (map cadr list)) (4) (define delete (lambda (item list) (cond ((equal? Item (car list) (cdr list)) (else (cons (car list) (delete item (cdr list))))))) (5) (define fibonacci n) (if (< n 2) n (+ fibonacci (- n 1)) (fibonacci (- n 2))))) (6) (define func (low, high) (cond (< low high) (display "low < high") (newline) (do ((nums (list low)) (i 0 (+ i 1))) ((= i low) num) (numlist ! num i i)) (display numlist) (newline) (else (display "high > low")))

Understand vtable and dynamic method binding.

- They are implemented by creating a dispatch table (vtable) for the class and putting a pointer to that table in the data of the object - Objects of a derived class have a different dispatch table • In the dispatch table, functions defined in the parent come first, though some of the pointers point to overridden versions • You could put the whole dispatch table in the object itself - That would save a little time, but potentially waste a lot of space Of course you only have a vtable in C++ if your class has virtual functions • That's why you can't do a dynamic_cast on a pointer whose static type doesn't have virtual function

Lambda Calculus Perform alpha and beta reduction for lambda calculus. a. S2 = 3. b. 2+3 = 5 c. 2*2 = 4

- λ-calculus is a formal system in Mathematical Logic -Natural numbers (0, 1, 2, ....) are defined as functions in λ−calculus. • I is defined as: λx.x , the identity function. Note that Ix ≡ x for any x. • 0 is defined as: λsz.z ≡ λs.(λz.z) ≡ λs.I • 1 ≡ λsz.s(z) • 2 ≡ λsz.s(s(z)) • 3 ≡ λsz.s(s(s(z))) • Successor functions: S ≡ λwyx.y(wyx) Exercise: Prove: 0 ≡ 1. prove: S(n) ≡ n + 1 (λwyx.y(wyx)) ≡λyx.y(λsz.z)yx) ≡λyx.y(x) ≡λyx.y(x) = λsz.s(z) • Addition: λxyzw.xz(yzw) • Verify that (λxyzw.xz(yzw) 2 3 ≡ 5 ≡λzw.2z(3zw) ≡λzw.2z(λsz.s(s(s(z))).zw) ≡λzw.2z(z(z(z(w))) ≡λzw.(λsz.s(s(z))) \ z(z(z(z(w)))) ≡λzw.(z(z(z(z(z(w))))) ≡λsz.(s(s(s(s(s(w))))) • Multiplication: λxyz.z(yz) ------------------------------------------ a. ≡ (λwyx.y(wyx))(λsz.s(sz)) ≡ (λyx.y((λsz.s(s(z))) ≡ (λyx.y(y(y(x))) ≡ 3 b. ≡ (λwyx.y(wyx))(λsz.s(sz)) ≡ (λyx.y((λsz.s(s(z))) ≡ (λyx.y(y(y(x))) ≡ 3 c. ≡ (λxyz.x(yz))2 2 ≡ (λz.2(2z)) ≡ 4

Polymorphism. (Definition. Examples)

Allows a single body of code to work with objects of multiple types. It may or may not need run-time type checking. For example, integers and floats are implicitly polymorphic since you can add, subtract, multiply and so on, irrespective of the fact that the types are different. They're rarely considered as objects in the usual term.

Associative Array. (Definitions. Implementations. Challenges. Associative arrays in languages).

An abstract data type composed of a collection of (key, value) pairs, such that each possible key appears with this data type. It is a non discrete index type. Must be implemented with hash tables or search trees. They resemble the dictionary or map types supported by the standard libraries of many object oriented languages. In C++, they are typically defined by overloading operator[]. C#, like C++, provides extensive facilities for operator overloading but it does not use these facilities to support associative arrays. Instead, the language provides a special indexer mechanism, with its own unique syntax. Most script languages, such as Python, PHP, Javascript support associative array. ------------------------------------------------------------- They are arrays that can use non-integer type values as indices: • example: age["John"]


Related study sets

intro to public speaking mid term

View Set

An Update on Demineralization/Remineralization CE

View Set

Chapter 19: Documenting and Reporting

View Set

Families and Children (Chapter 9)

View Set