3 ms·
> You can call methods with explicit self too. Point is "signatures are different". You can't use this function in place where you need signature without &self
by EugeneOZ 11y ago
> You can call methods with explicit self too.
Point is "signatures are different". You can't use this function in place where you need signature without &self.
> You're not supposed to
It makes life of web-servers harder.
> Could you expand on this point?
To parse JSON with nested objects you need to declare a lot of structures. When APIs are difficult, people even use code generators.
> It's idiomatic
It's not an argument. What work should work. Idiomatic or not - another question.
- Manishearth 11y ago> Point is "signatures are different". The signature is fn(&Foo, u8). If that's not in the right order, you can always put it in a closure -- this is not a Rust-specific problem. > It makes life of web-servers harder. I don't see why web servers need exceptions. You do have catch_panic if you want to prevent the application from ever crashing; that's what it's for (rewrapping fatal errors at the top level or preventing panics from leaking through FFI) > To parse JSON with nested objects you need to declare a lot of structures. Fair enough. I think there was a nested hashmap based JSON library somewhere?
- EugeneOZ 11y ago> you can always put it in a closure That's where I started. And it's Rust-specific problem because of implicit "self" argument, needed to send link to instance.
- Manishearth 11y agoNo, the implicit self can be made explicit in the caller. Or you can have a non-self function. This is no different from having a function which takes parameters in a different order from what's expected, and is not specific to Rust.
- EugeneOZ 11y agoNo, caller doesn't care about "self" and should not. It's Rust-specific ugliness and "different order of arguments" is absolutely not the same as "implicit first argument".
- Manishearth 11y agoI think I really need to see an example of what you're talking about. "implicit first argument" can be made explicit, we've established that. If the signature is still different that's an issue with order of arguments. If you don't want it to take self at all, well, it's a method, that's how methods work, they have a receiver. In all languages.
- EugeneOZ 11y agoI really wonder how it can be unclear. Iron expect method with signature "Fn(req: &mut Request) -> IronResult<Response>", it means you just can't use any method of instance, because all of them have crappy "&self" in signature (otherwise there is no point to make them methods of some object). And yes, you can add closure wrapper, add "move" keyword and satisfy all "move" requirements. But it's exactly what I'm talking about.
- Manishearth 11y agoYes. And this problem is isomorphic to the problem where you have a freestanding function; i.e. struct Foo {..} impl Foo { fn handle(&mut self, req: &mut Request) {..} } is isomorphic to struct Foo {..} fn handle(foo: &mut Foo, req: &mut Request) {..} And of course it is. The handle function needs a `Foo` to store state or whatever. If it didn't, you wouldn't have implemented it as a method at all, you would have implemented it as a non-self function (`impl Foo {fn handle(req: &mut Request)}`, which can also be passed directly as `Foo::handle`). Where would the Iron function get this receiver from? You have to pass the receiver down with the function, so you need a closure (anything which is callable and has an associated state, i.e. more than just a function pointer) This has nothing to do with `self`. It has to do with the fact that methods need a receiver, which is a general fact of life with methods. So your handler needs a receiver with some extra state that you're using. You would need to pass down the receiver regardless, and the signature doesn't support arbitrary receivers. This is a problem in Rust and Python, as you correctly noted. It's a worse problem in Java where the stdlib callable doesn't even allow arguments, so you have to implement an interface (FWIW this solution is available to you in Rust too, either directly implementing `Fn(..)` or if Iron decides to accept a special trait instead), which is much more typing. PHP needs you to construct an array thing to make a callable closure, which is arguably just as 'bad' as Java. C# has type safe callbacks which allow you to specify arguments, however methods don't work. You need additional boilerplate for it (http://stackoverflow.com/questions/4015451/pass-a-method-as-a-parameter http://stackoverflow.com/questions/4015451/pass-a-method-as-...) C++ has function pointers, but methods don't work as function pointers (since you still need there to be a closure under the hood, and C++ doesn't do that kind of implicit stuff). C++ Concepts seems to have a "Callable" concept, but I didn't look into whether or not it comes with auto-closureifying syntax. So really the issue has nothing to do with `self` being used for method signatures, it has to do with whether or not `object.method` is automatically turned into a closure. Rust tries to avoid such magic, so it doesn't have this feature. It could, with relative ease, without getting rid of `self`. Two languages which do seem to do this are Javascript and Go. In Go (http://play.golang.org/p/jsKtkbD7vr http://play.golang.org/p/jsKtkbD7vr), `foo.handle` is automatically turned into a `func(*Request)`, which is even more magical, since IronRun expected a `func` and not an `interface Callable` or whatever. Javascript does the same, `obj.handle` will auto-create a closure for you. Yes, it would be slightly neater for Rust to auto-closure `obj.handle`, but this sounds a bit too magical for Rust (which tries to be low level and make costs explicit). This has nothing to do with `self`, and this isn't a problem localized to Rust.