Instructor: James Riely
int loop (int n, int result) {
if (n <= 1) {
return result;
} else {
return loop (n - 1, n * result);
}
}
int fact (int n) {
return loop (n, 1);
}
int fact (int n) {
int loop (int n, int result) {
if (n <= 1) {
return result;
} else {
return loop (n - 1, n * result);
}
}
return loop (n, 1);
}
$ gcc -c nested-fact.c
$ gcc -pedantic -c nested-fact.c
function.c: In function ‘fact’:
function.c:2:3: warning: ISO C forbids nested functions [-pedantic]
int fact (int n) {
int loop (int i, int result) {
if (i > n) {
return result;
} else {
return loop (i+1, i * result);
}
}
return loop (1, 1);
}
def printElt [A,B] (f:A=>B) (x:A) : B =
println (x)
f (x)
def mapDebug [A,B] (xs:List[A], f:A=>B) : List[B] =
xs.map (printElt (f))
def mapDebug [A,B] (xs:List[A], f:A=>B) : List[B] =
def printElt (x:A) : B =
println (x)
f (x) // use f from enclosing context
xs.map (printElt)
def mapDebug [A,B] (xs:List[A], f:A=>B) : List[B] =
xs.map ((x:A) => { println (x); f (x) }) // anonymous function clearer
#include <stdio.h>
#include <stdlib.h>
typedef void (*funcptr) (int);
funcptr f (int x) {
void g (int y) {
printf ("x = %d, y = %d\n", x, y);
}
g (1);
return &g;
}
int main (void) {
funcptr h = f (10);
(*h) (2);
f (20);
(*h) (3);
}
$ gcc -std=c99 nested-gcc.c
$ ./a.out
x = 10, y = 1 <- safe to call g, with x=10
x = 10, y = 2 <- unsafe to call h, created with x=10, GOOD!
x = 20, y = 1 <- safe to call g
x = 20, y = 3 <- unsafe to call h, created with x=10, BAD!
#include <stdio.h>
#include <stdlib.h>
#include <Block.h>
// ^funcptr for blocks; *funcptr for function pointers
typedef void (^funcptr) (int);
funcptr f (int x) {
funcptr g;
g = ^(int y) {
printf ("x = %d, y = %d\n", x, y); // use x from enclosing defn
};
g = Block_copy (g);
g (1); // OK, f's activation record still allocated
return g;
}
int main (void) {
funcptr h = f (10);
h (2); // OK, because of Block_copy
f (20);
h (3); // OK, because of Block_copy
Block_release (h);
}
$ sudo apt-get install libblocksruntime-dev
$ clang -fblocks nested-clang.c -lBlocksRuntime
$ ./a.out
x = 10, y = 1
x = 10, y = 2
x = 20, y = 1
x = 10, y = 3 <- safe to call h, created with x=10, GOOD!
Block_copy
and Block_release
$ clang -fblocks nested-clang.c -lBlocksRuntime
$ ./a.out
x = 10, y = 1
x = -1035955720, y = 2 <- unsafe to call h, created with x=10, BAD!
x = 20, y = 1
x = -1035955720, y = 3 <- unsafe to call h, created with x=10, BAD!
func f (_ x:Int) -> (Int) -> () {
func g (_ y:Int) -> () { print ("x = " + String(x) + " y = " + String(y)) }
g (1)
return g
}
func main () {
let h = f (10)
h (2)
let _ = f (20)
h (3)
}
main()
$ swiftc nested-swift.swift
$ ./nested-swift
x = 10 y = 1
x = 10 y = 2
x = 20 y = 1
x = 10 y = 3
def f (x:Int) : Int=>Unit =
def g (y:Int) : Unit = println ("x = %d, y = %d".format (x, y))
g (1)
g
def main () =
val h = f (10)
h (2)
f (20)
h (3)
main()
x = 10, y = 1
x = 10, y = 2
x = 20, y = 1
x = 10, y = 3 <- safe to call h, created with x=10, GOOD!
import java.util.function.IntConsumer;
public class NestedFunc1 {
static IntConsumer f (int x) {
IntConsumer g = y -> System.out.format ("x = %d, y = %d%n", x, y);
g.accept (1);
return g;
}
public static void main (String[] args) {
IntConsumer h = f (10);
h.accept (2);
f (20);
h.accept (3);
}
}
$ javac NestedFunc1.java
$ java NestedFunc1
x = 10, y = 1
x = 10, y = 2
x = 20, y = 1
x = 10, y = 3 <- safe to call h, created with x=10, GOOD!