5 ms·
I read an article recently about memory in Go (the "why is my go program 138GB!?" article), which was enlightening and also weird. I don't have any experience w
by SwellJoe 12y ago
I read an article recently about memory in Go (the "why is my go program 138GB!?" article), which was enlightening and also weird. I don't have any experience with either language, but have plans to learn a smattering of both in 2015.
As for dynamic dispatch...does Rust not support it, or is there some language construct that allows solving the problems dynamic dispatch solves without imposing annoying limitations or needless verbosity? And, aren't there fast implementations of dynamic dispatch?
- steveklabnik 12y agoRust supports both. You might enjoy reading http://programmers.stackexchange.com/a/247313 http://programmers.stackexchange.com/a/247313
- wycats 12y ago> As for dynamic dispatch...does Rust not support it, or is there some language construct that allows solving the problems dynamic dispatch solves without imposing annoying limitations or needless verbosity? Rust supports dynamic dispatch if you truly need it, but the normal approach is to use trait bounds, which the compiler expands when used. Here's an example: fn main() { let r = MemReader::new("hello world\n".as_bytes()); get_line(&r); } fn get_line<R: Buffer>(r: &R) -> IoResult<String> { r.read_line() } In this very simple example, the `get_line` function takes any value that implements the `Buffer` trait, which provides the `read_line` method. When `get_line` is called inside of `main`, the compiler creates a special version of `get_line` that takes a `MemReader`, and dispatches to its implementation of `read_line` statically. In practice, this feels a lot like dynamic dispatch, but using trait bounds always results in static dispatch in practice. Also, in this example, the `MemReader` is stack-allocated, and lent to the `get_line` method. In very rare cases, you may want dynamic dispatch. For example, imagine you have an array of Buffers, and want to read a line from each of them. In this case, you use a "trait object" (a `Box<Buffer>`), which moves the object to the heap and allows dynamic dispatch. In practice, I have written many thousands of lines of production Rust code and have only encountered a need for trait objects a handful of times. This means that idiomatic, normal Rust code is stack-allocated and statically dispatched. The verbosity of trait bounds has decreased more and more over time, and my favorite proposal (by aturon) for making it pretty close to maximally ergonomic is: fn main() { let r = MemReader::new("hello world\n".as_bytes()); get_line(&r); } fn get_line(r: &impl Reader) -> IoResult<String> { r.read_line() } I hope this lands as new syntax after 1.0 :)
- allan_s 12y agoit would indeed be great to have this syntax, can you link to the RFC if you have it? so that we can follow how is this proposal going.
- deleted 12y ago[deleted]
- tterrace 12y agoCould you link the "why is my go program 138GB!" article?
- dbaupp 12y agoI believe it's http://utcc.utoronto.ca/~cks/space/blog/programming/GoBigVirtualSize http://utcc.utoronto.ca/~cks/space/blog/programming/GoBigVir... Permalink to the relevant section of the Go source, with descriptive comments: https://github.com/golang/go/blob/04cf881fbea55d5bca584c78b15454b189af11f5/src/runtime/malloc1.go#L106 https://github.com/golang/go/blob/04cf881fbea55d5bca584c78b1...