11/11/2020 Worksheet Argument Passing Worksheet Argument Passing Table of Contents 1. Questions and Completion 2. Finding Current Information 3. L-Value or Not? 4. Argument Passing 4.1. CBV in C - Int 4.2. CBV in C - Pointer 4.3. CBV in Java - Int 4.4. CBV in Java - Reference 4.5. Scala - Reference 4.6. C - Struct 5. Returning Two Items 5.1. Java - Immutable Pair Class 5.2. Java - Mutable Pair Class 5.3. C - Immutable Struct 5.4. C - Mutable Pair Struct 6. Scope and Recursive Values 7. Solutions 7.1. Solution: L-Value or Not? 7.2. Solution: CBV in C 7.3. Solution: CBV in Java 7.4. Solution: Returning Two Items - Java - Immutable Pair Class 7.5. Solution: Returning Two Items - Java - Mutable Pair Class 7.6. Solution: Returning Two Items - C - Immutable Pair Struct 7.7. Solution: Returning Two Items - C - Mutable Pair Struct 7.8. Solution: Scope and Recursive Values 1 Questions and Completion To receive credit for completing the worksheet, you must complete the corresponding quiz (it is just a checkbox) on D2L when you have finished the worksheet. If you have questions as you go through this worksheet, please feel free to post them on the discussion forum. 2 Finding Current Information The Concepts textbook is helpful in providing some information for topics this week. However, implementation details differ significantly between PLs, so it is necessary to supplement textbook reading with experiments and more current information online (often blog posts of experiments by other people). Unfortunately, book length treatments of implementation details are becoming rarer as their shelf-life decreases. 3 L-Value or Not? In each of the following contexts, determine whether the given expression is an l-value or not. Your code should replace the ellipsis (...). 1. Is x++ an l-value in C? The context is: void f (int x) { } ... 2. Is arr[x++] an l-value in C? The context is: void f (int x) { int arr[] = { 5, 6, 7, 8, 9, 10, 11 }; } ... 3. Is f ().x an l-value in C? The context is: struct S { int x; int y; https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 1/11 11/11/2020 Worksheet Argument Passing }; struct S f () { struct S s; s.x = 5; s.y = 6; } return s; // returns a copy of the "struct S", i.e., copies the two int members back void g () { } ... 4. Is t.x an l-value in C? The context is: struct S { int x; int y; }; struct S f () { struct S s; s.x = 5; s.y = 6; } return s; // returns a copy of the "struct S", i.e., copies the two int members back void g () { struct S t = f (); } ... 5. Is f ()->x an l-value in C? Recall that this means (*(f())).x, i.e., call f, dereference the pointer, then access the x member of the struct. The context is: #include <stdlib.h> struct S { int x; int y; }; struct S *f () { struct S *p = (struct S *) malloc (sizeof (struct S)); p->x = 5; // recall that p->x is just shorthand for (*p).x p->y = 6; } return p; // returns a copy of the pointer, i.e., copies just a pointer back void g () { } ... 6. Is arr[x++] an l-value in Java? The context is: class LValue6 { static void f (int x) { int[] arr = { 5, 6, 7, 8, 9, 10, 11 }; } } ... 7. Is list.get (x++) an l-value in Java? The context is: import java.util.ArrayList; class LValue7 { static void f (int x) { ArrayList<Integer> list = new ArrayList<> (); list.add (5); https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 2/11 11/11/2020 Worksheet Argument Passing } } list.add (6); list.add (7); list.add (8); ... 8. Is list.get (x++).x an l-value in Java? The context is: import java.util.ArrayList; class C { int x; int y; C (int x, int y) { this.x = x; this.y = y; } } class LValue8 { static void f (int x) { ArrayList<C> list = new ArrayList<> (); list.add (new C (5, 5)); list.add (new C (6, 6)); list.add (new C (7, 7)); list.add (new C (8, 8)); } } ... Solution: L-Value or Not? 4 Argument Passing 4.1 CBV in C - Int Confirm that C uses call-by-value to pass int variables by writing a simple C program then running it. 4.2 CBV in C - Pointer Confirm that C uses call-by-value to pass pointer variables by writing a simple C program then running it. Solution: CBV in C? 4.3 CBV in Java - Int Confirm that Java uses call-by-value to pass int variables by writing a simple Java program then running it. 4.4 CBV in Java - Reference Confirm that Java uses call-by-value to pass reference variables (meaning references to instances on the heap) by writing a simple Java program then running it. Solution: CBV in Java? 4.5 Scala - Reference When the following Scala program is executed it prints C(10). Can we conclude that Scala uses call-by-reference? case class C (var x:Int) object Test { def f (o:C) = { o.x = 10 } def main (args:Array[String]) = { val c = C (5) https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 3/11 11/11/2020 } } Worksheet Argument Passing f (c) println (c) 4.6 C - Struct Examine the following C program. A struct S contains two int members (like fields) and an array of int (length is ARR_SIZE or 16). #include <stdio.h> #include <stdlib.h> #define ARR_SIZE 16 struct S { int x; int y; int arr[ARR_SIZE]; }; void print_S (struct S *p) { printf ("S {\n x = %d,\n y = %d,\n for (int i = 0; i < ARR_SIZE; i++) { printf ("%02X, ", p->arr[i]); } printf ("],\n}\n"); } arr = [ ", p->x, p->y); void f (struct S s) { printf ("s in f #1\n"); print_S (&s); s.x = s.x + 1; /* increment s.x (first way to write it) */ s.y += 1; /* increment s.y (second way to write it) */ for (int i = 0; i < ARR_SIZE; i++) { s.arr[i]++; /* increment s.arr[i] (third way to write it) */ } } printf ("s in f #2\n"); print_S (&s); int main (void) { struct S t; t.x = 5; t.y = 6; } for (int i = 0; i < ARR_SIZE; i++) { t.arr[i] = i; } //printf ("sizeof(struct S)=%lu\n", sizeof(struct S)); printf ("t in main #1\n"); print_S (&t); f (t); printf ("t in main #2\n"); print_S (&t); 1. How big is a struct S? (You can check your answer afterwards by adding a line to print sizeof(struct S).) 2. In contrast how big is each field in an instance of this Java class? class S { int x; int y; int[] arr; } 3. The main function allocates a variable t of type struct S in its activation on the call-stack. We often say that t is stack-allocated. The function f is called with t as an argument. The function f prints the contents of its argument, updates its argument, then prints the contents again. Finally main prints the contents of t again. Try to work out will be printed, given the statement "C copies structures when passed as arguments". Confirm your answer by compiling and running the C program. 4. Rewrite the C program so that f receives a pointer to a struct S, and does its updates via that pointer. Try to work out how that will affect the output. Recompile and run your program to confirm your answer. https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 4/11 11/11/2020 Worksheet Argument Passing 5 Returning Two Items It is often necessary to return two or more items from a function or method. In Scala, tuple types can be used to return two items. For example, fibaux below performs an efficient calculation of the n and n+1 elements of the Fibonacci sequence. By returning a pair of two consecutive numbers from the Fibonacci sequence it avoids the unnecessary recomputation in the naive definition of the Fibonacci function. def fibaux (n:BigInt) : (BigInt, BigInt) = { if (n <= 0) { (0, 1) } else if (n == 1) { (1, 1) } else { val (a, b) = fibaux (n - 1) (b, a + b) } } def fib (n:BigInt) : BigInt = fibaux (n)._1 For example: scala> (0 to 70).toList.map (n => BigInt (n)).map (fib) res0: List[BigInt] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 2 Now consider how to return two or more items in other programming languages. 5.1 Java - Immutable Pair Class The following Java program defines an immutable Pair class (with type parameters X and Y). Complete the definition of fibaux in the following Java program, which uses the immutable Pair class. You may need to refer to the Java documentation for use of Java's BigInteger class. import java.math.BigInteger; class Pair<X,Y> { final X x; final Y y; Pair (X x, Y y) { this.x = x; this.y = y; } } public class Fib1 { static Pair<BigInteger,BigInteger> fibaux (BigInteger n) { } ... static BigInteger fib (BigInteger n) { return fibaux (n).x; } } public static void main (String[] args) { for (int i = 0; i < 71; i++) { System.out.println (fib (BigInteger.valueOf (i))); } } Solution: Returning Two Items - Java - Immutable Pair Class 5.2 Java - Mutable Pair Class If the final modifier is removed from the fields of Pair, the caller to fibaux can pass in (a reference to) a Pair instance, and the fields of that instance can be updated with the results. Complete the definition of fibaux in the following Java program. https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 5/11 11/11/2020 Worksheet Argument Passing import java.math.BigInteger; class Pair<X,Y> { X x; Y y; Pair (X x, Y y) { this.x = x; this.y = y; } } public class Fib2 { static void fibaux (BigInteger n, Pair<BigInteger,BigInteger> result) { } ... static BigInteger fib (BigInteger n) { Pair<BigInteger, BigInteger> p = new Pair<> (BigInteger.ZERO, BigInteger.ZERO); fibaux (n, p); return p.x; } } public static void main (String[] args) { for (int i = 0; i < 71; i++) { System.out.println (fib (BigInteger.valueOf (i))); } } Solution: Returning Two Items - Java - Mutable Pair Class 5.3 C - Immutable Struct The following C program defines an immutable pair struct. We use long for simplicity instead of an arbitrary precision data type for integers. Complete the definition of fibaux in the following C program, which uses the immutable pair struct. #include <stdio.h> #include <stdlib.h> struct pair { const long x; const long y; }; struct pair fibaux (long n) { } ... long fib (long n) { return fibaux (n).x; } int main (void) { for (int i = 0; i < 71; i++) { printf ("%ld\n", fib (i)); } } Solution: Returning Two Items - C - Immutable Pair Struct 5.4 C - Mutable Pair Struct Explain why we cannot remove the const modifier from the members of struct pair and then rewrite fibaux with the following signature (contrast with the Java mutable Pair class above). struct pair { long x; long y; }; https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 6/11 11/11/2020 Worksheet Argument Passing void fibaux (long n, struct pair result) { } ... Explain how to change the signature of fibaux so that an argument for the result can be passed to fibaux. Solution: Returning Two Items - C - Mutable Pair Struct 6 Scope and Recursive Values 1. Write a Scala expression alternates of type Stream[Boolean] that alternates between true and false (starting with true). 2. Try the following expressions in the Scala REPL (after your definition of alternates). "the rain in spain".toList "the rain in spain".toList.zip (alternates) "the rain in Spain".toList.zip (alternates).filter ((p:(Char,Boolean)) => p match { case (c:Char,b:Boolean) => b }) /* shorthand for the previous version */ "the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => b } "the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => b } val evens = "the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => b }.map (p => p._1) val odds = "the rain in Spain".toList.zip (alternates).filter { case (c:Char,b:Boolean) => !b }.map (p => p._1) evens.zip (odds) 7 Solutions 7.1 Solution: L-Value or Not? 1. No, temporary value from ++ 2. Yes, array 3. No, temporary value from f() 4. Yes, struct 5. Yes, pointer is temporary, but field is not 6. Yes, array 7. No, temporary Integer 8. Yes, all object access via pointers/references in Java 7.2 Solution: CBV in C #include <stdio.h> void swapInt(int x, int y) { int oldX = x; int oldY = y; x = oldY; y = oldX; } void swapPointer(int *x, int *y) { int* oldX = x; int* oldY = y; x = oldY; y = oldX; } int main() { { int a = 0; int b = 1; printf ("a = %d, b = %d\n", a, b); swapInt (a, b); printf ("a = %d, b = %d\n", a, b); } { int a = 0; int *p = &a; int b = 1; int *q = &b; printf ("*p = %d, *q = %d\n", *p, *q); https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 7/11 11/11/2020 } } Worksheet Argument Passing swapPointer (p, q); printf ("*p = %d, *q = %d\n", *p, *q); 7.3 Solution: CBV in Java class CBV { private static void swapInt(int x, int y) { int oldX = x; int oldY = y; x = oldY; y = oldX; } private static void swapRef(Integer x, Integer y) { Integer oldX = x; Integer oldY = y; x = oldY; y = oldX; } } public static void main(String args[]) { { int a = 0; int b = 1; System.out.format ("a = %d, b = %d\n", swapInt (a, b); System.out.format ("a = %d, b = %d\n", } { Integer a = 0; Integer b = 1; System.out.format ("a = %d, b = %d\n", swapRef (a, b); System.out.format ("a = %d, b = %d\n", } } a, b); a, b); a, b); a, b); 7.4 Solution: Returning Two Items - Java - Immutable Pair Class import java.math.BigInteger; class Pair<X,Y> { final X x; final Y y; Pair (X x, Y y) { this.x = x; this.y = y; } } public class Fib1 { static Pair<BigInteger,BigInteger> fibaux (BigInteger n) { if (n.compareTo (BigInteger.ZERO) <= 0) { return new Pair<> (BigInteger.ZERO, BigInteger.ONE); } else if (n.equals (BigInteger.ONE)) { return new Pair<> (BigInteger.ONE, BigInteger.ONE); } else { Pair<BigInteger, BigInteger> p = fibaux (n.subtract (BigInteger.ONE)); return new Pair<> (p.y, p.x.add (p.y)); } } static BigInteger fib (BigInteger n) { return fibaux (n).x; } public static void main (String[] args) { for (int i = 0; i < 71; i++) { System.out.println (fib (BigInteger.valueOf (i))); https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 8/11 11/11/2020 } } Worksheet Argument Passing } $ javac Fib1.java $ java Fib1 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733 1134903170 1836311903 2971215073 4807526976 7778742049 12586269025 20365011074 32951280099 53316291173 86267571272 139583862445 225851433717 365435296162 591286729879 956722026041 1548008755920 2504730781961 4052739537881 6557470319842 10610209857723 17167680177565 27777890035288 44945570212853 72723460248141 117669030460994 190392490709135 7.5 Solution: Returning Two Items - Java - Mutable Pair Class https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 9/11 11/11/2020 Worksheet Argument Passing import java.math.BigInteger; class Pair<X,Y> { X x; Y y; Pair (X x, Y y) { this.x = x; this.y = y; } } public class Fib2 { static void fibaux (BigInteger n, Pair<BigInteger,BigInteger> result) { if (n.compareTo (BigInteger.ZERO) <= 0) { result.x = BigInteger.ZERO; result.y = BigInteger.ONE; } else if (n.equals (BigInteger.ONE)) { result.x = BigInteger.ONE; result.y = BigInteger.ONE; } else { fibaux (n.subtract (BigInteger.ONE), result); BigInteger x = result.x; BigInteger y = result.y; } } result.x = y; result.y = x.add (y); static BigInteger fib (BigInteger n) { Pair<BigInteger, BigInteger> p = new Pair<> (BigInteger.ZERO, BigInteger.ZERO); fibaux (n, p); return p.x; } } public static void main (String[] args) { for (int i = 0; i < 71; i++) { System.out.println (fib (BigInteger.valueOf (i))); } } 7.6 Solution: Returning Two Items - C - Immutable Pair Struct #include <stdio.h> #include <stdlib.h> struct pair { const long x; const long y; }; struct pair fibaux (long n) { if (n <= 0) { return (struct pair) { 0, 1 }; } else if (n == 1) { return (struct pair) { 1, 1 }; } else { struct pair p = fibaux (n - 1); return (struct pair) { p.y, p.x + p.y }; } } long fib (long n) { return fibaux (n).x; } int main (void) { for (int i = 0; i < 71; i++) { printf ("%ld\n", fib (i)); } } https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 10/11 11/11/2020 Worksheet Argument Passing 7.7 Solution: Returning Two Items - C - Mutable Pair Struct It would not work because fibaux would receive a copy of the struct pair from the caller, so modifications to result would not be seen by the caller. To modify the program, we pass a pointer to a struct pair instead, and fibaux fills in its value. #include <stdio.h> #include <stdlib.h> struct pair { long x; long y; }; void fibaux (long n, struct pair *presult) { if (n <= 0) { presult->x = 0; presult->y = 1; } else if (n == 1) { presult->x = 1; presult->y = 1; } else { fibaux (n - 1, presult); long x = presult->x; long y = presult->y; } } presult->x = y; presult->y = x + y; long fib (long n) { struct pair result; // not initialized here, will be initialized by fibaux fibaux (n, &result); return result.x; } int main (void) { for (int i = 0; i < 71; i++) { printf ("%ld\n", fib (i)); } } 7.8 Solution: Scope and Recursive Values val alternates:Stream[Boolean] = true #:: false #:: alternates Author: James Riely Created: 2020-10-27 Tue 17:12 Emacs 25.3.50.1 (Org mode 8.2.10) Validate https://fpl.cs.depaul.edu/jriely/courses/csc447/worksheets/ws-argument-passing.html 11/11