-
Notifications
You must be signed in to change notification settings - Fork 100
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
Call/CallResult/Event Arguments. #21
Comments
The difference is intentional: WAMP should be usable with languages that have this semantics (of function always having a single return type). JavaScript allows "undefined". Other languages allow multiple return values. To make this work transparently, the client libs needed to adapt that. But then the API is different depending on host language: i.e. a WAMP result with multiple values would be wrapped into array for languages lacking multi-return value, but not for other languages supporting that construct. So its unified at WAMP level. For similar reason WAMP does not provide means to have RPCs with named arguments, only positional arguments. You can of course send a dict though. So: not a bug, won't fix. |
Ok, but then why Call messages are not following the same logic ? What I'm saying is all messages should follow a unified specification about arguments, one way or another. |
Because all host languages support "call by positional arguments". |
I'm not really understanding but I'm ok if you say so. Also I'm using Java (function always having a single return type) and I'm more comfortable with the optional multiple arguments way. |
The logic is: model WAMP call request and result messages along the least common denominator of host languages:
The reasoning is: there is no point in making WAMP call request/result messages "symmetric" on the wire, if that cannot be conveniently mapped to host languages. Personally I think good protocol design should take into account the fact that the protocol isn't a goal in itself, but only together with host language integration. |
I disagree. There is a distinct difference between multiple return and returning an array, and I like to think of single return as a special case of multiple return, not the other way around. Correct support of multiple-return functions requires the client to know something about the host to determine whether an array is actually an array or multiple-returns pretending to be an array. Clients that don't support multiple return can do the transation in whatever way works for that particular language (translate into array, tuple, whatever). It doesn't seem right to restrict a protocol because most languages expect something to be a certain way, especially when making it more general costs nothing. As a concrete example, consider the following Go examples:
I cannot write a library to handle any of this transparently because there's nothing in the protocol that tells me there's a difference. This seems unnecessarily messy just to make single-return languages simpler, especially since it's simpler to translate a multiple-return into an array for those languages, which can be done transparently. I understand that Go is not officially supported, so I'll back this up with a Javascript example. When writing an async function, it's common to use a callback, which can take multiple arguments:
This could be very nicely modeled with In the same vein, CALL_ERROR can be generalized to make ErrorDetails variadic as well without losing any expressiveness. It's possible for languages like Go to return multiple errors even though it's not common (and not really idiomatic either). Please reconsider this decision. I really don't understand the logic for restricting it to a single return value. Supporting multiple-return is backwards compatible and can be simply handled by languages that don't support it. |
WAMP should be language neutral, so we want to support Go as well as Java and JavaScript (and others of course). However, regarding above issue, that ("language neutral") could mean following a
protocol approach at both ends of the spectrum. Existing/conceivable languages do/could provide any combination of the following with function calls:
Here is a nice language overview regarding named arguments: http://rosettacode.org/wiki/Named_parameters "no return" (4.) is different from "single return" (5.) with I am not aware of languages supporting 7. or 8., but who knows what gets invented tomorrow? However, regarding 9., there are procedural SQL dialects like PL/SQL. Python supports 6., but you cannot differentiate between 6. and 5. returning a tuple:
Regarding your JavaScript example with multiple returns - this is how you would do that with AutobahnJS:
Then, if the protocol would differentiate between single and multiple returns, you'd be able to differentiate in languages supporting this, but languages without support couldn't unless wrapping in a special WAMP follows the "keep it simple" mantra. The "least common denomiator" approach is simple. However, I'd nevertheless be interested if we can formulate a cohesive proposal for the "superset" approach (supporting all of 1. - 9., not only 1., 5. and 6.). |
Since someone seems to agree with me and most of the discussion about this was private let's make a public recap. So you claim to do it intentionally to ease implementation of host language, especially language with function returning 1 single value. I'm working on the Java implementation so here is why I disagree and I think in fact it make things complicated even for this kind of language : Wamp is a communication language it means we have to serialize and deserialize object through JSON. class WampArguments {
boolean hasNext();
Object next();
T next(Class<T> type);
} The user can iterate over to get all the arguments and this way he can specified which type he is expecting so we can deserialize it properly. Not all language allows parameterized function but the point stay the same.
And I can't imagine it returning anything else like int, boolean, String... because I can't guess what's the type of the CallResult. Now I heard a lot about wrapping it into an array. I'm not wrapping anything.
The actual design is confusing because, as beatgammit said, an array can be a single return or a multiple-return wrapped. Things should be clear at protocol level for all messages like it's done for CallMessage. |
Ok we posted at same time. The point of my previous comment was implementation are not strictly based on language specification. We have to adapt and that's the job of an implementation. Adapt a design to a concrete working mechanism. I think a protocol should be simple (not depending on any language) and easy to use at final ends. With the actual design final user must adapt because of this lack. The final user must "hack" the protocol by sending multiple-returns as one. |
Java has no multiple returns, so I don't understand why excluding multiple returns as an explicit RPC return message does any harm to "end users" (= developer programming against a WAMP library) in this case. Yes, when calling a RPC endpoint, the user either consumes the returned value via a generic object (as you seem to do) or the user specifies the type into which the return value is supposed to be coerced into in advance. The latter option is what AutobahnAndroid provides in addition to the first. AutobahnAndroid is a Java implementation of WAMPv1 clients-side, and there is no problem with only having single-return, and not multiple-return. |
I don't see how allowing 0 or more return values hurts anything with single returns. It doesn't solve the problem with named returns (which I've also never heard of) but it does allow 4-6 implicitly (languages that support just 5 can do their own magic). Forcing a single return only makes 5 easy, while requiring a hack for 4 and 6. I think the best mix of extensibility and saving bytes is an ordered list of parameters:
Where the new third parameters parameter represents the modifiers on the parameters. For example, for this D function:
The call would look like:
If they were named parameters instead:
This only adds a few bytes in the simple case, but it adds a lot of expressiveness and extensibility. No polymorphism is required, and the general case is optimized. |
Regarding "cohesive proposal for the superset approach": I think above points into the right direction. I will try to summarize / write up above, so that we can then discuss and vote up/down 2 concrete proposals: the "least common denominator" and the "superset" approach. With regard to IN, OUT, INOUT: not sure why you include those modifiers during the call (and hence WAMP message). Lets discuss with your concrete D example (I dont know D, so bare with me if I make syntax errors):
When calling such function providing
Here, the single return is always before INOUT and OUT returning parameters. Then, there are different variants of
and different variants of
Mmh. Not sure yet what to think about above. In any case, I don't know D, but I do know PostgreSQL PL/pgSQL, which has one of the most flexible procedure parameter and result passing styles I am aware of. And if we in the end decide to walk the "superset" road, then IMHO we should be able to support even those wield styles of PostgreSQL. |
Good point about the access modifiers. In hindsight, I can't see how it could be useful. Another idea, drop the array wrapper:
This seems a little less cluttered, but it has the negative side-effect that the "parameters" idea isn't isolated, which could make extending a little more difficult. For example, if some kind of meta information is needed, it would go after the parameters, requiring that both positional and named parameters be supplied, even if empty. Then, after that, if another parameter type is defined (register name, external resource, whatever), this would go after that meta information. At the risk of being slightly uglier, I like my previous proposal. However, if this cleaner version is used, then future additions should probably go in another method type: CALL_A, CALL_RESULT_A, etc. FWIW, I am in favor of "superset of all". |
The "superset of all" is now in WAMPv2: https://github.com/tavendo/WAMP/tree/master/spec |
In Call messages you can send 0,1 or multiple arguments.
In CallResult and Event messages you have to send an unique argument, which can be null or a list of objects.
Why theses differences ? Shouldn't we always be able to send 0(null), 1 or multiple (without the use of list) arguments in all messages using arguments ?
What I mean is all messages using arguments should use the same specification.
The text was updated successfully, but these errors were encountered: