I have two interfaces which is responsible for holding a closure
Here is the first one for holding the closure when it comes to a map operation.
package com.fs;
/**
* This interface is responsible for holding the closures when it comes to map.
* It uses two generic types. One for the argument and one for the return type.
* @param <B> Generic type
* @param <A> Generic type
*/
public interface Func<B,A> {
/**
* Function prototype m takes an argument of type A and returns a type B.
* A map operation can produce a different type.
* @param x of type A
* @return type B
*/
B m(A x);
}
And the second one for filtering operations
package com.fs;
/**
* This interface is responsible for holding the closures when it comes to filter.
* @param <A> Generic type
*/
public interface Pred<A> {
/**
* Function prototype m takes an argument of type A and returns a boolean.
* A filter operation checks every element if it fits a predicate.
* @param x of type A
* @return boolean
*/
boolean m(A x);
}
I have a class named CList which is capable of working with closures.
package com.impl.list;
import com.fs.*;
public class CList<T> {
T head;
CList<T> tail;
public CList(T x, CList<T> xs){
head = x;
tail = xs;
}
static <A,B> CList<B> map(Func<B,A> f, CList<A> xs){
if(xs==null){
return null;
}
return new CList<>(f.m(xs.head),map(f,xs.tail));
}
static <A,B> CList<B> maploop(Func<B,A> f, CList<A> xs){
//?????
return null;
}
static <A> CList<A> filter(Pred<A> f, CList<A> xs){
if(xs == null){
return null;
}
if(f.m(xs.head)){
return new CList<>(xs.head, filter(f,xs.tail));
}
return filter(f,xs.tail);
}
static <A> int length(CList<A> xs){
int ans =0;
while(xs!= null){
++ans;
xs=xs.tail;
}
return ans;
}
}
Here is my public interface implementing CList with closures.
package com.impl.list;
import com.fs.Func;
import com.fs.Pred;
public class CListClient {
public static CList<Integer> doubleAll(CList<Integer> xs){
Func<Integer, Integer> df = new Func<Integer, Integer>() {
@Override
public Integer m(Integer x) {
return x * 2;
}
};
return CList.map(df, xs);
}
public static int countNs(CList<Integer> xs,final int n){
Pred<Integer> pf = new Pred<Integer>() {
@Override
public boolean m(Integer x) {
return x==n;
}
};
return CList.length(CList.filter(pf, xs));
}
public static CList<Integer> doubleAllloop(CList<Integer> xs){
Func<Integer, Integer> df = new Func<Integer, Integer>() {
@Override
public Integer m(Integer x) {
return x * 2;
}
};
return CList.maploop(df, xs);
}
}
And a simple tester:
package basic;
import com.impl.list.CList;
import com.impl.list.CListClient;
import org.junit.Test;
public class ListTester {
CList<Integer> intlist_1 = new CList<>(new Integer(1),null);
CList<Integer> intlist_2 = new CList<>(new Integer(2),intlist_1);
CList<Integer> intlist_3 = new CList<>(new Integer(3),intlist_2);
CList<Integer> intlist_4 = new CList<>(new Integer(4),intlist_3);
CList<Integer> intlist_5 = new CList<>(new Integer(4),intlist_4);
CList<Integer> intlist = new CList<>(new Integer(5),intlist_5);
@Test
public void test_doubleAll(){
CList<Integer> doubled = CListClient.doubleAll(intlist);
CList<Integer> doubledloop = CListClient.doubleAllloop(intlist);
}
@Test
public void test_CountNs(){
int count3s = CListClient.countNs(intlist, 3);
}
}
I am trying to convert the map function which is implemented in a recursive way to a while loop. I named it maploop. It hurts my brain for two days.Any hint will make me very happy.I am asking this question here since there is probability that someone may take Dan Grossman course and see the example and try to implement that function. I prefer a hint than an actual answer. Thanks.
Initialize the accumulator before the while-loop. Use the negation of the base-case condition as the loop's condition. Use the recursive function's body (except the recursive call) as the body of the while-loop. After the loop, apply the base-case update of the accumulator and return its value.
So, yes all-recursive code can be converted to iteration.
Which data structure is best suited for converting recursive implementation to iterative implementation of an algorithm? Explanation: Since function calls are executed in Last In First Out order, stack is the data structure for converting recursive to iterative implementation.
Any recursive algorithm can be rewritten to use loops instead. The opposite is also true. Any iterative algorithm can be written in terms of recursion only. expressiveness: some algorithms are just naturally simpler or easier to write with loops.
When converting a recursive function to an iterative function, you have to examine which non tail call state is required, if any. Then create a stack and push the states onto the stack, and code it like you would the recursive function otherwise. If you have multiple recursive calls in the function, you'll need your new state item to also contain a value indicating at which point in the function you are.
In this case, you only have one recursive call, and the only state is xs
, so things are pretty simple and you don't need a custom state object.
Here's how I'd do things (not tested).
static <A,B> CList<B> maploop(Func<B,A> f, CList<A> xs){
Stack<CList<A>> stack = new Stack<>();
while(xs != null){
stack.push(xs);
xs = xs.tail;
}
CList<a> result = xs;
while(!stack.empty()){
xs = stack.pop();
result = new CList<>(f.m(xs.head), result);
}
return result;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With