qpid-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Fraser Adams <fraser.ad...@blueyonder.co.uk>
Subject Type systems - was Re: Comments on the AMQP management spec
Date Fri, 11 Apr 2014 17:12:06 GMT
On 11/04/14 16:34, Gordon Sim wrote:
> In a modified version of your original code snippet:
>
>   message.body = ['Rod', 10000001, {cat: true, donkey: 8}];
>
> how would you indicate that this is a management related message and 
> that therefore the numbers should always be encoded as a double? (and 
> what about the boolean?) 

That's actually a really interesting question and one that has caused me 
a lot of navel gazing as to how to best encode from JavaScript into the 
AMQP type system (going the other way is relatively easy - well longs 
have some interesting edge cases).

I was as bit torn, for being *explicit* about types I started off 
thinking about creating a raft of wrapper/boxing classes such as say 
proton.Data.Float, proton.Data.UnsignedInteger etc. etc. ad infinitum 
:-) though I'm not thinking that I'll use strings with a "literal" form 
instead e.g. {"Rod": "4.0f"} {"Jack": "5ul"} and so on and if I want the 
string 4.0f to quote it {"Rod": "'4.0f'"} that seems a reasonable 
approach for typed numbers in a loosely typed language and feels perhaps 
more natural and idiomatic than say {"Rod": new proton.Data.Float(4.0)} 
though clearly the latter is as explicit as it gets, but is looking 
closer to Java than JavaScript at that point.

I'd be interested in the thoughts of the group on this - I'm open to offers.


It's possibly more "exciting" when considering what to do by default for 
numbers. The "easy and obvious" thing to do would be to take JavaScript 
numbers and encode them as double, what I'm currently doing looks like 
this (still work in progress) because "easy and obvious" didn't 
necessarily translate in my mind to "most useful"

     } else if (Data.isNumber(obj)) {
         /**
          * Encoding JavaScript numbers is surprisingly complex and has 
several
          * gotchas. The code here tries to do what the author believes 
is the
          * most intuitive encoding of the native JavaScript Number. It 
first
          * tries to identify if the number is an integer or floating 
point type
          * by checking if the number modulo 1 is zero (i.e. if it has a 
remainder
          * then it's a floating point type, which is encoded here as a 
double).
          * If the number is an integer type a test is made to check if 
it is a
          * 32 bit Int value. N.B. JavaScript automagically coerces floating
          * point numbers with a zero Fractional Part into an exact 
integer so
          * numbers like 1.0, 100.0 etc. will be encoded as int or long 
here,
          * which is unlikely to be what is wanted. There's no easy way 
around this
          * the two main options are to add a very small fractional 
number or to
          * represent the number in a String literal e.g. "1.0f", 
"1.0d", "1l"
          */
         if (obj % 1 === 0) {
console.log(obj + " is Integer Type " + (obj|0));
             if (obj === (obj|0)) { // the |0 coerces to a 32 bit value.
                 // 32 bit integer - encode as an Integer.
console.log(obj + " is Int ");
                 this['putInteger'](obj);
             } else { // Longer than 32 bit - encode as a Long.
console.log(obj + " is Long");
                 this['putLong'](obj);
             }
         } else { // Floating point type - encode as a Double
console.log(obj + " is Float Type");
             this['putDouble'](obj);
         }
     }

In other words I check if the number is an "integer like number" by 
checking its remainder, if it is integer like I coerce it into a 32 bit 
value and if that is the same as the original then it is a real integer 
otherwise I encode as a long. Floating point types I encode as doubles.

I think that's mostly what would be "natural" in most peoples minds, 
however JavaScript screws with that a bit, so to take your example

message.body = ['Rod', 10000001, {cat: true, donkey: 8}];

Those would be encoded as Integers, but unfortunately

message.body = ['Rod', 10000001.0, {cat: true, donkey: 8.0}];

Would also be encoded as Integers because JavaScript implicitly converts 
things that can be exactly represented as integers into integers 
internally. So something like this

message.body = ['Rod', "10000001.0", {cat: true, donkey: "8.0"}];

Would be needed to specify integer numbers as doubles if you see what I 
mean.


I'm quite torn on all of this, which is why I definitely agreed with 
your comment that type systems can complicate things rather :-)


Again I'd be interested in what the community thinks would be the most 
useful approach. The JavaScript bindings are coming on quite well in the 
branch (currently working on Binary data support). I've still got some 
tidying, adding tests and sorting out some wrinkles like the stuff 
above, but it's starting to look pretty decent.

Frase



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org


Mime
View raw message