> Overloaded functions are unnecessary in Rust. In C++ they are heavily used 
> because of templates use duck-typing, but Rust uses explicit interfaces 
> (typeclass-like) which makes it unnecessary.

I agree. This is one of the main use cases for overloaded functions in
C++, and it is irrelevant to Rust. Considering this, I'd say, that
introducing optional named parameters might be a better solution.

> let mut result = vec!(); // type of "result" is "Vec<...>" which is only 
> partially known

> for x in some_range.iter() {
>        doit(result, *x);    // there is a single "doit" in scope, whose 
> arguments is "Vec<int>" thus this is the type of "result"
>  }

To be honest, such a non-local type inference creeps me out. It might
be an unending source of errors. While it probably can be used in some
quick and dirty code snippets, I would never commit such code to a
repository of any self-respecting project.

> Named parameters and default values are just syntactic sugar; they might feel 
> handy, indeed, but in general they can be emulated => Rust already has named 
> parameters for "struct" initialization, and it also has functional update for 
> those "struct" thus as long as you are willing to add one more symbol:

While it is indeed a syntactic sugar, I believe that it's an important
one. (You may argue that all of Python is just syntactic sugar over
some dictionary operations and all of Haskell is syntactic sugar over
linked lists.) I can't imagine anyone adding an explicit struct type
for each and every function that might be expanded in future, or just
has optional arguments.

>> 2. What about exceptions?
> As mentioned, the issue is about recovery: you modified a lot of stuff in 
> your "try" that is still accessible afterward, is it in a safe state ? is it 
> in sensible state ? No one knows, and your compiler does not care. Tasks 
> enforce explicitness about what is modified, which helps in auditing.

Just to make sure I understand how it all should work. Suppose I have
a parser, that raises ParseError. I might use it like this:

let something = Something::new();

try {
  something.parse_str("...");
} catch ParseError as e {
  println!("ParseError at {}:{}", e.row, e.col);
  return;
}

What would be Rust alternative, except passing the errors all around
parser? Doesn't it grow parser code by at least 50%?

>> 3. It seems like almost any string operation requires as_slice().
>> Can't various string methods be also implemented for String?

> It's the lowest common denominator approach, a slice is cheap (no memory 
> allocation) and universal (may refer either to heap allocated buffer or 
> static buffer).

Why not make a trait BaseString and apply all the operations to it?

