Reputation: 2134
I am doing the following programming exercise: Moves in squared strings (I). The statement is:
You are given a string of n lines, each substring being n characters long: For example:
s = "abcd\nefgh\nijkl\nmnop"
We will study some transformations of this square of strings.
Vertical mirror: vert_mirror (or vertMirror or vert-mirror) vert_mirror(s) => "dcba\nhgfe\nlkji\nponm" Horizontal mirror: hor_mirror (or horMirror or hor-mirror) hor_mirror(s) => "mnop\nijkl\nefgh\nabcd"
or printed:
vertical mirror |horizontal mirror abcd --> dcba |abcd --> mnop efgh hgfe |efgh ijkl ijkl lkji |ijkl
efgh mnop ponm |mnop abcdTask:
Write these two functions
and
high-order function oper(fct, s) where fct is the function of one variable f to apply to the string s (fct will be one of vertMirror, horMirror)
Examples:
s = "abcd\nefgh\nijkl\nmnop" oper(vert_mirror, s) => "dcba\nhgfe\nlkji\nponm" oper(hor_mirror, s) => "mnop\nijkl\nefgh\nabcd"
I would like some help because of it is the first time I need to pass functions as method's arguments. The initial test cases are (taken from the exercise):
import static org.junit.Assert.*;
import org.junit.Test;
public class OpstringsTest {
private static void testing(String actual, String expected) {
assertEquals(expected, actual);
}
@Test
public void test() {
System.out.println("Fixed Tests vertMirror");
String s = "hSgdHQ\nHnDMao\nClNNxX\niRvxxH\nbqTVvA\nwvSyRu";
String r = "QHdgSh\noaMDnH\nXxNNlC\nHxxvRi\nAvVTqb\nuRySvw";
testing(Opstrings.oper(Opstrings::vertMirror, s), r);
s = "IzOTWE\nkkbeCM\nWuzZxM\nvDddJw\njiJyHF\nPVHfSx";
r = "EWTOzI\nMCebkk\nMxZzuW\nwJddDv\nFHyJij\nxSfHVP";
testing(Opstrings.oper(Opstrings::vertMirror, s), r);
System.out.println("Fixed Tests horMirror");
s = "lVHt\nJVhv\nCSbg\nyeCt";
r = "yeCt\nCSbg\nJVhv\nlVHt";
testing(Opstrings.oper(Opstrings::horMirror, s), r);
s = "njMK\ndbrZ\nLPKo\ncEYz";
r = "cEYz\nLPKo\ndbrZ\nnjMK";
testing(Opstrings.oper(Opstrings::horMirror, s), r);
}
}
I have tried the following implementation:
import java.util.function.*;
class Opstrings {
public static String vertMirror (String string) {
String[] words = string.split("\\s+");
StringBuilder sb = new StringBuilder();
for(String word : words){
sb.append(new StringBuilder(word).reverse()+"\n");
}
return string.strip().toString();
}
public static String horMirror (String string) {
return new StringBuilder(string).reverse().toString();
}
public static String oper/*🅾️*/(Consumer<String> operator, String s) {
return operator.accept(s);
}
}
And when we execute the previous code, the compiler outputs:
./src/main/java/Opstrings.java:15: error: incompatible types: void cannot be converted to String return operator.accept(s); ^ 1 error
I understand that Consumer is defined to return void. So then I decided to investigate and I read that Callable is able to return results. So then I tried:
import java.util.concurrent.Callable;
class Opstrings {
public static String vertMirror (String string) {
String[] words = string.split("\\s+");
StringBuilder sb = new StringBuilder();
for(String word : words){
sb.append(new StringBuilder(word).reverse()+"\n");
}
return string.strip().toString();
}
public static String horMirror (String string) {
return new StringBuilder(string).reverse().toString();
}
public static String oper/*🅾️*/(Callable operator, String s) {
return operator.accept(s);
}
}
However this time our compiler says that we can not call the functions without arguments when String is required (from the test cases):
./src/test/java/OpstringsTest.java:14: error: incompatible types: invalid method reference testing(Opstrings.oper(Opstrings::vertMirror, s), r); ^ method vertMirror in class Opstrings cannot be applied to given types required: String found: no arguments reason: actual and formal argument lists differ in length ./src/test/java/OpstringsTest.java:17: error: incompatible types: invalid method reference
In addition, I have also read:
Could you help me please figuring out how could we pass in Functional Interfaces as method's arguments and return its results?
EDIT: As @JB Nizet says it can be done using UnaryOperator:
import java.util.function.*;
class Opstrings {
public static String vertMirror (String string) {
String[] words = string.split("\\s+");
for(int i = 0; i < words.length; i++){
words[i] = new StringBuilder(words[i]).reverse().toString();
}
return String.join("\n",words);
}
public static String horMirror (String string) {
String[] words = string.split("\\s+");
StringBuilder sb = new StringBuilder();
for(int i = words.length-1; i >= 0; i--){
sb.append(words[i]+"\n");
}
return sb.toString().strip();
}
public static String oper/*🅾️*/(UnaryOperator<String> operator, String s) {
return operator.apply(s);
}
}
Upvotes: 1
Views: 260
Reputation: 691765
Consumer
is a function from someting to nothing (void). Callable
is a function from nothing to something. You want a function from something to something else.
That's what Function
is for. Or, since the return type and the argument type are the same in your case, UnaryOperator
.
Upvotes: 3