Sorry if this is a bit long. A bit of background and history.
Impersonal third party view.
It is definitely a language issue. Both ordered and optional
parameters are language specific issues. Ordered parameters with
optional (or default) arguments are a common denominator for many
classical languages (we say multi-paradigm in the C++xy case).
I once worked on a JSON-RPC 1.0 implementation in Java that used
reflection and dynamic binding as well as a few other things such as
server side context injection (local argument resolution). I see
this in the Go implementation which appears to take arrays. We have
done some Objective-C/C/C++/Java stuff with JSON in the past. Just a
little.
Here is some data points for some other languages, from my somewhat
biased perspective:
- Objective-C for has named parameters however argument order is
mandatory. i.e. the parameter names essentially add clarity to the
code. The binary level signatures for Objective-C message selectors
includes the parameter count but not the parameter names. e.g.
@selector(coerceFriend:::) would indicate a method with 3 arguments.
So order here is essential and it would not be possible to resolve
arguments by name at an ABI level to support dynamic invocation with
by-name calls.
- C++ optional parameters would be possible; /easily/ with ordered
parameters; using varargs style linkage, however the types, not the
names are encapsulated in the C++ method signature (RTTI and CTTI
<type_traits>) so unordered named and optional parameters
would be /hard/. For example varargs linkage on x86_64 passes the
argument count in the %rax register. Side note: Ideally we want RTTI
to go away and use CTTI <type_traits> for a C++xy reflection
system. I'm looking at it from removing boilerplate. i.e. packing
and unpacking JSON::Value, etc. and instead binding to native
methods, including ACLs and permissions.
- With LLVM/libcxxabi and or equivalent g++/libstdc++ features and
CTTI <type_traits> (fun new stuff in C++xy: C++11, C++14 and
C++17), it /might/ be possible to recover the parameter names and
not depend on argument order. It would appear to be a budget issue
as it would be easier to just preserve order and not depend on
names. This means order becomes a MUST for interop with languages
that depend on order not names (e.g. only have typelist as a method
signature) and want to support optional arguments. Otherwise type
deduction would become very ambiguous. i.e. support for serializing
and serializing a loose bag into native method calls versus into the
simple 'typeless' JSON container model where you have to write lots
of tedious boilerplate code to pack and unpack results on send and
receive.
I am not certain if parameter name recovery is universally supported
in C++. __func__ macro or typeid(&func).name() would be ugly and
are not yet equivalent across compilers, and they don't get you
parameter names. Unordered optional parameters and dynamic binding
would be /difficult/ unless a mechanism could be created to recover
parameter names. I think not possible. Note in C++ you can define a
function like this (C++11 variadic arguments).
template <typename Filter...>
std::vector<meta::log_entry>
getMetaDataLog(std::chrono::time_point, std::chrono::time_point,
Filter&&... /* filters */);
- Look, no argument names.
In this case you only have a typelist (parameter pack in C++
specification speak, typelist in STL <type_traits> speak) and
no parameter names. So yes order is essential for many languages. We
stuck to order in our implementation and only supported JSON-RPC 1.0
in our implementation.
- Order is also mandatory in protobuf IDL and many other RPC
serializations (Sun-RPC, IIOP, etc). You can always send a loose bag
type (unordered_set, hash) if you want it loose. That's a subset.
- The other issue this raises is the use of TypeScript and
ECMAScript 6 which now give us some level of type safety in the
browser. There is the possibility of an efficient compact typed
binary encapsulations: BJSON with type encoding? protobuf?,
something new? i.e. something that can encapsulate the common
denominator of the richer type systems in ECMAScript 6, C++,
Objective-C, C#, Swift, etc. i.e. Universal support for strongly
typed languages and loosely typed languages.
- Most language have overlap for their containers (C++: vector,
queue, set, map, unordered_set, unordered_map). (Java has Vector,
Queue, HashSet, HashMap, LinkedHashSet, LinkedHashMap). C++ has a
preference for strong typing, type inference and argument dependent
lookup. Some languages use type erasure and some use templates.
python implementation can easily ignore the extra type information
or map it to the best-practices for these containers. i.e. normative
language encapsulation.
- A typeless language can ignore type information; look at the data
as a loose bag; however it is much harder for a typed language to
recover types and order where strict ordering and type information
is required.
- JSON-RPC 2.0 introduced a flaw that universal interop is no longer
/easy/ unless one degrades to accepting loose bags for all calls; so
order is lost for strongly typed languages. You can't call methods
by signature in many languages unless the server were to advertise
either by-name or by-order and the client can support both calling
conventions. This means order is required. Otherwise we get a
disjunct set. We end up with clients sending loose bags to servers
that support call by ordered arguments and they essentially can't
communicate with each other. Send loose bags to a strongly typed C++
server and it is impossible to do type deduction. It becomes
convention, rather than specification. Code degrades to lots of
boiler-plate.
- This issue was raised and there was a disagreement with the chair
(can't remember the name, only the order, I was second). Vaguely
remember the discussion. There was no support to keep it simple. The
argument was that a loose bag is essentially a degraded case of a
single unordered 'map/object' argument. The 2.0 spec essentially
broke support for universal interop for some languages that can't
handle loose bags. A loose bag could have been contained in a 1
element array [] effectively 2 more bytes and the spec would have
been simpler and less ambiguous. Client code that only sends loose
bags essentially drops the super-set of an ordered list or
arguments. i.e. makes type deduction for strongly typed languages
(read: apply) nearly impossible. Not all JSON implementations even
preserve order. We did. We used a linkhash.
- JSON-RPC 2.0 appears very python centric (i.e. defined in terms of
pythons apply method); Not universal. Or perhaps contains a
disjunction in the spec.
- While we're on the topic of JSON. Some silly bugger thought that
because JSON can decode \u1234 that this should be emitted instead
of UTF-8. Lax spec interpretation. UTF-8 is defined to be valid
explicitly so un-escaping is only required on decode. Another
argument :=D
Try protobuf perhaps? I believe it binds to the native function
linkage for many languages. See if it supports variadic template
bindings, typelists and versioning...???
~mc