There is a pattern is Scala called loan pattern. You open a resource, “loan” the resource to another function, and the loaner closes the resource.
Scala
This function expects a file a function. When it's called it creates the resource, executes the function and closes the resource.
def withPrintWriter(file: File, op: PrintWriter => Unit) { val writer = new PrintWriter(file) try { op(writer) } finally { writer.close() } }
This is how it's called:
withPrintWriter( new File("date.txt"), writer => writer.println(new java.util.Date) )
C#
Now I extended the definition with currying:
readonly Func, string>> openFile = path => handler => { var reader = new StreamReader(path); try { return handler(reader); } finally { reader.Close(); Console.WriteLine("Stream closed"); } };
Here are two examples on calling the function above:
readonly FuncreadAllLines = input => input.ReadToEnd(); readonly Func readSingleLine = input => input.ReadLine(); [Fact] public void LoanPattern_AllText() { var result = openFile("TextFile1.txt")(readAllLines); Assert.Equal("This is the test content.\r\nThis is a second line.", result); } [Fact] public void LoanPattern_ReadSingleLine() { var result = openFile("TextFile1.txt")(readSingleLine); Assert.Equal("This is the test content.", result); }
Result
Now the code calling the function (openFile) is much simpler and there is no need for error handling in the caller. Furthermore thanks to currying, even the resource name can be bound in the constructor, hiding the resource initialization as well.
No comments:
Post a Comment