Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Revert bdfc9c02 (restore [] as falsy) #10253

Closed
JakobJingleheimer opened this issue Nov 27, 2014 · 14 comments
Closed

Revert bdfc9c02 (restore [] as falsy) #10253

JakobJingleheimer opened this issue Nov 27, 2014 · 14 comments

Comments

@JakobJingleheimer
Copy link

This was an awesome feature, and the problem is with Javascript: Empty anything should be falsy. Anyone who was surprised by [] being considered falsy is at fault for not reading the documentation, which clearly stated this behaviour.

Updating existing projects to compensate for the breaking change introduced by bdfc9c0 is no simple task, even just finding where it will break will be very labour-intensive, just for the dev to restore this functionality anyway.

@pkozlowski-opensource
Copy link
Member

I don't think it makes sense to revert bdfc9c0 as with it things like 'no' were considered falsy which was really surprising.

Now, speaking of [] - I would expect it to be truthy as it is in JS. More generally - I really do think that we should follow what JS do in this respect.

@JakobJingleheimer
Copy link
Author

Strings like 'no' should not be falsy because 'no' is an actual word and possibly a valid value (also 'f' was a big gotcha, for which I answered a lot of questions on SO). But what is the use of an empty array or empty object? (empty object was never falsy in angular, but I'd like it to be) Data types should be persistent; ex I call GET example.com/collection/index?type=foo; ordinarily /collection returns an array, but there are no items in the collection of type foo, so it should return an empty array. The status of the call is success because nothing technically went wrong; but effectively I have nothing to work with from the response: Say I'm going to add some headings and run an ngRepeat

<table ng-show="collection">
  <thead>
    <th>Bar</th>
    <th>Qux</th>
  </thead>
  <tbody>
    <tr ng-repeat="item in collection">
      <td>{{ item.name }}</td>
      <td>{{ item.something }}</td>
    </tr>
</table>

In the above, there is absolutely no value when collection is empty, and it will be detrimental to show the headings with no rows (the table will look broken). With the new way, I have to do an extra step (ng-show="collection.length") to get the desired behaviour, when it's already the only use-case.

It would be nice if Javascript considered anything empty to be falsy, but we can't change Javascript as easily as Angular (also that would probably break the hell out of a lot of stuff if JS suddenly started to consider [] falsy).

@pkozlowski-opensource
Copy link
Member

@jshado1 I'm sure that others can come up with other arguments to not make [] falsy (ex.: #3969 (comment)). We could argue for long but the real question is this: do we want to invent special rules or stick to the ones from JS?. Every time AngularJS expressions behave differently, as compared to JS, it requires explanation, documentation etc.

I don't see the bdfc9c0 frankly as it would force people to once again through the braking changes. For sure we can't do this in 1.3 and I would be against doing this in 1.4, but let's see what others got to say.

@JakobJingleheimer
Copy link
Author

In the case of the referenced comment, I would expect the parser to compensate. ![] should be true (like how !null is natively true).

@caitp
Copy link
Contributor

caitp commented Nov 27, 2014

it might seem weird, but I feel like javascript semantics are basically the default language that most developers speak, so it's really unexpected if we do something "different", and treat non-(JS)-falsy values as falsy.

While it is arguably a weird thing in javascript, it's sort of the same in all of the languages javascript has inherited from, for instance:

  int* array = new int[0];
  if (array) {
    std::cout << "Array is NOT falsy" << std::endl;
  } else {
    std::cout << "Array is falsy" << std::endl;
  }
  array[0] = 1; // SIGSEGV

will allocate an array of integers (of length 0), and print the non-falsy string. While it's true that the collection is empty, testing if the collection is truthy or not is basically testing if the collection itself exists at all.

I don't think we want to re-break this, it's less confusing this way.

@JakobJingleheimer
Copy link
Author

@caitp A falsy check does not check if something exists, it checks if it's equivalent to junk.

@caitp
Copy link
Contributor

caitp commented Nov 27, 2014

not junk, "falsy", like "null", "nil", "void 0", "undefined", "false", "0" --- these aren't gunk, but they're "zero-ish" (read: values which would be represented as, or coalesced to, a 0) values. (A reference to a valid object is not a zero-ish value)

@JakobJingleheimer
Copy link
Author

A truthy/falsy check is for making a vague determination. If you want to know something specific, don't use a vague test.

@caitp
Copy link
Contributor

caitp commented Nov 27, 2014

It's a pretty specific determination, because falsy means something pretty specific =) What you're asking for is for us to interpret something non-falsy as falsy, and I don't think that we want to do that, for the simple reason that it confuses the heck out of people (as it did before the referenced sha was landed).

@JakobJingleheimer
Copy link
Author

foo === false is specific. foo is exactly equal to false and nothing else.
foo == false is vague. foo is equal any of the following: null, '', false, 0 (or, hopefully, [])

@pkozlowski-opensource
Copy link
Member

@jshado1 once again, i think that we could argue here for long if [] and {} should be truthy or not but for me this is a wrong question. Imo we should decide if angularjs expressions should have different truthy / falsy semantic as compared to js. I simply see no reason of diverging here, i'm afraid...

@JakobJingleheimer
Copy link
Author

My reasoning is that you had already diverged; you have the people who were originally confused using older version, plus now people who already understood the original functionality and are now confused by (arguably useful) functionality suddenly being broken.

Also, the people confused by the original functionality are currently working on that piece, so it's easier to isolate where the "problem" is; whereas something having to go back and change a bunch of stuff depending on that problem have to find all the instances.

@lgalfaso
Copy link
Contributor

Hi @jshado1 many developers found the original behavior extremely confusing as they expect that expressions follow javascript logic, and we realize that the original behavior was a mistake. I am sorry that this change is causing you some pain, but bdfc9c0 is not going to be reverted as we believe that the current behavior is the right behavior

@JakobJingleheimer
Copy link
Author

If you were dead-set on this (breaking) change, v2 would have been a better time to introduce because that version will already introduce breaking changes :/

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants