Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extend overloading example by mentioning macros #75

Closed
vks opened this issue Jun 4, 2014 · 7 comments
Closed

extend overloading example by mentioning macros #75

vks opened this issue Jun 4, 2014 · 7 comments

Comments

@vks
Copy link
Contributor

vks commented Jun 4, 2014

Currently only traits are mentioned in the overloading example. They only work if the functions to be overloaded have the same number of arguments. Using macros it is possible to have more generic overloading. See for example this implementation of a Python-like range:

#![feature(macro_rules)]

use std::iter::range_step;

macro_rules! range (
    ($start:expr, $end:expr, $step:expr) => (
        range_step($start, $end, $step)
    );
    ($start:expr, $end:expr) => (
        range($start, $end)
    );
    ($end:expr) => (
        range(0, $end)
    );
)
@japaric
Copy link
Member

japaric commented Jun 4, 2014

Currently only traits are mentioned in the overloading example

Sorry, which chapter are we talking about? The "Operator overloading" one?


If any case, I think this should go in the "macro_rules!" chapter.

@vks
Copy link
Contributor Author

vks commented Jun 4, 2014

Actually the operator overloading chapter is about something else, sorry for the confusion. I was referring to function overloading.

If you are coming from a C++ background and want to know how function overloading translates to Rust, then there are two possibilities:

  1. Use traits and generics when a function has a constant number of arguments but should work for different types (i.e. when implementing abs for floats and integers).
  2. Use macros when the number of arguments varies (i.e. the range example). This does not work for methods.

Maybe there should be a new chapter about function overloading?

@japaric
Copy link
Member

japaric commented Jun 5, 2014

Maybe there should be a new chapter about function overloading?

Note that Rust does not have function overloading, hence having a "function overloading" chapter (with that exact name) may be misleading. However, I agree that it would be great to show how to achieve something similar with traits [1] and macros.

I think we have two options:

(1) We add a "function overloading" chapter, but clearly state that these are tricks to achieve something similar, because Rust doesn't have function overloading.

or

(2) We stuff these tricks in other chapters (like in the macro_rules! chapter)

I'm leaning towards the first one.

@vks What do you think?

[1] This is a little limited at the moment, currently trait methods are specialized based on the concrete type of Self, but this can be extended using double dispatch (see "What if I want overloading" section") to allow specialization based on Self and another method argument. There is (was?) an RFC for making this easier (less verbose), but I don't know when it'll be implemented.

@vks
Copy link
Contributor Author

vks commented Jun 5, 2014

@japaric I prefer option (1). Option (2) would be too hard to find if you are looking for overloading.

An example about multiple dispatch would be nice, but it probably should be it's own chapter, as it is fairly advanced.

@japaric
Copy link
Member

japaric commented Jun 14, 2014

I need to think more about this. But as a first idea, your macro example can go with the macro_rules chapter as a sub-chapter.

And the multiple dispatch could be a sub-chapter in the "trait" chapter. (I'm not too sure about this last one)

@mdinger
Copy link
Contributor

mdinger commented Aug 13, 2014

Here is an expanded range macro. Playpen link here

Here is their macro:

// `range!(a..b)` for example
//
// `a..b` => [a,b) (exclusive)
// `a...b` => [a,b] (inclusive)
// `..b` => [0,b)
// `a..` => [a, infinity)
// `a..b, c` => [a,b) in increments of c
macro_rules! range {
    (.. $to: expr) => {
        std::iter::range(std::num::zero(), $to)
    };
    (... $to: expr) => {
        std::iter::range_inclusive(std::num::zero(), $to)
    };
    (.. $to: expr, $step: expr) => {
        std::iter::range_step(std::num::zero(), $to, $step)
    };
    (... $to: expr, $step: expr) => {
        std::iter::range_step_inclusive(std::num::zero(), $to, $step)
    };
    ($from: expr .., $step: expr) => {
        std::iter::count($from, $step)
    };
    ($from: expr .. $to: expr) => {
        std::iter::range($from, $to)
    };
    ($from: expr ... $to: expr) => {
        std::iter::range_inclusive($from, $to)
    };
    ($from: expr ..) => {
        std::iter::count($from, std::num::one())
    };
    ($from: expr .. $to: expr, $step: expr) => {
        std::iter::range_step($from, $to, $step)
    };
    ($from: expr ... $to: expr, $step: expr) => {
        std::iter::range_step_inclusive($from, $to, $step)
    };
}

@steveklabnik
Copy link
Member

I don't feel this is appropriate for the book; using macros for only overloading isn't something that you should do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants