JSONx is Sexy LIESx



  • Trout-faced is a truly ancient term of abuse, so combines with said sketch rather obviously.

    Now, go and cut down the tallest tree in the forest with a herring.


  • 🚽 Regular

    @flabdablet said:

    Filed under: a good grasp of scale
    Fish scale?

    @another_sam said:

    Continuing the lame joke tradition


  • FoxDev

    You don't have to compete with me for whoosh badgers y'know… 😛


    @Zecc said:

    @flabdablet said:
    Filed under: a good grasp of scale

    Fish scale?

    This is one halibut plaice…
    :rimshot:



  • 😑


  • FoxDev

    My apologies if I've given you a haddock; I cod some stuff for that somewhere…



  • 🚪



  • @RaceProUK said:

    This is one halibut plaice

    Good for trolling too.

    Here's a tutorial on the correct use of the cluebat.
    https://www.youtube.com/watch?v=h_NSFWBhQ2A
    After sufficient application of the bat, you can lead them by the nose.



  • @tar said:

    So remember when everyone argued that [,,] was a 'convenient' shorthand for [undefined,undefined,undefined], and I said that was stupid and wrong?Well...

    Actually, I think this is a result of the fact that "undefined" doesn't work as an assignable keyword. I'm not sure if this is an inconsistency in the spec or by design, but making a variable (or array index) with a value become undefined requires using delete, not assigning "undefined". So, [,,] has two undefined values (because JS chops the last comma, dubiously), whereas [undefined, undefined, undefined] has three defined values, all of which are whatever the word undefined gives you.

    When you do "a = [undefined, undefined, undefined]", you're doing the same thing as:

    var h;
    b = [h, h, h];
    

    As is evident from the output of both assignments:

    > var h
    undefined
    > c = [h,h,h]
    [ undefined, undefined, undefined ]
    > a = [undefined,undefined,undefined]
    [ undefined, undefined, undefined ]
    

    @accalia said:

    i know why stringify reported nulls (undefined is coalesced to null for json) but why is that only two elements? and why does forEach not fire correctly for it?

    i'm inclined to think we found a bug in V8.

    This is actually correct behavior; maps over arrays skip undefined, which was part of my original motivation for wanting them preserved in JSON.

    @Zecc said:

    This disturbs me:

    > [undefined, ,undefined].forEach(function(x, idx){console.log(idx);})
    0
    2
    undefined

    The forEach function skips the "true" undefined, which is the second element. The last undefined is, of course, the return value of forEach, which is nothing, thus undefined.

    @Jaime said:

    This entire thread started with @VaelynPhi lamenting that JSON didn't bake in a JavaScript array quirk. Three hundred replies later, we now have confirmation that JavaScript arrays really are weird.

    I don't think collective confusion proves your conclusion, especially when my original complaint wasn't even what you claim. The annoyance was the silent conversion of "undefined" to "null", which undefined is not, because null is an actual value, whereas undefined is the absence of a value (not the absence of a key), and so is treated differently by functions which iterate over arrays. This is a pretty straightforward and easy to understand problem: array data moved from one system to another via native JSON doesn't behave the same on both ends.

    The semantics of null and undefined obviously rely on the semantics of the data context, but a simple example would have null represent a known empty value and undefined represent an unknown value.


  • FoxDev

    @VaelynPhi said:

    This is actually correct behavior; maps over arrays skip undefined, which was part of my original motivation for wanting them preserved in JSON.

    not quite.

    [undefined].map(function(){console.log('boo')});
    [,].map(function(){console.log('boo')});
    

    one of those will pring 'boo' the other won't.

    took me bloody forever to figure out WHY (answer is upthread. has to do with the fact that one of these constructs creates a sparse array and the other doesn't)



  • @accalia said:

    not quite.

    [undefined].map(function(){console.log('boo')});
    [,].map(function(){console.log('boo')});

    one of those will pring 'boo' the other won't.

    took me bloody forever to figure out WHY (answer is upthread. has to do with the fact that one of these constructs creates a sparse array and the other doesn't)

    The array "[undefined]" has one value which is defined to be the primitive "undefined". The second array you used, "[,]" has one undefined value. So, any function over the array will generally print for the first array, but nothing for the second array (because it skips the undefined value).

    The string "undefined" isn't a keyword in JS; it's valid output, not valid input. So,

    [undefined].map(function(){ console.log("boo"); })
    

    is the same as

    var h;
    [h].map(function(){ console.log("boo"); })
    

    as far as the interpreter is concerned. Both print "boo" once and return an array with undefined as the single value (since map returned no replacement value).



  • @VaelynPhi said:

    The array "[undefined]" has one value which is defined to be the primitive "undefined". The second array you used, "[,]" has one undefined value.

    In the first case the array value is defined to be undefined. In the second case, the array value isn't undefined, because it's not defined to be undefined, it's simply undefined. Defined undefined is not the same thing as undefined undefined. It seems perfectly straightforward, although I would avoid trying to write code which behaves differently depending on whether the undefined in question is in fact undefined or not. Fortunately [,] seems to be the only way that undefined undefined can creep into your program...



  • @tar said:

    Fortunately [,] seems to be the only way that undefined undefined can creep into your program...

    > var thingNotDefined;
    undefined
    > console.log(thingNotDefined);
    undefined
    undefined


  • Defined undefined:

    C:\>node
    > var a;
    undefined
    > a
    undefined
    > b = [a];
    [ undefined ]
    > b.forEach(function(x) { console.log("** " + x); })
    ** undefined
    undefined
    

  • FoxDev

    is there a badge i can nominate you for? because that's not pedantry but it is so epic that it makes me dizzy...... it deserves an award.



  • @VaelynPhi said:

    The annoyance was the silent conversion of "undefined" to "null", which undefined is not, because null is an actual value, whereas undefined is the absence of a value (not the absence of a key)

    null was invented to be a way to represent nothing. It's a JavaScript quirk that undefined is a thing. The fact that JSON only has one representation for nothing is perfectly sane. That's exactly what I claimed your original complaint was - asking JSON to distinguish between undefined and null. It's also unreasonable to suggest that JSON is deficient if it doesn't support sparse arrays.


  • FoxDev

    you want a sparse array? serialize an object with keys: '0',, '1', '4', '42', etc.

    bam! sparse array!



  • @accalia said:

    you want a sparse array? serialize an object with keys: '0',, '1', '4', '42', etc.

    bam! sparse array!

    Ummmm.... no

    a = [];
    a['0'] = 'Zero';
    a['1'] = 'One';
    a['4'] = 'Four';
    a['42'] = 'Fourty Two';
    alert(JSON.stringify(a));
    // Result: ["Zero","One",null,null,"Four",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"Fourty Two"]
    

    A sparse array doesn't serialize as sparse. An "object with keys '0',, '1', '4', '42'" does this:

    b = {};
    b['0'] = 'Zero';
    b['1'] = 'One';
    b['4'] = 'Four';
    b['42'] = 'Fourty Two';
    
    alert(JSON.stringify(b));
    //Result: {"0":"Zero","1":"One","4":"Four","42":"Fourty Two"}
    

    This serializes as an object, not an array.



  • @Jaime said:

    Fourty

    Eek.


  • FoxDev

    @Jaime said:

    An "object with keys '0',, '1', '4', '42'" does this:

    which is what i said to create.

    i'm aware of what it serializes as. but you cn treat an object with numeric keys like a sparse array if what you want is a sparse array.



  • @accalia said:

    i'm aware of what it serializes as. but you cn treat an object with numeric keys like a sparse array if what you want is a sparse array.

    But, I said "you can't serialize a sparse array" to which you responded "serialize an object with ...". Regardless, you still can't serialize a sparse array. Sure you can do something else that might meet the same functional needs, but that doesn't change the fact that you cannot serialize a sparse array.


  • FoxDev

    ok. so riddle me this:

    what exactly is the functional difference between a sparse array and an object with numeric keys?

    i'd love to hear of even one functional difference.

    filed under: Functional != Syntactical



  • @accalia said:

    i'd love to hear of even one functional difference.

    Hey, I already said it meets the same functional needs. I was @VaelynPhi who needed the array to deserialize exactly as it was before serialization. My answer is you can't, and I'm OK with that. You're not going to get an argument from me; I think what JSON does is just fine.

    Yet, the answer is still "You can't JSON serialize a sparse array and expect it to deserialize as a sparse array on the other end".


  • 🚽 Regular

    @accalia said:

    what exactly is the functional difference between a sparse array and an object with numeric keys?

    .length


  • FoxDev

    ...

    :frystare:

    not sure if trolling or serious


  • 🚽 Regular

    Serious, but it's quite possible I whooshed and am talking about something else. It's late and I'm sleepy.



  • @VaelynPhi said:

    maps over arrays skip undefined

    No they don't. They skip missing array entries. As you pointed out in the very post that this quote comes from, it's perfectly possible to create an array entry with an undefined value, and this is not the same thing as failing to create an entry at all.

    The confusion stems from Javascript's inheritance of the general OO-language penchant for making object assignments actually assign object references without syntactic clues that this is what's actually going on. This would never have been allowed in a respectable language like C. Even VB gets this right, by requiring the set keyword to do object assignment.

    Get off my lawn. I have onions to tie to my belt, and you're not helping.


  • Discourse touched me in a no-no place

    @Jaime said:

    It's a JavaScript quirk that undefined is a thing.

    Where would the JS undefined come in a sane type logic? Nulls are relatively straight forward; they map to either ⊥ or some sort of option type.



  • @tar said:

    Fortunately [,] seems to be the only way that undefined undefined can creep into your program...

    var a = [];
    a.length = 1;
    


  • @flabdablet said:

    Even VB gets this right, by requiring the set keyword to do object assignment.

    They stopped that last century.

    I don't see a problem with = doing a reference assignment.


  • FoxDev

    @flabdablet said:

    The confusion stems from Javascript's inheritance of the general OO-language penchant for making object assignments actually assign object references without syntactic clues that this is what's actually going on. This would never have been allowed in a respectable language like C.

    A language famous for having no OO support whatsoever 😆
    BTW, every OO language* defaults to reference assignment for objects; if you want to value-copy, you need a deep-clone method (in .NET you'd implement ICloneable, though even MS says not to do so :wtf:).

    *INB4 someone mentions an OO language I've never heard of or used


  • Discourse touched me in a no-no place

    @RaceProUK said:

    BTW, every OO language* defaults to reference assignment for objects; if you want to value-copy, you need a deep-clone method (in .NET you'd implement ICloneable, though even MS says not to do so ).

    *INB4 someone mentions an OO language I've never heard of or used

    What, INB4 C++?


  • FoxDev

    Oh yeah… forgot about that…



  • @tar said:

    Defined undefined:

    I think you're getting a type, a value, and an assignment confused. This could probably be fixed in JS by reserving undefined and removing the global property (unless someone can point me to a use for the global property?).

    @Jaime said:

    null was invented to be a way to represent nothing. It's a JavaScript quirk that undefined is a thing. The fact that JSON only has one representation for nothing is perfectly sane. That's exactly what I claimed your original complaint was - asking JSON to distinguish between undefined and null. It's also unreasonable to suggest that JSON is deficient if it doesn't support sparse arrays.

    You can continue to misrepresent what I said all you want, but that was still not my argument. Even so, JSON is deficient by virtue of its own name: even if it did support sparse arrays, it would still not actually represent Javascript objects properly. But again, it's the silent failure that's bothersome. Since JSON.parse throws errors like a pedantic Donkey Kong, it would be reasonable to expect JSON.stringify to do the same with values it can't properly serialize.

    I love JSON above and beyond any other textual data exchange format (perhaps this is driven by my hate of XML somewhat), but it is severely lacking in many ways and ought to be expanded a little to accommodate its current usage.

    @accalia said:

    i'm aware of what it serializes as. but you cn treat an object with numeric keys like a sparse array if what you want is a sparse array.

    But, as I said much earlier in this thread, which has no doubt been lost in the sands of time, array functions do not behave correctly on such objects, and part of the point of what I was doing was to have arrays correctly communicated between two endpoints without having to modify the middleware or introduce any novel quirks into the serializer and deserializer.

    @accalia said:

    i'd love to hear of even one functional difference.

    Array functions.

    @flabdablet said:

    No they don't. They skip missing array entries. As you pointed out in the very post that this quote comes from, it's perfectly possible to create an array entry with an undefined value, and this is not the same thing as failing to create an entry at all.

    "var a = [undefined];" does not, despite its looks, contain an undefined entry. It contains a defined entry with undefined type. There is a difference. Part of the confusion comes from the fact that the type of a variable which has not been defined is "undefined", which leads to some semantic confusion since programmers are used to things being absolutely different unless they were created with the same process. The symbol "undefined" is defined as having type "undefined"--if you start the JS interpreter, the global property "undefined" has been defined.

    If it helps, you can say that arrays like [,,,] contain unassigned values (just as arrays whose values have been deleted).

    Perhaps this will make some sense of things:

    > a=[undefined]
    [ undefined ]
    > var h
    undefined
    > b=[h]
    [ undefined ]
    > c=[,]
    [  ]
    > u.inspect(a,{depth:null,showHidden:true})
    '[ undefined, [length]: 1 ]'
    > u.inspect(b,{depth:null,showHidden:true})
    '[ undefined, [length]: 1 ]'
    > u.inspect(c,{depth:null,showHidden:true})
    '[ , [length]: 1 ]'
    

    @flabdablet said:

    The confusion stems from Javascript's inheritance of the general OO-language penchant for making object assignments actually assign object references without syntactic clues that this is what's actually going on. This would never have been allowed in a respectable language like C. Even VB gets this right, by requiring the set keyword to do object assignment.

    Perhaps you could explain how this would even help?



  • @RaceProUK said:

    A language famous for having no OO support whatsoever

    Yes, as I said: a respectable language.


  • Discourse touched me in a no-no place

    @VaelynPhi said:

    ought to be expanded a little to accommodate its current usage.

    Seriously, alterations to a data serialization language is a Really Bad Idea, because it screws over lots of implementations all over the place (the world is not all frigging Javascript, not even close). Now that it is nailed down by standardPDF, let there be no changes at all to it. If the JS people had wanted something else, they should have standardized something else.



  • @dkf said:

    Seriously, alterations to a data serialization language is a Really Bad Idea, because it screws over lots of implementations all over the place (the world is not all frigging Javascript, not even close). Now that it is nailed down by standardPDF, let there be no changes at all to it. If the JS people had wanted something else, they should have standardized something else.

    I understand the reticence, and you may just be completely right, but I don't see why a superset couldn't accommodate current usage while allowing new behavior. One could even simply add two new functions to the JSON object (serialize and deserialize) that work alongside stringify and parse, but do not replace them.



  • @VaelynPhi said:

    One could even simply add two new functions to the JSON object (serialize and deserialize) that work alongside stringify and parse, but do not replace them.

    How would that be better than simply creating another serialization library that does what you want? Douglas Crockford's JSON parser is about 200 lines of actual code in a single 500 line file; fork it and add the features you want. No one else wants the features you do, so you will have to do this yourself.

    JSON was invented long before node.js, so it was never envisioned that there would be JavaScript on both ends. It's a very minimalistic serialization format designed for data interchange between languages. Bluntly, it's the wrong format for what you are doing.


  • FoxDev

    @VaelynPhi said:

    One could even simply add two new functions to the JSON object (serialize and deserialize) that work alongside stringify and parse, but do not replace them.

    In every implementation of JSON in every language it had been ported to, and managing communication between versions of JSON?

    No i an with @dkf here. Do not want.

    Invent a different serialization standard if you need that (like YAML did) but don't wedge that into JSON


  • FoxDev

    @accalia said:

    but don't weeks l wedge that into JSON

    Parse Error

    Seriously, I can't figure out what you meant to type/Swype there…


  • FoxDev

    s/weeks i//

    Looks like i hit i instead of backspace.



  • @VaelynPhi said:

    Perhaps you could explain

    Sure, I'll have a crack.

    The assignment of object references is baked so deep into most OO languages and the worldview of most people who use them that asking people to think about them is like asking fish to notice water; it generally doesn't happen.

    But if you've got a sparse array implementation that is really nothing more than a hashmap implementation with a few extra frills bolted on, it becomes kind of important.

    Think about what the interpreter is actually doing when you ask it for

    var blarg;
    var a = [17, undefined, blarg,, "yow", {"foo": "bar"}];

    It creates a new object prototyped from Array, makes the value of a a reference to it*, and starts filling it in. The first index implied by the array literal is 0; there's a numeric primitive value there, so the first thing added to the underlying hashmap is a key-value pair: the key is "0" and the value is the primitive value 17.

    The next index implied by the array literal is 1 because of the comma following the 17; this generates another key-value pair and adds it to the hashmap: key is "1", value is an object reference to the global object undefined.

    Next is key "2", with the value being an object reference to the variable blarg.

    Now there are two successive commas, so the next key-value pair to be built gets key "4" and value "yow".

    Finally, the last key-value pair gets key "5" and an object reference to a new object which itself contains the single key-value pair "foo" -> "bar".

    The implied trailing comma bumps the implied index to 6, so another key-value pair gets added with key "length" and value 6.

    Now, any attempt to read a[1] or a[2] or a[3] or a[99] will result in the value undefined.

    In the case of a[1] or a[2], this is not because keys "1" or "2" are missing from the hashmap. They're there; it's just that the values associated with those keys are object references, and the objects they reference evaluate to undefined because they've never had a value assigned to them.

    This is the same kind of behavior you get from

    var foo;
    var bar = foo;

    Both foo and bar will return undefined when read, because what's actually stored in those variables are references to objects (actually the same object, brought into existence via var foo;) which have not themselves ever been given a value.

    In the case of a[3] or a[99] you will still see read attempts return undefined. However in this case it is because they requested keys don't exist. There is no key-value pair in a with a key of "3" or "99".

    This is just like trying to read the value of blort when no var blort; statement is in scope: the current global object simply doesn't have a key-value pair with a key of "blort".

    And because array items a[1] and a[2] have actually been created - they're key-value pairs with keys of "1" and "2" and values of object references - they get included when you do a foreach on a.

    My point is that if you're vague about the distinction between object references and other kinds of values, it's hard to see the difference between the cases of a[1] and a[2] vs. a[3] and a[99].

    Personally I don't like the value undefined. If Javascript were to return the value null in all the places where it currently returns the value undefined I can't see how it would be less useful.

    *actually done by creating a key-value pair in the current global object with key "a" and a reference to the new object as the value.


  • Discourse touched me in a no-no place

    @flabdablet said:

    Personally I don't like the value undefined.

    It would be OK if it was equivalent to ⊤, but it is more like ⊥, which is what null is, and that means that JS has two things that are like ⊥ at the same time. :wtf: I'd be much happier if it had neither and just said that value absence was value absence, but I think that would scare quite a few horses in the JS community.



  • @dkf said:

    It would be OK if it was equivalent to ⊤, but it is more like ⊥

    Not familiar with the ⊤ ⊥ terminology; link a reference?



  • Seriously though, this wtfjs blog is a gift which just keeps on giving...

    > ",,,"==Array(4)
    true
    
    > 1+-+-+-+-+-+-+1
    2
    
    > (!+[]+[]+![]).length
    9
    
    > "3 is a " + typeof + ".";
    '3 is a number'
    
    > Z='constructor';
    'constructor'
    > Z[Z][Z][Z]('console.log("wtf?")')();
    wtf?
    undefined
    
    > ![[]][![]]
    true
    > [![]][+[]]
    false
    > [+[]][+[]]
    0
    > [+[]][![]]
    undefined
    > ![]+[]
    'false'
    > ![]+[][+[]]
    NaN
    > (![]+[])[+[]]
    'f'
    
    > var foo=[0]
    undefined
    > foo==foo
    true
    > foo==!foo
    true
    
    > [1,2,3] < [1,2,3]
    false
    > [1,2,3] > [1,2,3]
    false
    > [1,2,3] <= [1,2,3]
    true
    > [1,2,3] >= [1,2,3]
    true
    > [1,2,3] == [1,2,3]
    false
    > [1,2,3] === [1,2,3]
    false
    

    Thanks to this blog, I feel like I have a much stronger grip of Javascript now!



  • And what happens if the global var is declared with "var" ?
    <div id=global3></div>
    
    <script>
      global3.innerHTML = "global3";    // --> Uncaught TypeError: Cannot set property 'innerHTML' of undefined (wtf...)
      console.log(global3);             // --> undefined (wtf?)
      var global3 = 1;                  // --> this breaks the two lines above (wtf!)
      console.log(global3);             // --> 1
    </script>
    

    WAT.

    Moral: Javascript is not C, and is not Java, and variables are in scope for the whole function enclosing their declarations and not just from the point of declaration onward.

    Initiailization happens exactly where the var statement is, but the variable declared by that same statement is in scope all the way back to the start of the enclosing function.

    This is not WAT, this is RTFM.


  • Discourse touched me in a no-no place

    @flabdablet said:

    Not familiar with the ⊤ ⊥ terminology; link a reference?

    For ⊥, see:

    The equivalent for ⊤ is a bit less common as it is the containing type for all possible types, and so provides no constraints at all: this sort of captures the idea of something being undefined. It's not what JS does at all, but that's because JS was originally designed by ignorant fuckweasels.



  • @flabdablet said:

    <em>Initiailization</em> happens exactly where the <code>var</code> statement is, but the variable declared by that same statement is in scope all the way back to the start of the enclosing function.

    This is not WAT, this is RTFM.

    It seems like a bit of both to me, sure, the code is behaving as specified, but the specified behaviour is nuts.

    > (function () {
    ... console.log(a);
    ... var a = 1;
    ... console.log(a);
    ... })();
    undefined
    1
    


  • @tar said:

    the specified behaviour is nuts

    Meh.

    The first block-structured language I ever learned was Pascal, not C; Pascal has function scope rather than block scope for local variables, and all variable declarations within a given scope must occur before executable statements. C allows but does not require this pattern, as does Javascript. Consistent use of it makes scoping behave the same way in all three languages so the differences never get a chance to be surprising.

    The fact that JS declarations are hoisted to the top of their scopes rather than being illegal anywhere else allows mutually recursive functions to be declared without an explicit forward keyword or a C-like function prototype syntax, which is kind of convenient.

    I agree that hoisting surprises enough people that putting it in the language was probably a poor design choice.


  • 🚽 Regular

    @tar said:

    ```js
    1+-+-+-+-+-+-+1
    2

    
    What else would it be (If not a syntax error)?

  • 🚽 Regular

    @flabdablet said:

    This is not WAT, this is RTFM

    I'm more surprised (though not really, knowing the origins of JS) by the fact there is a de facto standard of creating implied globals from element ids.

    Filed under: FUCKING DISCOURSE WHY DID YOU BREAK PASTING ON ANDROID?


Log in to reply