On 2/10/13 2:51 PM, Brandon Mintern wrote:
I recently decided to start contributing to Rust, and to that end, I
grabbed the code and grepped for FIXME. One of the issues I came across
was #4423: "Make a version of char::escape_unicode that doesn't
allocate" (https://github.com/mozilla/rust/issues/4423).

I've given this some thought lately, and I think you're generally on the right track. I very much want to make readers and writers not allocate. Now that we have &Trait, this should be doable. Something like this was what I had in mind:

    fn with_str_writer<R>(s: &mut ~str, f: &fn(&Writer) -> R) -> R {
        let writer = StringWriter::new(s) as &Writer;
        f(writer)
    }

    struct StringWriter<'lt> {
        buf: &mut 'lt ~str
    }

    impl<'lt> Writer for StringWriter<'lt> {
        fn write(&self, bytes: &[u8]) {
            self.buf.append_bytes(bytes);
        }
    }

Then the functions like `escape_unicode` could become something like this:

    fn write_escaped_unicode(writer: &Writer, ch: char) { ... }

Then if you wanted the string you could write:

    let mut s = ~"";
    with_str_writer(&mut s, |w| write_escaped_unicode(w, '\u1F63B'))

Of course, that's pretty verbose. So we have a number of options:

(1) For every `write_foo` function, also define a `foo` function. Maybe we could use a macro to autogenerate these, or use one of the combinator functions below as a helper. Then you could write:

    let smiley = escaped_unicode('\u1F63B');

(2) Define a macro so we could write it this way:

    let smiley = write_string!(write_escaped_unicode('\u1F63B'));

(3) Define a few combinator functions that take arguments. Unfortunately we can't do just one due to the lack of tupling of arguments in Rust.

    fn write_string_1<A>(&fn(&Writer,A), A) -> ~str { … }
    fn write_string_2<A,B>(&fn(&Writer,A,B), A, B) -> ~str { … }
    fn write_string_3<A,B,C>(&fn(&Writer,A,B,C), A, B, C) -> ~str { … }

    let smiley = write_string_1(write_escaped_unicode, '\u1F63B');

(4) Define a combinator function that takes a thunk.

    fn write_string(&fn(&Writer)) -> ~str { … }

    let smiley = write_string(|w| write_escaped_unicode(w, '\u1F63B'));

Note that if we had something like Scala's pseudo-currying form with '_' we could shorten that to:

    let smiley = write_string(write_escaped_unicode(_, '\u1F63B'))

But that's probably not a 1.0 feature at this point.

I lean toward (1) myself as a worse-is-better solution, but I don't really feel strongly one way or another.

By the way, once we revamp writers in this way, we should be able to make fmt!() much more efficient, solving the performance problem that Chris Leary noted a while back...

Patrick

_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to