5 ms·
Yep. Add those and a proper type system and you have yourself a decent language. But when the creator of the language doesn't see the value in abstractions [0],
by thatswrong0 10y ago
Yep. Add those and a proper type system and you have yourself a decent language. But when the creator of the language doesn't see the value in abstractions [0], then it's probably never going to happen.
[0] https://github.com/robpike/filter https://github.com/robpike/filter
- RodgerTheGreat 10y agoHis formulation of reduce() is strikingly clumsy, both in signature and implementation. I daresay I wouldn't have much use for such a function either! Most languages which provide a reduce() permit programmers to provide an initial "carry-in" value. This is a neater and more useful way to handle the cases of a zero- or one-element list. Moreover, it lets you do more interesting things with the reduction. Consider the following, using ES6-style JavaScript to collect a set of the unique values of a list via reduce(): function unique(list) { return list.reduce(function (sofar, item) { if (!sofar.includes(item)) { sofar.push(item); } return sofar; }, []); }
- randomdata 10y agoTo be fair, even with a well designed interface, it is difficult to see the advantage of your example over using a simple for loop: func unique(list []int) (r []int) { for i := range list { if !includes(r, i) { r = append(r, i) } } return }
- RodgerTheGreat 10y agoIt was just the first example that came to mind to illustrate the general pattern. We could also make this particular example shorter by using your naming conventions and writing it in a more functional manner instead of mutating the list: function unique(list) { return list.reduce((r, i) => r.includes(i) ? r : r.concat(i), []); } Clearer? I dunno; probably depends on the reader's background and preferences.
- randomdata 10y agoI still don't see what you are gaining here. Outside of code golf, the goal should not be to try and write code as short as possible, regardless of the language you are using. But this just seems to validate Pike's assertion that a for loop is more suitable to the problem. Perhaps an example of where map/reduce is a significant improvement to the expressiveness would be appropriate for the discussion?
- XMPPwocky 10y agoI wrote an aimbot for a FPS game. The basic idea: Take all the players, and all the buildings. Filter out those that aren't enemies. Filter out those that are currently invincible. Transform that into a list of actual points in worldspace- the hitboxes for players, the AABB centers for buildings. (Not all player models have the same hitbox count.) Unless we are holding a weapon that does splash damage- then go for the feet on players (their origin). And if we hold a projectile weapon, do prediction based on the player's velocity. Now transform each point into a 2-tuple (position, score), based on some heuristics implemented in another function. Do a raycast to each point. Filter out those that can't be hit. Take the point with the highest score, if there is one, and set our viewangles to aim at it. Otherwise leave them alone. The actual implementation of this looked something like this: let target = get_players().chain(get_buildings) .filter(|e| are_enemies(me, e)) .filter(is_vulnerable) .flat_map(entity_to_scored_aimpoints) .filter(|(score, point)| trace(me_eyes_predicted, point).fraction > 0.999) .max_by(|(score, point)| score); if let Some(target) = target { aimray = target - me_eyes_predicted; viewangles = vector_to_angles(aimray); } (Note that max_by is just a special case of reduce/fold; in my experience, you rarely want to use reduce directly; there's probably a more ergonomic wrapper. Sometimes you do, though.) To me, that's pretty readable (stuff specific to the game aside, like the trace.fraction ugliness- fraction is "how far" the trace got before hitting something, 1.0 meaning there's nothing in the way. the comparison is to handle some floating-point inaccuracy there), and handles some really annoying cases properly.
- MrManatee 10y ago
- Chyzwar 10y agowell ES6 have Set, const set = new Set(list);
- codygman 10y agoPicture map, filter, and fold as for loops with annotations that restrict what they can do. This helps both the source code reader (you and I) and the source code compiler more easily understand what's going on. For the compiler this makes optimization easier. For the reader it makes reading easier after learning what these recursion primitives do. It is also less code, meaning less room for bugs.
- groovy2shoes 10y agoHoly shit. Those are the longest implementations of `map` and `reduce` I've ever seen.