4 ms·
> Consider now you send a physical letter to me? You use a mail carrier. You have my address, but sending is through the carrier. Same for calls, you use a serv
by jonahx 3y ago
> Consider now you send a physical letter to me? You use a mail carrier. You have my address, but sending is through the carrier. Same for calls, you use a service provider to make the call.
We perform some actions with tools, but not all. Do you use a tool to run? To read a book? You simply run, or read. My issue is that Go forces every situation into the tool paradigm.
If I have an object representing a file that I can read from, I am reading from that file. I am not using anything to read from it. So either the object can no longer represent the file directly (but instead a tool used to read it), or the file can keep representing the file but the language is off because the file is now also a "Reader" (in the Go sense) of the file.
> You are using some other code capable of reading from the file, though.
We are talking about how to conceptually name pieces of our code to match our natural concepts and language. That is, the conversation we're having is one about modeling, so this move seems illegal to me. The "other code implementing reader" is not part of the model. It would be like arguing, in regular life, that "you can't say that you read a book, because really it is your brain doing the reading".
- taeric 3y agoBut you are playing into it? If you are the one running, you are a runner. If you used someone else to run a letter to the whatever, they were the runner. It can fail if you are writing the physical contact point to the hardware, but very few of us do that. We use code that does that. Do I use a tool to read? I have reading glasses. And an ebook reader. And I've delegated some reading to others. Life is complicated. Language no less so.
- jonahx 3y ago> And an ebook reader Your ebook reader it the thing being read, not the thing that reads. Glasses for reading are also called readers, and they are the tool helping you read. Here, to your point, we see "language being complicated" -- the same convention being used for opposite things. But this is a tangential point leading us astray. I thought about this some more in the shower, and I think I can distill my objection more clearly. Methods on objects act on those objects. That is: object.do() is equivalent, in English, to performing the action "do" on "object". To take a random example from Effective Go: d, err := f.Stat() if err != nil { f.Close() return err } We "Stat()" the file (get statistics about it) and we "Close()" the file. This pattern is well-established in both Go and nearly every language with objects. Instance methods are actions performed on their object. Now of course "File" also implements "Reader". Yet when I "f.Read()" the situation is exactly the same as in "Stat" and "Close". I am reading the file. So where is the "Reader" now? Well the Reader is also the file. In the conceptual model, there is no other object around. The file is both the Reader and the object of reading. And that's my problem. The "reader as tool" is inconsistent with "methods act on objects". In the tool model you've been arguing for, I would have to write something like: reader.read(file) The redundancy of that aside, this is not typically what you see with Go code (though you sometimes do). You are more likely to see stuff like "f.Read()" As I said, you can argue that Go's "File" object is not meant to represent a file, but instead an abstract tool: a thing which can Read and Stat and Close files. But that's not what the documentation says: "File represents an open file descriptor." That is, in the intended conceptual model, the "f" in "f.Read()" is a file. And we are reading it. And that is at odds with it being a "Reader" -- a thing that reads.
- joshuamorton 3y agoThe reader reads the file into a string. You then access or modify the string. The file is a thing on disk being read by a file reader, an implementation of the reader interface, which reads the file.
- Too 3y agoIn this case, isn't it kindof right though? If it says it represents a file descriptor, not a concrete file. The descriptor reads the file for you. You close the descriptor, not the file, etc. Though in that case you could argue the name of the object should be FileDescriptor and not File. You are onto something, often we model functions to act on objects, not objects to be tools acting on other objects.
- jonahx 3y agoHere's some example C using one: bytesRead = read(fd, buf, BUF_SIZE - 1) You read the from the file descriptor into the buffer. Just like in Go you read from a file into a byte array. Neither the file descriptor nor the file is conceptualized as a tool for reading. The file descriptor is merely an abstraction of the file, which extends the concept of "file" to include pipes, sockets, and other io.
- tsimionescu 3y agoIn typical OS definitions, a file descriptor or file handle doesn't do anything, it's just some abstract way of referring to a position in a file uniquely. You can ask the OS to read data from the position in the file that the file descriptor points to, or to write data to it, or to map a segment of it into your memory, or to tell you other details about the file. But the file reader, and the file writer, and the file mapper etc are all parts of the OS, not the file nor the file descriptor. In this sense, the GP is right - to respect OS terminology, in Go we should write fileReaderWriter := os.Open(path, "rw") Since os.Open doesn't return a file handle/descriptor, but an object capable of reading or writing to a file. This is different from C, where open() does return a FILE*, which is just a handle to a file which you explicitly pass to read() or write() or mmap() etc.
- 3y ago