Skip to content
Advertisement

Writing Content to a Text File with Currying

public static Function<String, Function<String, Void>> 
write(BiConsumer<BufferedWriter, String> consumer) {
    return resourcePath -> data ->  {
        if(data != null) {
            try {
                BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(resourcePath));
                consumer.accept(bufferedWriter, data);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    };
}

I’m trying to write to a text file using the above method by applying the concept of currying. The first lambda expression receives the file path as parameter and the second one takes in a String value that should be written to the text file. The write method receives a BiConsumer argument because data is written differently depending on the context (appending to the end of the file, replacing a specific line in the file etc.). It can be called like this:

DataAccess.write((bufferedWriter, data) -> {
    // write to file here
}).apply("path").apply("data");

I know that I’m not supposed to return Void with the Function interface. How can I change the method definition so that it can be called in a similar way? If possible, I would still like to apply currying in this case.

Advertisement

Answer

I know that I’m not supposed to return Void with the Function interface. How can I change the method definition so that it can be called in a similar way?

You can change the return type of write() method to Function<String,Consumer<String>> (a Function producing a Consumer). Since you don’t need to produce any result, it doesn’t make sense to use a Function. When you only need to fire an action, it’s a job for a Consumer implementation.

public static Function<String, Consumer<String>>
write(BiConsumer<BufferedWriter, String> consumer) {
    
    return resourcePath -> data ->  {
        if(data != null) {
            try(var bufferedWriter = new BufferedWriter(new FileWriter(resourcePath))) {
                consumer.accept(bufferedWriter, data);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
}

Usage example (write().apply().accept()):

write((bufferedWriter, data) -> {
    // write to file here
}).apply("path").accept("data");

Sidenote: always use try-with-resources to make sure that your resources are properly closed.

Advertisement