ReactiveX / learnrx

A series of interactive exercises for learning Microsoft's Reactive Extensions Library for Javascript.
1.4k stars 292 forks source link

Question: Exercises 12 & 20 - Functionaly scalable or just tutorial? #128

Closed ghost closed 8 years ago

ghost commented 8 years ago

Howdy. I'm loving the interactive nature of http://reactivex.io/learnrx/. It is awesome.

However, my quasi-functional brain is having a hard time digesting the approach in exercise 12 (and consequently 20) that calls for mapping the boxarts without an index into the array.

Here is my code that is apparently offensive because it wants to do an index (My C# Linq brain says FirstOrDefault!):

return movieLists.
    map(function(ml) {
      return ml.videos.map(function(v) { 
        return {
          id: v.id, 
          title: v.title,
          boxart: v.boxarts.filter(ba => ba.width === 150 && ba.height === 200)
                           .map(ba => ba.url)
                           [0] //<< this isn't "allowed". firstOrDefault equivalent(?)

        };
      }
        );
    }).
    concatAll();

Without the indexer, this comes up with the "right" answer, in that it is an array with a single element. However, the resulting boxart element is an array and without the indexer (or FirstOrDefault) it is utterly wrong because of this.

Here is the correct answer:

return movieLists.
      map(function(movieList) {
        return movieList.videos.
          map(function(video) {
            return video.boxarts.
              filter(function(boxart) {
                return boxart.width === 150;
              }).
              map(function(boxart) {
                return {id: video.id, title: video.title, boxart: boxart.url};
              });
          }).
          concatAll();
      }).
      concatAll();

To my non-functional brain, this was extremely ugly. I can sense that perhaps this is a nested collection, and that this is possibly related to an unfolding of an abstract construct in the functional world. However, this just doesn't seem to scale to me.

Say I were to add a second array property similar to boxarts, like relatedtitles and I had some predicate to reduce it to a single value. With my approach, you would just add another line that takes the additional properties and filter+map them. How would the corresponding functional approach look?

With this question of scalability in mind, is this just an example to get the tutorial going? Or is there something a real functional guru can shed some light on this? Or should I just keep doing the exercises!? I was avoiding asking this question at exercise 12, but then the reduce exercise 20 brought me back to it. Am I asking the question too soon? If I keep watching the movie, will all be revealed and the universe will be in harmony?

I love the exercises though. This is the best functional + Rx tutorial I've seen over the past couple years.

ghost commented 8 years ago

Ah, I should have just kept doing exercises. If I had just done one more, I would have gotten to exercise 24 which uses Zip to address this issue of parallel level arrays.

I went ahead and asked for posterity's sake: For anyone else...just keep chugging.

teohhanhui commented 8 years ago

The provided answer maps boxarts instead of movies, which is counter-intuitive to the stated objective

Create a query that selects {id, title, boxart} for every video in the movieLists.

I too, like @bill-mybiz tried to do this:

return movieLists
    .map(function(movieList) {
      return movieList.videos;
    })
    .concatAll()
    .map(function(movie) {
      return {
        id: movie.id,
        title: movie.title,
        boxart: movie.boxarts
          .filter(function(boxart) {
            return boxart.width === 150 && boxart.height === 200;
          })[0].url,
      };
    });

What if there is no boxart with the required size, or no boxart at all? With the provided answer, the movie will be missing entirely...

ghost commented 8 years ago

@teohhanhui I think for the tutorial's purpose, they are just trying to convey the functional way of thinking of the problem. That being said, it is certainly an interesting point about the moving being missing entirely if there is no box art, and I wonder how a functional person would approach solving this with Rx?

teohhanhui commented 8 years ago

My point is that it seems to be the wrong way of solving this...

On Tue, 2 Feb 2016, 22:24 William Raiford notifications@github.com wrote:

@teohhanhui https://github.com/teohhanhui I think for the tutorial's purpose, they are just trying to convey the functional way of thinking of the problem. That being said, it is certainly an interesting point about the moving being missing entirely if there is no box art, and I wonder how a functional person would approach solving this with Rx?

— Reply to this email directly or view it on GitHub https://github.com/ReactiveX/learnrx/issues/128#issuecomment-178597337.

teohhanhui commented 8 years ago

I hope we can get some feedback from the creators / curators.