On Thu, May 29, 2014 at 3:44 AM, Matthieu Monrocq
<[email protected]> wrote:
>
>
>
> On Thu, May 29, 2014 at 2:38 AM, Oleg Eterevsky <[email protected]> wrote:
>>
>> Hi!
>>
>> I've just recently started learning Rust. Here's a few questions that
>> I have after writing about a hundred lines of code:
>>
>> 1. Why neither overloaded function, nor default values for arguments
>> are supported? In statically typed language overloaded functions are
>> quite safe and convenient. Also, from what I see, overloaded functions
>> could be used in various use cases instead of macros.
>>
>
> Overloaded functions are unnecessary in Rust. In C++ they are heavily used
> because of templates use duck-typing, but Rust uses explicit interfaces
> (typeclass-like) which makes it unnecessary.
>
> Overloaded functions also don't play too well with type inference. C++ works
> around this by having a very simple type inference (ie, it only deduces the
> return type), but Rust's type inference is more advanced:
>
>     let mut result = vec!(); // type of "result" is "Vec<...>" which is only
> partially known
>
>     for x in some_range.iter() {
>         doit(result, *x);    // there is a single "doit" in scope, whose
> arguments is "Vec<int>" thus this is the type of "result"
>     }
>
> If you were able to overload "doit" though, suddenly things would get hairy,
> and you would have to start explicitly typing your variables left and right.
>
> Thus, even besides the confusion a human being experiences (which overload
> is called ?) and the over-abuse of overloads in the first place (Qt seems to
> be doing nicely in that domain), there is a technical trade-off: better type
> inference or function overload ?
>
> Note: it also means that compiler error-messages are generally more
> explicit; tried forgetting to implementation "operator<<" for a type and see
> what your favorite C++ compiler reports ;)
>
>
> Named parameters and default values are just syntactic sugar; they might
> feel handy, indeed, but in general they can be emulated => Rust already has
> named parameters for "struct" initialization, and it also has functional
> update for those "struct" thus as long as you are willing to add one more
> symbol:
>
>     struct FooArgs { x: int, y: int, }
>
>     static DEFAULT_FOO: FooArgs = FooArgs { x: 4, y: 5, }
>
>     fn foo(args: FooArgs) {}
>
>     fn main() {
>         foo(FooArgs{x: 3, .. DEFAULT_FOO})
>     }
>
> I personally feel that the name "FooArgs" could be inferred in the call
> (since there is no overload of "foo" there is no ambiguity) which would
> assist in this pattern. There is also the issue that static cannot be build
> from arbitrary functions, but that may be lifted with Compilation Time
> Function Evaluation one day, and in the mean time you can have a
> FooArgs::default() that computes the defaults.
>
>
>>
>> 2. What about exceptions? Is it a design decision not to support them,
>> or are they planned for some future version? I understand, that
>> exceptions make memory management more difficult, but maybe there are
>> ways to restrict their usage to avoid problems (like making it
>> impossible to pass references as exception parameters?)
>>
> As mentioned, the issue is about recovery: you modified a lot of stuff in
> your "try" that is still accessible afterward, is it in a safe state ? is it
> in sensible state ? No one knows, and your compiler does not care. Tasks
> enforce explicitness about what is modified, which helps in auditing.
>
>>
>> 3. It seems like almost any string operation requires as_slice().
>> Can't various string methods be also implemented for String?
>>
> It's the lowest common denominator approach, a slice is cheap (no memory
> allocation) and universal (may refer either to heap allocated buffer or
> static buffer).
>
> Rust is working on DST (Dynamically Sized Types) and once this lands String
> will be able to implement Deref, which will ease things. There is also been
> talk about auto-deref to make it even painless.
>
>>
>> 4. It looks like vectors can be concatenated with + operations, but
>> strings can't. Is it deliberate?
>
>
> As someone else answered, it could be done.
>
> Personally though I've never liked that. '+' is mathematically a commutative
> operation and catenation is not a commutative operation. Also, in the
> absence of overloading this means to catenate you have to implement the Add
> trait. This is just weird. I would prefer infix function calls (`cat`) for
> example, or another dedicated operator (++ ?)
>
>>
>>
>> 5. Simple indexing doesn't work for vectors:
>>   let a = vec![1, 2, 3];
>>   println!("{}", a[0]);
>> It's a bit surprising...
>>
> Could probably be implemented, may have to wait for DST though.
>
>>
>> 6. impl ToStr for custom struct fails:
>>   error: conflicting implementations for trait `std::to_str::ToStr`
>>   note: conflicting implementation in crate `std`
>> Is it a bug? Is Show implicitly assumed for all struct's?
>>
>> 7. The usage of mut is a bit confusing. It is supposed to be used as a
>> qualifier for a variable, but it quickly becomes a part of the type,
>> when you define functions like
>>   fn test(something: &mut Something)
>> Maybe it makes sense move mut their? Or distinguish mut as a variable
>> qualifier vs const as a propery of type?
>>
>
> There has been an extended discussion about it, and I am also slightly
> confused by the use of `mut`. It reads "mutability" but in the case of
> references also implies exclusivity...
>
> At the end of the day though, there's already a number of high-profiles
> changes going on (such as the above DST), so for now it's wait and see. Once
> those are implemented and the core developers have a bit more time on their
> plate, the issue might be revisited.
>
>>
>> --
>> Thanks,
>> Oleg Eterevsky.
>> _______________________________________________
>> Rust-dev mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/rust-dev
>
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to