Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 24, 2010 Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
I have noticed an emerging idiom in my code lately: bring together n ranges, transform them to one range using a n-ary function. Currently it's achieved with:
map!((a) {return myNaryFun(a._0, a._1, ...); })(zip(range1, range2, ...));
It's a bit of a nuisanse -- rarely do my transforming functions take tuples, and there's the necessity of composing 2 higher-order ranges to render fairly common functionality. I think Zip could be further parametrized with a zipper function, so that the above code would boil down to:
zip!myNaryFun(range1, range2, ...);
Having looked at Zip's source, such change shouldn't be a big deal. Oh, and the default zipper function would be std.typecons.tuple, not to trouble those not keen on generalization.
Good?
--
Tomek
|
October 24, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tomek Sowiński | 2010/10/24 Tomek Sowiński <just@ask.me>: > I have noticed an emerging idiom in my code lately: bring together n ranges, transform them to one range using a n-ary function. Currently it's achieved with: > > map!((a) {return myNaryFun(a._0, a._1, ...); })(zip(range1, range2, ...)); > > It's a bit of a nuisanse -- rarely do my transforming functions take tuples, and there's the necessity of composing 2 higher-order ranges to render fairly common functionality. I think Zip could be further parametrized with a zipper function, so that the above code would boil down to: > > zip!myNaryFun(range1, range2, ...); > > Having looked at Zip's source, such change shouldn't be a big deal. Oh, and the default zipper function would be std.typecons.tuple, not to trouble those not keen on generalization. That's what Haskell calls ZipWith. I called it tmap (as in tuple-map) when I needed it in D. IMHO, it should be a generalization of std.algorithm.map: let it accept n ranges and a n-ary function. It can even do a partial check at compile-time. Extending filter() and reduce() to work with n ranges in parallel and a n-args function is also useful. you may be interested in looking there: http://www.dsource.org/projects/dranges/ (more specifically, in the algorithm module) Philippe |
October 24, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tomek Sowiński | Tomek S.: > map!((a) {return myNaryFun(a._0, a._1, ...); })(zip(range1, range2, ...)); Currently the docs of std.algorithm.map say: >Multiple functions can be passed to map. In that case, the element type of map is a tuple containing one element for each function.< But lot of time ago I have said that in my opinion that's not the best design. Python has a different design, its map does what you want, you may write your code in Python as: map(myNaryFun, range1, range2, ...) An example (Python 2.6): >>> a = ["a", "b", "c", "d"] >>> b = [1, 2, 3, 4] >>> map(lambda c,n: c * n, a, b) ['a', 'bb', 'ccc', 'dddd'] Is is possible to change the std.algorithm.map to a semantics similar to the Python one, that I think is more useful? Bye, bearophile |
October 24, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sun, 24 Oct 2010 21:39:24 +0200, bearophile <bearophileHUGS@lycos.com> wrote: > Tomek S.: > >> map!((a) {return myNaryFun(a._0, a._1, ...); })(zip(range1, range2, ...)); > > Currently the docs of std.algorithm.map say: > >> Multiple functions can be passed to map. In that case, the element type of map is a tuple containing one element for each function.< > > But lot of time ago I have said that in my opinion that's not the best design. Python has a different design, its map does what you want, you may write your code in Python as: > > map(myNaryFun, range1, range2, ...) > > An example (Python 2.6): > >>>> a = ["a", "b", "c", "d"] >>>> b = [1, 2, 3, 4] >>>> map(lambda c,n: c * n, a, b) > ['a', 'bb', 'ccc', 'dddd'] > > Is is possible to change the std.algorithm.map to a semantics similar to the Python one, that I think is more useful? From what I can see, map currently simply doesn't support passing it multiple ranges. It would be a trivial change to let it support multiple ranges in addition to multiple functions. -- Simen |
October 24, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | Dnia 24-10-2010 o 21:34:54 Philippe Sigaud <philippe.sigaud@gmail.com> napisał(a): > That's what Haskell calls ZipWith. I called it tmap (as in tuple-map) > when I needed it in D. > IMHO, it should be a generalization of std.algorithm.map: let it > accept n ranges and a n-ary function. It can even do a partial check > at compile-time. It could be. As long as the job gets done it doesn't matter what will be generalized, Map or Zip. One will cover other's functionality entirely. > Extending filter() and reduce() to work with n ranges in parallel and > a n-args function is also useful. > you may be interested in looking there: > http://www.dsource.org/projects/dranges/ > (more specifically, in the algorithm module) Nice lib. Any plans to incorporate some of it to Phobos? -- Tomek |
October 24, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen kjaeraas | Simen kjaeraas:
> From what I can see, map currently simply doesn't support passing it
> multiple ranges. It would be a trivial change to let it support multiple
> ranges in addition to multiple functions.
If you may have multiple of both then the situation becomes complex. So I think that single function - multiple ranges is simpler & better than that :-)
Bye,
bearophile
|
October 25, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen kjaeraas | On 10/24/10 14:55 CDT, Simen kjaeraas wrote:
> On Sun, 24 Oct 2010 21:39:24 +0200, bearophile
> <bearophileHUGS@lycos.com> wrote:
>
>> Tomek S.:
>>
>>> map!((a) {return myNaryFun(a._0, a._1, ...); })(zip(range1, range2,
>>> ...));
>>
>> Currently the docs of std.algorithm.map say:
>>
>>> Multiple functions can be passed to map. In that case, the element
>>> type of map is a tuple containing one element for each function.<
>>
>> But lot of time ago I have said that in my opinion that's not the best
>> design. Python has a different design, its map does what you want, you
>> may write your code in Python as:
>>
>> map(myNaryFun, range1, range2, ...)
>>
>> An example (Python 2.6):
>>
>>>>> a = ["a", "b", "c", "d"]
>>>>> b = [1, 2, 3, 4]
>>>>> map(lambda c,n: c * n, a, b)
>> ['a', 'bb', 'ccc', 'dddd']
>>
>> Is is possible to change the std.algorithm.map to a semantics similar
>> to the Python one, that I think is more useful?
>
> From what I can see, map currently simply doesn't support passing it
> multiple ranges. It would be a trivial change to let it support multiple
> ranges in addition to multiple functions.
This is coming full circle. At a point, map _did_ support multiple ranges. Some people found that non-modular - if you want multiple ranges, you should use map with zip...
Andrei
|
October 25, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Oct 25, 10 14:04, Andrei Alexandrescu wrote: > This is coming full circle. At a point, map _did_ support multiple > ranges. Some people found that non-modular - if you want multiple > ranges, you should use map with zip... Except that at "that point"[1], map's multi-range support is equivalent to map!(func)(r1, r2, r3...) == map!(func)(chain(r1, r2, r3...)) which is hardly useful. OTOH zipWithN is a very useful higher-order function. [1]: http://web.archive.org/web/20080417051734/www.digitalmars.com/d/2.0/phobos/std_algorithm.html#map |
October 25, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to KennyTM~ | On 10/25/10 1:42 CDT, KennyTM~ wrote:
> On Oct 25, 10 14:04, Andrei Alexandrescu wrote:
>> This is coming full circle. At a point, map _did_ support multiple
>> ranges. Some people found that non-modular - if you want multiple
>> ranges, you should use map with zip...
>
> Except that at "that point"[1], map's multi-range support is equivalent to
>
> map!(func)(r1, r2, r3...) == map!(func)(chain(r1, r2, r3...))
>
> which is hardly useful. OTOH zipWithN is a very useful higher-order
> function.
>
> [1]:
> http://web.archive.org/web/20080417051734/www.digitalmars.com/d/2.0/phobos/std_algorithm.html#map
Oh, you're right. Sorry!
Andrei
|
October 25, 2010 Re: Improving std.range.Zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to KennyTM~ | Dnia 25-10-2010 o 08:42:31 KennyTM~ <kennytm@gmail.com> napisał(a): > On Oct 25, 10 14:04, Andrei Alexandrescu wrote: >> This is coming full circle. At a point, map _did_ support multiple >> ranges. Some people found that non-modular - if you want multiple >> ranges, you should use map with zip... > > Except that at "that point"[1], map's multi-range support is equivalent to > > map!(func)(r1, r2, r3...) == map!(func)(chain(r1, r2, r3...)) > > which is hardly useful. OTOH zipWithN is a very useful higher-order function. > > [1]: http://web.archive.org/web/20080417051734/www.digitalmars.com/d/2.0/phobos/std_algorithm.html#map You're right. Still, modularity is a valid point. Thinking about it, this can be a good exercise in static inheritance -- make Zip the base taking care of multi-range traversal (stopping policy, etc) and the "derived" ranges (Map, Filter, Reduce) would only implement element accessors, transformation, and so on. -- Tomek |
Copyright © 1999-2021 by the D Language Foundation