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

Port List functions from JavaScript to Elm #152

Merged
merged 4 commits into from Feb 1, 2015

Conversation

Projects
None yet
3 participants
@jonathanhefner
Contributor

jonathanhefner commented Jan 30, 2015

This builds off of #150, so that should be merged first.

In the same spirit as #130, I ported several List API functions from JavaScript to pure Elm. Some notes:

  • I kept scanl in a separate commit because it is a tiny performance regression (1.55 -> 1.65 seconds on an old laptop for a 100k element list). The regression is due to the requisite extra reverse call.
  • I did not port sortBy in terms of sortWith because that resulted in a larger performance regression (2.5 -> 3.0 seconds on an old laptop for a 100k element list). The regression is (likely) due to the extra string comparison required by the JavaScript sortWith implementation. If we decide the performance penalty is worth it, I can port it also.
  • There are several native functions (any, drop, take, repeat) which were not converted, but could be by introducing an additional 1 or 2 native functions to drive looping. Either a function like foldlWhile that handles early termination, and / or a function like foldn (or Range.foldl) that handles counting without creating intermediary lists (i.e. without [1..n]). I can implement these in a separate experimental branch if anyone just wants to see what they would look like.
@evancz

This comment has been minimized.

Show comment
Hide comment
@evancz

evancz Feb 1, 2015

Member

This looks great, nice work!

I think the last point about any, drop, etc. is interesting. It'd be good to move more code into Elm, so I'd be curious to see what this looks like and if it has performance implications.

Member

evancz commented Feb 1, 2015

This looks great, nice work!

I think the last point about any, drop, etc. is interesting. It'd be good to move more code into Elm, so I'd be curious to see what this looks like and if it has performance implications.

evancz pushed a commit that referenced this pull request Feb 1, 2015

Merge pull request #152 from jonathanhefner/pure-elm-list-functions
 Port List functions from JavaScript to Elm

@evancz evancz merged commit c63dd04 into elm:master Feb 1, 2015

1 check passed

continuous-integration/travis-ci The Travis CI build passed
Details
@jvoigtlaender

This comment has been minimized.

Show comment
Hide comment
@jvoigtlaender

jvoigtlaender Feb 1, 2015

Contributor

Concerning the "implement some functions using native loops" aspect, there are already some candidate implementations for such loops in https://github.com/TheSeamau5/elm-loop.

Contributor

jvoigtlaender commented Feb 1, 2015

Concerning the "implement some functions using native loops" aspect, there are already some candidate implementations for such loops in https://github.com/TheSeamau5/elm-loop.

@jonathanhefner

This comment has been minimized.

Show comment
Hide comment
@jonathanhefner

jonathanhefner Feb 1, 2015

Contributor

I created three branches to show what looping could be like for any, repeat, take, and drop:

  • Using foldn
    • any cannot be implement via foldn, and thus is not ported
  • Using foldlWhile
    • repeat cannot be implemented via foldlWhile, but a safe, less-efficient, pure-Elm version is included for consideration (note the ** in the benchmark data below)
  • Using loopUntil
    • all 4 functions are possible, however the iteration logic was quite confusing to write (I say this as someone who grew up writing C, C#, and Java)

When benchmarking the branches, I first ran the combined tests for just the 4 functions on a 100k element list (that's the first column). That didn't provide a clear enough picture, so then I isolated the tests for each function (that's the remaining columns). For take and drop, there were multiple tests doing similar work, so I pared it down to just one test taking or dropping 99,999 elements from a 100k element list.

branch All 4 any repeat take n-1 drop n-1
master 3.15s 1.0s 1.4s 1.4s 1.1s
foldn 4.0s n/a 1.35s 1.65s 1.15s
foldlWhile 4.15s 1.05s 1.45s** 1.6s 1.3s
loopUntil 4.65s 1.4s 1.55s 1.65s 1.35s
Contributor

jonathanhefner commented Feb 1, 2015

I created three branches to show what looping could be like for any, repeat, take, and drop:

  • Using foldn
    • any cannot be implement via foldn, and thus is not ported
  • Using foldlWhile
    • repeat cannot be implemented via foldlWhile, but a safe, less-efficient, pure-Elm version is included for consideration (note the ** in the benchmark data below)
  • Using loopUntil
    • all 4 functions are possible, however the iteration logic was quite confusing to write (I say this as someone who grew up writing C, C#, and Java)

When benchmarking the branches, I first ran the combined tests for just the 4 functions on a 100k element list (that's the first column). That didn't provide a clear enough picture, so then I isolated the tests for each function (that's the remaining columns). For take and drop, there were multiple tests doing similar work, so I pared it down to just one test taking or dropping 99,999 elements from a 100k element list.

branch All 4 any repeat take n-1 drop n-1
master 3.15s 1.0s 1.4s 1.4s 1.1s
foldn 4.0s n/a 1.35s 1.65s 1.15s
foldlWhile 4.15s 1.05s 1.45s** 1.6s 1.3s
loopUntil 4.65s 1.4s 1.55s 1.65s 1.35s

@jonathanhefner jonathanhefner referenced this pull request Feb 8, 2015

Closed

Proposal: Generators #165

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