One of the conveniences offered by JavaScript's jQuery is the ability to chain methods like so:
$(document).ready(function() {
$('#dvContent')
.addClass('dummy')
.css('color', 'red')
.fadeIn('slow');
});
Instead of the more verbose non-chained way of writing the same:
$(document).ready(function() {
$('#dvContent').addClass('dummy');
$('#dvContent').css('color', 'red');
$('#dvContent').fadeIn('slow');
});
Above jQuery code courtesy of jquerybyexample.net.
This is possible because the $(selector)
function in jQuery returns a jQuery reference to whatever is indicated by selector
, and it is standard for jQuery functions that don't return some type of value (i.e. would otherwise be void
) to return the jQuery reference from $(selector)
so that the next function in the chain can make use of it.
In Rust, however, this seems impossible.
Let's implement this in pseudo-Rust:
fn $(selector: &Selector) -> JQueryReference {
JQuery::get(selector)
}
So far so good...
impl Chainable for JQueryReference {
fn addClass(&self, class: String) -> Self {
deep_frontendy_stuff_add_class(&self, class);
self
}
}
Ooh, no bueno, that deep_frontendy_stuff_add_class()
function can't modify self
. Oh I know, I'll just make the reference mutable!
impl Chainable for JQueryReference {
fn addClass(&mut self, class: String) -> Self {
deep_frontendy_stuff_add_class(&mut self, class);
self
}
}
Cool, that worked! But wait, what if I want to go old school and not use the fancy chained types?
$("#dvContent".to_string()).addClass("dummy".to_string());
$("#dvContent".to_string()).css("color".to_string(), "red".to_string());
Nooooooooo! The borrow checker is at it again!
How do I implement such behavior, and if you wouldn't mind, please be as descriptive as possible about why. This question is really an example to help understand the language.