Skip to content

Instantly share code, notes, and snippets.

@omar-3
Last active April 10, 2020 06:45
Show Gist options
  • Save omar-3/95dcc3c719bcdba8864127e26a8537f1 to your computer and use it in GitHub Desktop.
Save omar-3/95dcc3c719bcdba8864127e26a8537f1 to your computer and use it in GitHub Desktop.
a very very short itertools-ish module
/* Support for functional programming capabilities in Chapel
Provides a different number of generators and iterators inspired
by Python, and other functional programming languages: APL, Haskell, Scala.
*/
module functional {
/* iterator that produces an evenly spaced values
starting with *start* and ends at *end*
with *step* spaces inclusively. Has the same functionality
as ranges.
:arg start: starting point of the iterator
:type start: int
:arg end: ending point of the iterator
:type end: int
:arg step: the space between every two conscutive value
:type step: int
*/
iter count(start: int, step: int, end: int) {
var n = start;
while 1 {
yield n;
n = n + step;
if n == end {
return;
}
}
}
/* iterator returning the first *number* of elements in the container.
:arg list: an iterable container like a list or a string
:arg type: [] T
:arg number: number of elements to be yielded, default is 5
:arg type: int
*/
iter firstElements(list, number=5) {
var iterable = list;
var iterations = number;
for i in iterable {
iterations = iterations - 1;
yield i;
if iterations == 0 {
return;
}
}
}
/* filtering a container by the truth value of *function*
:arg list: an iterable container
:arg type: [] T
:arg function: non generic boolean function
*/
iter filter(list, function) {
var iterable = list;
for i in iterable {
if function(i) {
yield i;
}
}
}
/* trying to concatenate iterable containers with + in Chapel, does element-wise
addition. *chain* function returns an iterable container produced by chaining
all the lists passed to the function
:arg lists: all the containers to be chained together
:arg type: [] T
*/
iter chain(lists...?numOflists) {
var iterables = lists;
var num = numOflists;
for i in 1..num {
var iterable = iterables(i);
for element in iterable {
yield element;
}
}
}
/* returns elements from *list* that have corresponding Truth value
in the *truthList*
:arg list: an iterable container
:arg type: [] T
:arg truthList: an iterable container, whose elements has boolean value
:arg type: preferly [] int
*/
iter compress(list, truthList) {
var iterable = list;
var truth = truthList;
for (i,j) in zip(list, truthList) {
if j {
yield i;
}
}
}
/* drops elements from *list* as long as the predicate *function*
is false, once the predicate evaluate to true, the function returns
every element.
:arg list: an iterable container
:arg type: [] T
:arg function: non generic boolean function
*/
iter dropwhile(list, function) {
var iterable = list;
var barrier = false;
for i in iterable {
if function(i){
barrier = true;
}
if barrier {
yield i;
}
}
}
}
@ben-albrecht
Copy link

ben-albrecht commented Mar 4, 2020

@Omar659 - Implementations look reasonable. Nicely done.

  • Note the arg name list actually collides with List.list. That could become an issue if you ever use List; in your module.
  • I noticed at least 1 typo in documentation - chplspell is a nice tool to check out.
  • For many iterators, you define local copies of the arguments to modify them. That's fine, but be aware you can also use the in intent on the argument to automatically create a modifiable copy of that argument, e.g.
proc f(in x: int) {
  x += 1; // x is now a modifiable copy of the argument passed in
  return 2 * x;
}

Some directions you could go from here:

  • Write some tests
  • Add some checks to ensure that the correct types are passed to the iterator
  • Implement parallel iterators for these
  • Put these in a mason package and publish the package on the registry
  • Create some benchmark examples to compare performance of your implementations to, e.g. python implementations

@omar-3
Copy link
Author

omar-3 commented Mar 5, 2020

okay, thank you for the helpful comments.

I was thinking after that, I would start implementing the combinatorics iterators for containers. I guess this would be it for the standard python itertools module. After that, if we have time left we could extend the module to have all the functionalities of the python functional programming module: extended itertools, operator, and functools modules. Especially functools module would be a reasonable challenge for GSoC period besides documenting and refining itertools module. What do you think of that plan?

@omar-3
Copy link
Author

omar-3 commented Mar 5, 2020

  • Put these in a mason package and publish the package on the registry

That is the first thing I did, you can see the package repo from here, but I thought it would be an inconvenience to link a repo for just one file :D

@omar-3
Copy link
Author

omar-3 commented Mar 5, 2020

  • I noticed at least 1 typo in documentation - chplspell is a nice tool to check out.

The thing is that I'm in the middle of a hard semester right now, and I'm usually doing GSoC work before sleep or really early in the morning, but chplspell is a very nice tool really, simple and new I think. That's why I want to get involved in Chapel, a bit new language and there are A LOT of things to do and you see things are being built, not like python for example where things are established and their mailing list is full of things I can't relate with.

@ben-albrecht
Copy link

Especially functools module would be a reasonable challenge for GSoC period besides documenting and refining itertools module. What do you think of that plan?

I like that idea. However, I am nervous that many functools implementations will run into challenges due to the current state of Chapel FCFs and FCIs. I would suggest taking a shallow breadth-first pass over functools and try to determine what functions are possible to implement in Chapel today (this may require making some proof-of-concept implementations).

That is the first thing I did, you can see the package repo from here, but I thought it would be an inconvenience to link a repo for just one file :D

Nice! Well done. I still stand by my other suggested next steps :)

The thing is that I'm in the middle of a hard semester right now, and I'm usually doing GSoC work before sleep or really early in the morning

No worries. I understand.

That's why I want to get involved in Chapel, a bit new language and there are A LOT of things to do and you see things are being built

Yes, many things are being built from the ground up in Chapel still, so there are many unique opportunities to contribute as the language / standard library matures.

@omar-3
Copy link
Author

omar-3 commented Mar 8, 2020

  • Create some benchmark examples to compare performance of your implementations to, e.g. python implementations

is there some other way for comparing performance other than measuring the time of execution?

if I proposed doing the functional module with similar capabilities as this python library and this javascript library and this C++ library has very interesting stuff and the standard c++ algorithm library has some cool stuff not found in python libraries, would that be a bit overkill? or that is fine to have a functional programming module that goes much further than python? sorry If I was a bit naive.

I'm asking because I want to start writing the proposal and my midterms are approaching and won't be free as much soon.

As for the other tasks like testing and parallel iterators, I'm working on them, and would post them in a couple of days. I have found some issues presented in the master repository to get my hand more in Chapel.

@omar-3
Copy link
Author

omar-3 commented Mar 8, 2020

there is some work in itertools already here. I can't understand his testing method, is he just running the scripts and see if the output is the same as the file.good he has written or what?

@akshansh2000
Copy link

akshansh2000 commented Mar 8, 2020

there is some work in itertools already here. I can't understand his testing method, is he just running the scripts and see if the output is the same as the file.good he has written or what?

Hi @omar-3
Yes, I have done exactly that. Perhaps you would want to look at start_test to understand it better :)

@omar-3
Copy link
Author

omar-3 commented Mar 8, 2020

what and where is start_test :"D

@akshansh2000
Copy link

what and where is start_test :"D

Chapel TestSystem

@omar-3
Copy link
Author

omar-3 commented Mar 8, 2020

Chapel TestSystem

That is amazing, thank you.

@ben-albrecht
Copy link

@Omar659 - Mason packages can use the UnitTest testing system alternatively. UnitTest does not have a built-in mechanism for performance testing, but that shouldn't stop you from implementing them by adding timers to your tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment