Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

amap() and maybe afilter() too #9900

Open
dlangBugzillaToGithub opened this issue Mar 19, 2011 · 6 comments
Open

amap() and maybe afilter() too #9900

dlangBugzillaToGithub opened this issue Mar 19, 2011 · 6 comments

Comments

@dlangBugzillaToGithub
Copy link

bearophile_hugs reported this on 2011-03-19T17:09:37Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=5756

CC List

Description

I suggest to add to Phobos functions like amap() and maybe afilter() too.

amap() means array(map())
afilter() means array(filter())


Rationale:

- Functions like sum() are used all the time, Python programmers use it thousands of times.
- In some situations a specialized version is faster, I have shown this about sum() in an enhancement request (Andrei has then tried to generalize this suggestion of mine again);
- array(map()) uses twice the number of parentheses of amap(). Haskell syntax shows very well why too many parentheses make functional-style code needlessly harder to read.
- Experience shows me that in D you can't use lazy things as much as you use in Haskell. This means that very often I have to convert the results of D map()/filter() to true arrays.
- sum() is a semantic chunk, while reduce!q{a+b}() is not as explicit in its purpose, it's not a single chunk. You are able to speed up your coding if you need to use less chunks.
- The number of "nearly duplicated" functions to add is quite limited.

But such functions aren't orthogonal, you can build them with few other small things. In Python std library you see functions that aren't orthogonal, but they are handy, like ifilterfalse() and starmap():
http://docs.python.org/library/itertools.html

You see something similar in the Haskell Prelude (it's a standard module loaded and compiled before any other), a very well designed piece of code:
http://www.haskell.org/onlinereport/standard-prelude.html

It contains un-orthogonal functions like:

concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f


zipWith          :: (a->b->c) -> [a]->[b]->[c]
zipWith z (a:as) (b:bs)
                 =  z a b : zipWith z as bs
zipWith _ _ _    =  []


zip              :: [a] -> [b] -> [(a,b)]
zip              =  zipWith (,)


putStrLn   :: String -> IO ()
putStrLn s =  do putStr s
                 putStr "
"
  

print      :: Show a => a -> IO ()
print x    =  putStrLn (show x)
@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 2011-03-23T23:47:04Z

As in std.parallelism, I suggest to add a second optional argument to the amap()/afilter(), an optional buffer to return the result. If the buffer is provided, it must be the same length as the range.

So you write:

auto numbers = iota(10);
auto squareRoots = new double[numbers.length];
amap!sqrt(numbers, squareRoots);

Instead of:

auto numbers = iota(10);
auto squareRoots = new double[numbers.length];
copy(map!sqrt(numbers), squareRoots);

@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 2011-03-27T13:38:59Z

It seems dsimcha has renamed two functions in std.parallelism, now the eager version is named amap:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=132731

@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 2011-04-12T17:19:56Z

See also bug 5838

@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 2011-09-14T04:55:40Z

See here for better explanations:

http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=29516

@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 2011-09-29T15:06:38Z

An example of amap usage. This is input data:

auto data = ["1111100000",
             "1111000000",
             "1110000000",
             "1100001000",
             "1000010000",
             "0000100001",
             "0001000011",
             "0010000111",
             "0000001111",
             "0000011111"];

To convert it into a 2D matrix of booleans:

auto r = array(map!q{ array(map!q{ a == '1' }(a)) }(data));

The result r:
    
[[true, true, true, true, true, false, false, false, false, false], [true, true, true, ...]]

Using amap the line of code becomes shorter and less noisy, almost readable:

auto r = amap!q{ amap!q{ a == '1' }(a) }(data);

@dlangBugzillaToGithub
Copy link
Author

lt.infiltrator commented on 2014-03-19T21:21:18Z

Would you like to create a PR for this?

@LightBender LightBender removed the P4 label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants