Hacker News new | past | comments | ask | show | jobs | submit login

The thing is ‘filename’ is a bad example for a an object.

Of course, it should be a string. However ‘File’ object is a better example that favors OOP. When you call ‘.read’ on a file object, you expect its content. It doesn’t matter if it’s a windows file, unix file, an IO string, or a web resource. When you call ‘.read’, it just work. Whereas in the functional world, you’ll have to 4 different ‘.read’ function calls with an if statement.




> Whereas in the functional world, you’ll have to 4 different ‘.read’ function calls with an if statement.

A good language for functional programming provides parametric polymorphism via traits or typeclasses:

    pub trait Read {
      fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>;
    }
    impl Read for std::fs::File { /* ... */ }
    impl Read for String { /* ... */ }
Then you can write a generic function like this:

    pub fn read_kilobyte<R>(r: R) -> io::Result<Vec<u8>>
        where R: std::io::Read {
      let mut buf = vec![0u8; 1024]; // vector of 1024 0s
      let nbytes = r.read(&mut buf[..])?;
      buf.truncate(nbytes);
      Ok(buf)
    }
And call it like this:

    let kb1 = read_kilobyte(File::open(...)?)?;
    let kb2 = read_kilobyte("foo bar baz quux".to_string())?;
No ifs in sight.


That looks an awful lot like OOP to me...


One of the many difference is that there is no inheritance, and implementations of traits can be added for types long after they are defined. Traits in rust are not like java interfaces.


How are traits specific to being a functional language rather than an OO language though?

I mean, I don't see anything horribly functional-language-specific about your trait example.


It wasn't my example, but it's just disproving the notion that FP somehow means you need to write big if statements to dispatch your functions.

Traits are not functional-language specific except in that they are often used in FP to solve problems similar to those one might use inheritance to solve in OOP.


I think you could use a curried read function, in this case. The read function would be passed as an argument instead of your I/O stream.

I fear I've slipped somewhat into OO habits by using Go interfaces.


Exactly right. "Polymorphism" is nothing more than passing a function [or bunch of functions] as argument[s] of another function.


It's unfortunate you're being downvoted for your opinion instead of having other ideas presented to you so I'll do my best though I'm no expert.

> Whereas in the functional world, you’ll have to 4 different ‘.read’ function calls with an if statement.

You could do this but that's not idiomatic.

What you would preferably do is have a function that takes a read function as a parameter. This is essentially the same thing as what OO languages implicitly do.

For an example of generic functions you can take a look at map or fold/reduce. You'll see they don't need to use if statements in the way you described.


I don't know why people keep insisting on using generic words as identifiers when doing so makes it much harder to find something. If I enter "fwrite" into Google, the correct documentation pops right up. I can easily find all the places where file write occurs in my code. I can easily find all the places where network activities are triggered when the associated functions have unique names. Using a if statement and four different *_read function calls is not a shortcoming at all when you take test coverage into consideration.


I'm not sure polymorphism is the best justification for OO. There are plenty of functional paradigms that can abstract over file implementations just as easily as OO. I think the better argument is that a file represents a resource and thus has a more "thingly" character than other "dumb" data.


But wouldn't you have four different read functions in your OOP example anyway, just each in it's own object?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: