Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #24448 > unrolled thread

ANN: Ramda, a new functional programming library

Started byScott Sauyet <scott.sauyet@gmail.com>
First post2014-05-27 20:13 -0700
Last post2016-03-07 10:50 +0100
Articles 20 on this page of 34 — 7 participants

Back to article view | Back to comp.lang.javascript


Contents

  ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-27 20:13 -0700
    Re: ANN: Ramda, a new functional programming library John C <rescattered@gmail.com> - 2014-05-27 21:00 -0700
      Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-28 04:37 -0700
    Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-28 04:36 -0700
    Re: ANN: Ramda, a new functional programming library "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2014-05-28 08:49 -0700
      Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-28 15:59 -0700
        Re: ANN: Ramda, a new functional programming library "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2014-05-28 16:15 -0700
          Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-28 17:05 -0700
            Re: ANN: Ramda, a new functional programming library Christoph Michael Becker <cmbecker69@arcor.de> - 2014-05-30 14:53 +0200
              Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-30 11:14 -0700
    Re: ANN: Ramda, a new functional programming library Dr J R Stockton <reply1400@merlyn.demon.co.uk.invalid> - 2014-05-29 19:40 +0100
      Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-29 17:55 -0700
        Re: ANN: Ramda, a new functional programming library Christoph Michael Becker <cmbecker69@arcor.de> - 2014-05-30 14:05 +0200
          Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-30 11:10 -0700
    Re: ANN: Ramda, a new functional programming library John C <rescattered@gmail.com> - 2014-05-30 06:25 -0700
      Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-30 11:23 -0700
        Re: ANN: Ramda, a new functional programming library John C <rescattered@gmail.com> - 2014-05-30 12:44 -0700
          Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-30 13:39 -0700
            Re: ANN: Ramda, a new functional programming library John C <rescattered@gmail.com> - 2014-05-30 19:17 -0700
              Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-05-31 09:52 -0700
                Re: ANN: Ramda, a new functional programming library Christoph Michael Becker <cmbecker69@arcor.de> - 2014-05-31 22:24 +0200
                  Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-06-01 06:55 -0700
        Re: ANN: Ramda, a new functional programming library Christoph Michael Becker <cmbecker69@arcor.de> - 2014-05-31 21:00 +0200
          Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-06-01 06:54 -0700
    Re: ANN: Ramda, a new functional programming library Dr J R Stockton <reply1400@merlyn.demon.co.uk.invalid> - 2014-06-01 19:05 +0100
      Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-06-01 19:28 -0700
        Re: ANN: Ramda, a new functional programming library Dr J R Stockton <reply1400@merlyn.demon.co.uk.invalid> - 2014-06-03 22:01 +0100
          Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-06-03 19:15 -0700
            Re: ANN: Ramda, a new functional programming library Dr J R Stockton <reply1400@merlyn.demon.co.uk.invalid> - 2014-06-05 23:41 +0100
              Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2014-06-06 11:36 -0700
            Re: ANN: Ramda, a new functional programming library Dr J R Stockton <reply1400@merlyn.demon.co.uk.invalid> - 2014-06-07 23:13 +0100
    Re: ANN: Ramda, a new functional programming library billyroberts111@gmail.com - 2016-03-06 10:22 -0800
      Re: ANN: Ramda, a new functional programming library Scott Sauyet <scott.sauyet@gmail.com> - 2016-03-06 17:52 -0800
        Re: ANN: Ramda, a new functional programming library "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2016-03-07 10:50 +0100

Page 1 of 2  [1] 2  Next page →


#24448 — ANN: Ramda, a new functional programming library

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-27 20:13 -0700
SubjectANN: Ramda, a new functional programming library
Message-ID<da2909bd-58cc-4183-8b3c-167039985491@googlegroups.com>
I've been away from this group a while, and probably will not be 
around for long this time, as I'm pretty buried in several projects 
that haven't left me much spare time.  But I wanted to announce my 
current project.  I'll check in regularly for a while to read responses.

I'm looking for feedback on a new functional programming library for 
Javascript that I've been developing with a friend.  This may seem 
very familiar to those who saw a similar request a year ago.  That was 
for a different library, which turned out to be more of academic 
interest.  This one was originally based on that project, eweda, but 
with a more practical bent.

The library is called "ramda", which is just a silly pun on "lambda".

My co-author has just published a brief introduction at

    <http://buzzdecafe.github.io/code/2014/05/16/introducing-ramda/>

The project is on Github, at 

    <https://github.com/CrossEye/ramda> 

and the library is (temporarily, at least) in a single source file: 

    <https://github.com/CrossEye/ramda/blob/master/ramda.js> 

You can install it for a Node.js project with

    npm install ramda

------------------------------ 

The API has a sizable overlap with Underscore [1] and LoDash [2].  But 
its motivations are closer to allong.es [3] or Lemonad [4] or 
Functional Javascript [5].  It's an attempt to do in Javascript 
something more akin to normal functional programming, as would be 
found in Haskell, ML, Scheme, or LISP. 

The library's functions are available as properties on the main 
object, `ramda`: 

    var square = function(x) {return x * x;}; 
    var nbrs = ramda.range(1, 5); // => [1, 2, 3, 4] 
    var squares = ramda.map(square, nbrs); // => [1, 4, 9, 16] 

But they can be attached to any object, including the global object 
via `ramda.installTo()`.  This will pollute the global namespace with 
a number of functions, but is one possible means of using the library. 
After that, you could just call 

    var squares2 = map(square, range(1, 5)); // => [1, 4, 9, 16] 

You might note something surprising here.  Even when it has the same 
functions as Underscore/LoDash, its parameter order often differs. 
This is intentional.  Underscore's API was built out of the native, 
OO- first functions on `Array.prototype` and other similar structures. 
Ramda's API, on the other hand is designed around composition and 
partial application (or currying.)  You can create new functions 
easily by not passing all the arguments to something like `map`: 

    var squareAll = map(square); 
    squareAll(range(1, 6)); // => [1, 4, 9, 16, 25] 

In all cases, functions that take one list as a parameter, have it as 
their last parameter.  And those that take one function as a parameter 
have it as their first one.  The API should be internally consistent, 
even if it's a bit different from other libraries. 

------------------------------ 

There is a fairly large set of tests (using Mocha), but they are by no 
means comprehensive, serving more as an API guide than as an 
exhaustive analysis of edge cases.  They are in the folder `tests`, 
and can be run in a modern browser at 

    <https://rawgit.com/CrossEye/ramda/master/test/index.html> 

The only documentation beyond the test suite is a Docco-annotated 
version of the source, available at 

    <https://rawgit.com/CrossEye/ramda/master/docs/ramda.html> 

------------------------------ 

The functions we include are mostly standard functional library list 
functions, ones like `map`, `foldl`, `foldr`, `filter`, `take`, 
`skip`, some object-based ones like `prop`and `func`, plain function 
manipulations like `compose`, `flip`, `memoize` and various partials, 
as well as a few arithmetic and logic functions.  There are over 100 
functions now, with some dozen aliases. (`reduce` is the same as 
`foldl`.)  

I'd love for experienced people to look at the functions and see what 
is missing, what is totally unnecessary, and what could use a better 
name or at least an alias.  In the latter category, I really would 
like to find a better name for `foldl1`, whose name was borrowed from 
Haskell.  It's the difference between a left fold with an explicit 
accumulator supplied: 

    var total = foldl(add, 0, range(1, 11)) // => 55 

and one where the first value of the (non-empty) list is taken as the 
accumulator: 

    var total2 = foldl1(add, range(1, 11)); // => 55 

With the automatic partial application of functions, there is no good 
way to allow for dynamic functions signatures, so I can't simply 
assume that `foldl` with two parameters means something different from 
`foldl` with one.  So a good name to replace `foldl1` would be very 
helpful.  Similarly, of course, for `foldr1`. 

------------------------------ 

We also have a few functions that we think are unique to Ramda.  Two 
examples are:

  - `when` is similar to functions in other libraries that accept an 
    object specification and return a predicate that can be used to 
    test additional objects.  Ramda's `when` takes more than just 
    individual values for specification, though; it can also take 
    functions:

        isTriangular = where({
          sides: 3,
          a: function(a, t) {return a < t.b + t.c;},
          b: function(b, t) {return b < t.a + t.c;},
          c: function(c, t) {return c < t.a + t.b;}
        });

        isTriangular({sides: 5}); //=> false
        isTriangular({sides: 3, a: 2, b: 1, c: 7}); //=> false
        isTriangular({sides: 3, a: 3, b: 4, c: 5}); //=> true

  - `useWith`.  We still haven't decided which of the two APIs 
    for this function we prefer, and for the moment are including     
    both.  This function combines a number of configuration functions 
    with a single gathering function and returns a new function.  When 
    the resulting function is called, the arguments are supplied, 
    respectively, to each of the configuration functions, and the 
    results of these functions are all passed to the gathering 
    function.  This allows us to define Codd's `project` (similar to 
    SQL `select`) for lists of objects with quite simple code:

        project = useWith(map, pickAll, identity); // OR (other API)
        project = use(map).over(pickAll, identity);

    This would get used like this:

        var kids = [
          {name: 'Abby', age: 7, hair: 'blond'},
          {name: 'Fred', age: 12, hair: 'brown'},
          {name: 'Rusty', age: 10, hair: 'brown'},
          {name: 'Alois', age: 15, disposition: 'surly'}
        ];
        filter(propEq("hair", "brown"), kids);
        //=> Fred and Rusty

------------------------------ 

The library has a facility for creating lazy infinite lists; we're in 
the process of pulling that out of the core and making it a separate 
extension.  In fact we want to have a bundle-building mechanism to 
allow you to create your own package, the way Modernizr and David 
Mark's MyLibrary (is that still around?) do.

But that infrastructure work has never really made it to the top of 
our list of priorities.  We've just picked up a volunteer to help with 
documentation, so soon the library might be better documented.

But we're still mostly focused on code.  And perhaps the biggest thing 
left is to implement some of the standard algebraic types, such as 
Functor, Applicative, Monoid, and Monad, as well as some standard 
objects implementing those, such as Maybe, Either, and IO.  This is 
well underway, and will probably be ready within weeks.

------------------------------ 

In any case, this is a very long post.  I'd love to hear any feedback 
you have to offer.  I'd especially love to hear suggestions about the 
API design. 

Thanks,

  -- Scott,

_____ 
[1] http://underscorejs.org/ 
[2] http://lodash.com/ 
[3] https://github.com/raganwald/allong.es 
[4] http://fogus.github.io/lemonad/ 
[5] http://osteele.com/posts/2007/07/functional-javascript 

[toc] | [next] | [standalone]


#24449

FromJohn C <rescattered@gmail.com>
Date2014-05-27 21:00 -0700
Message-ID<aff02561-f06e-412c-aa0a-06cf9088b930@googlegroups.com>
In reply to#24448
On Tuesday, May 27, 2014 11:13:11 PM UTC-4, Scott Sauyet wrote:
> I've been away from this group a while, and probably will not be 
> 
> around for long this time, as I'm pretty buried in several projects 
> 
> that haven't left me much spare time.  But I wanted to announce my 
> 
> current project.  I'll check in regularly for a while to read responses.
> 
> 
> 
> I'm looking for feedback on a new functional programming library for 
> 
> Javascript that I've been developing with a friend.  This may seem 
> 
> very familiar to those who saw a similar request a year ago.  That was 
> 
> for a different library, which turned out to be more of academic 
> 
> interest.  This one was originally based on that project, eweda, but 
> 
> with a more practical bent.
> 
> 
> 
> The library is called "ramda", which is just a silly pun on "lambda".
> 
> 
> 
> My co-author has just published a brief introduction at
> 
> 
> 
>     <http://buzzdecafe.github.io/code/2014/05/16/introducing-ramda/>
> 
> 
> 
> The project is on Github, at 
> 
> 
> 
>     <https://github.com/CrossEye/ramda> 
> 
> 
> 
> and the library is (temporarily, at least) in a single source file: 
> 
> 
> 
>     <https://github.com/CrossEye/ramda/blob/master/ramda.js> 
> 
> 
> 
> You can install it for a Node.js project with
> 
> 
> 
>     npm install ramda
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> The API has a sizable overlap with Underscore [1] and LoDash [2].  But 
> 
> its motivations are closer to allong.es [3] or Lemonad [4] or 
> 
> Functional Javascript [5].  It's an attempt to do in Javascript 
> 
> something more akin to normal functional programming, as would be 
> 
> found in Haskell, ML, Scheme, or LISP. 
> 
> 
> 
> The library's functions are available as properties on the main 
> 
> object, `ramda`: 
> 
> 
> 
>     var square = function(x) {return x * x;}; 
> 
>     var nbrs = ramda.range(1, 5); // => [1, 2, 3, 4] 
> 
>     var squares = ramda.map(square, nbrs); // => [1, 4, 9, 16] 
> 
> 
> 
> But they can be attached to any object, including the global object 
> 
> via `ramda.installTo()`.  This will pollute the global namespace with 
> 
> a number of functions, but is one possible means of using the library. 
> 
> After that, you could just call 
> 
> 
> 
>     var squares2 = map(square, range(1, 5)); // => [1, 4, 9, 16] 
> 
> 
> 
> You might note something surprising here.  Even when it has the same 
> 
> functions as Underscore/LoDash, its parameter order often differs. 
> 
> This is intentional.  Underscore's API was built out of the native, 
> 
> OO- first functions on `Array.prototype` and other similar structures. 
> 
> Ramda's API, on the other hand is designed around composition and 
> 
> partial application (or currying.)  You can create new functions 
> 
> easily by not passing all the arguments to something like `map`: 
> 
> 
> 
>     var squareAll = map(square); 
> 
>     squareAll(range(1, 6)); // => [1, 4, 9, 16, 25] 
> 
> 
> 
> In all cases, functions that take one list as a parameter, have it as 
> 
> their last parameter.  And those that take one function as a parameter 
> 
> have it as their first one.  The API should be internally consistent, 
> 
> even if it's a bit different from other libraries. 
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> There is a fairly large set of tests (using Mocha), but they are by no 
> 
> means comprehensive, serving more as an API guide than as an 
> 
> exhaustive analysis of edge cases.  They are in the folder `tests`, 
> 
> and can be run in a modern browser at 
> 
> 
> 
>     <https://rawgit.com/CrossEye/ramda/master/test/index.html> 
> 
> 
> 
> The only documentation beyond the test suite is a Docco-annotated 
> 
> version of the source, available at 
> 
> 
> 
>     <https://rawgit.com/CrossEye/ramda/master/docs/ramda.html> 
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> The functions we include are mostly standard functional library list 
> 
> functions, ones like `map`, `foldl`, `foldr`, `filter`, `take`, 
> 
> `skip`, some object-based ones like `prop`and `func`, plain function 
> 
> manipulations like `compose`, `flip`, `memoize` and various partials, 
> 
> as well as a few arithmetic and logic functions.  There are over 100 
> 
> functions now, with some dozen aliases. (`reduce` is the same as 
> 
> `foldl`.)  
> 
> 
> 
> I'd love for experienced people to look at the functions and see what 
> 
> is missing, what is totally unnecessary, and what could use a better 
> 
> name or at least an alias.  In the latter category, I really would 
> 
> like to find a better name for `foldl1`, whose name was borrowed from 
> 
> Haskell.  It's the difference between a left fold with an explicit 
> 
> accumulator supplied: 
> 
> 
> 
>     var total = foldl(add, 0, range(1, 11)) // => 55 
> 
> 
> 
> and one where the first value of the (non-empty) list is taken as the 
> 
> accumulator: 
> 
> 
> 
>     var total2 = foldl1(add, range(1, 11)); // => 55 
> 
> 
> 
> With the automatic partial application of functions, there is no good 
> 
> way to allow for dynamic functions signatures, so I can't simply 
> 
> assume that `foldl` with two parameters means something different from 
> 
> `foldl` with one.  So a good name to replace `foldl1` would be very 
> 
> helpful.  Similarly, of course, for `foldr1`. 
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> We also have a few functions that we think are unique to Ramda.  Two 
> 
> examples are:
> 
> 
> 
>   - `when` is similar to functions in other libraries that accept an 
> 
>     object specification and return a predicate that can be used to 
> 
>     test additional objects.  Ramda's `when` takes more than just 
> 
>     individual values for specification, though; it can also take 
> 
>     functions:
> 
> 
> 
>         isTriangular = where({
> 
>           sides: 3,
> 
>           a: function(a, t) {return a < t.b + t.c;},
> 
>           b: function(b, t) {return b < t.a + t.c;},
> 
>           c: function(c, t) {return c < t.a + t.b;}
> 
>         });
> 
> 
> 
>         isTriangular({sides: 5}); //=> false
> 
>         isTriangular({sides: 3, a: 2, b: 1, c: 7}); //=> false
> 
>         isTriangular({sides: 3, a: 3, b: 4, c: 5}); //=> true
> 
> 
> 
>   - `useWith`.  We still haven't decided which of the two APIs 
> 
>     for this function we prefer, and for the moment are including     
> 
>     both.  This function combines a number of configuration functions 
> 
>     with a single gathering function and returns a new function.  When 
> 
>     the resulting function is called, the arguments are supplied, 
> 
>     respectively, to each of the configuration functions, and the 
> 
>     results of these functions are all passed to the gathering 
> 
>     function.  This allows us to define Codd's `project` (similar to 
> 
>     SQL `select`) for lists of objects with quite simple code:
> 
> 
> 
>         project = useWith(map, pickAll, identity); // OR (other API)
> 
>         project = use(map).over(pickAll, identity);
> 
> 
> 
>     This would get used like this:
> 
> 
> 
>         var kids = [
> 
>           {name: 'Abby', age: 7, hair: 'blond'},
> 
>           {name: 'Fred', age: 12, hair: 'brown'},
> 
>           {name: 'Rusty', age: 10, hair: 'brown'},
> 
>           {name: 'Alois', age: 15, disposition: 'surly'}
> 
>         ];
> 
>         filter(propEq("hair", "brown"), kids);
> 
>         //=> Fred and Rusty
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> The library has a facility for creating lazy infinite lists; we're in 
> 
> the process of pulling that out of the core and making it a separate 
> 
> extension.  In fact we want to have a bundle-building mechanism to 
> 
> allow you to create your own package, the way Modernizr and David 
> 
> Mark's MyLibrary (is that still around?) do.
> 
> 
> 
> But that infrastructure work has never really made it to the top of 
> 
> our list of priorities.  We've just picked up a volunteer to help with 
> 
> documentation, so soon the library might be better documented.
> 
> 
> 
> But we're still mostly focused on code.  And perhaps the biggest thing 
> 
> left is to implement some of the standard algebraic types, such as 
> 
> Functor, Applicative, Monoid, and Monad, as well as some standard 
> 
> objects implementing those, such as Maybe, Either, and IO.  This is 
> 
> well underway, and will probably be ready within weeks.
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> In any case, this is a very long post.  I'd love to hear any feedback 
> 
> you have to offer.  I'd especially love to hear suggestions about the 
> 
> API design. 
> 
> 
> 
> Thanks,
> 
> 
> 
>   -- Scott,
> 
> 
> 
> _____ 
> 
> [1] http://underscorejs.org/ 
> 
> [2] http://lodash.com/ 
> 
> [3] https://github.com/raganwald/allong.es 
> 
> [4] http://fogus.github.io/lemonad/ 
> 
> [5] http://osteele.com/posts/2007/07/functional-javascript

Nice. The code on Github looks very well organized -- I like how well-commented it is. I'm not sure what the point in trying to emulate Haskell too much would be (things such as Maybe or IO) since I thought that the point of those sorts of monads was to get around Haskell's rigid type system and lack of side effects. In the context of javascript wouldn't they be trying to solve a problem that javascript doesn't have? I would think that a functional language like ML which isn't afraid of side-effects would be a closer fit to javascript.

In any event -- I have a hobby project that I want to work on this summer to port some image-producing Haskell code I wrote in the past to javascript so I can display the resulting images on an html canvas. Your library looks like it might be a promising way to go.

[toc] | [prev] | [next] | [standalone]


#24456

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-28 04:37 -0700
Message-ID<1868ca82-5747-4fe2-a98c-a8c5361be6d9@googlegroups.com>
In reply to#24449
John C wrote:
> Scott Sauyet wrote:

>> I'm looking for feedback on a new functional programming library for 
>> Javascript [ ... ]
>>     <https://github.com/CrossEye/ramda> [ ... ]

> Nice. The code on Github looks very well organized -- I like how 
> well-commented it is. 

Thank you.  If nothing else, that helps us maintain a minimal amount of
documentation in the form of annotated source code:

    <https://rawgit.com/CrossEye/ramda/master/docs/ramda.html>

> I'm not sure what the point in trying to emulate Haskell too much 
> would be (things such as Maybe or IO) since I thought that the point 
> of those sorts of monads was to get around Haskell's rigid type system 
> and lack of side effects. 

I don't think Haskellers would be suggesting attempts to get around their
precious type system!  :-)

Right now where Ramda really is useful is in dealing with data objects;
it's very powerful at mapping, filtering, reducing, and many other 
straightforward FP techniques for manipulating data.  But we'd like to 
extend it into other parts of the front-end stack, places less orderly,
such as dealing with the DOM, with HTTP and other asynchronous processes.

In order to deal with these, we'd like to have something like `Maybe` 
Functor which isolates the null-checking to a single place. We probably 
wouldn't need Haskell's `Just` and `Nothing` subclasses, as Javascript's 
looser type system will let us handle things just fine with a single 
`Maybe` whose value may or may not be null. But when we fmap over a 
`Maybe` we then don't have any further worries about whether the value 
is null. Only at the very end, when we're unpacking our data again do we 
have to check it. 

Similarly, we'd like to build our systems by composing functions, and
then triggering them based on some events.  But our functions will not be
entirely pure; we will want to update the DOM, make a server request, or
create some other side-effect along the way.  But we still want our pure
functions to be as straightforward as possible.  Something like the `IO`
Monad could help us to segregate the pure from the impure.


> In the context of javascript wouldn't they be trying to solve a 
> problem that javascript doesn't have? I would think that a functional 
> language like ML which isn't afraid of side-effects would be a closer 
> fit to javascript. 

We're not doing this in isolation.  A lot of projects are trying to
implement a common specification for these algebraic types:

    <https://github.com/fantasyland/fantasy-land>
    
I have the feeling that these folks are Clojure and Scala folks more 
than Haskell. I've never really learned ML, although I find I can read 
it reasonably well.


> In any event -- I have a hobby project that I want to work on this 
> summer to port some image-producing Haskell code I wrote in the past 
> to javascript so I can display the resulting images on an html canvas. 
> Your library looks like it might be a promising way to go. 

Best of luck with that. Feel free to email if you're looking for help 
with the library.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24455

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-28 04:36 -0700
Message-ID<2f5fd1b2-271b-4460-87e0-b1ad81ddd379@googlegroups.com>
In reply to#24448
Scott Sauyet wrote:

> I'm looking for feedback on a new functional programming library for 
> Javascript [ ... ]
>     <https://github.com/CrossEye/ramda> [ ... ]

I guess I was getting sleepy when I finally posted this, as I copied the
wrong example to illustrate this section:

>   - `useWith`.  We still haven't decided which of the two APIs 
>     for this function we prefer, and for the moment are including     
>     both.  This function combines a number of configuration functions 
>     with a single gathering function and returns a new function.  When 
>     the resulting function is called, the arguments are supplied, 
>     respectively, to each of the configuration functions, and the 
>     results of these functions are all passed to the gathering 
>     function.  This allows us to define Codd's `project` (similar to 
>     SQL `select`) for lists of objects with quite simple code:
> 
>         project = useWith(map, pickAll, identity); // OR (other API)
>         project = use(map).over(pickAll, identity);

`project` would actually get used like this:

    var kids = [
        {name: 'Abby', age: 7, hair: 'blond', grade: 2},
        {name: 'Fred', age: 12, hair: 'brown', grade: 7}
    ];
    project(['name', 'grade'], kids);
    //=> [{name: 'Abby', grade: 2}, {name: 'Fred', grade: 7}]

Of course the point of that section was to demonstrate `useWith`/`use.over`, 
but I still prefer to have the examples meaningful.

The point is that `useWith` returned a function (assigned to `project`) that
takes a list of property names, passes it to `pickAll`, a list of objects,
passes it to `identity`, and then passes the results of those functions to
`map`.  (This works because `pickAll` is curried, but that's true of pretty 
well all functions of more than one parameter in the library.)

Sorry if anyone was confused by the earlier example.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24457

From"Michael Haufe (TNO)" <tno@thenewobjective.com>
Date2014-05-28 08:49 -0700
Message-ID<737583eb-f24f-4f9a-a221-4c1677f59932@googlegroups.com>
In reply to#24448
On Tuesday, May 27, 2014 10:13:11 PM UTC-5, Scott Sauyet wrote:
> I've been away from this group a while, and probably will not be 
> around for long this time, as I'm pretty buried in several projects 
> that haven't left me much spare time.  But I wanted to announce my 
> current project.  I'll check in regularly for a while to read responses.
>
> [...]

Would you mind giving me an update on things since our last conversations? 

https://groups.google.com/d/topic/jsmentors/0Cj7AEH5Oic/discussion
https://groups.google.com/d/topic/jsmentors/wH6X8SDPnbw/discussion

[toc] | [prev] | [next] | [standalone]


#24459

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-28 15:59 -0700
Message-ID<ead75684-b2f7-4ea2-b758-02fac986f26b@googlegroups.com>
In reply to#24457
Michael Haufe (TNO) wrote:
> Scott Sauyet wrote:

>> I've been away from this group a while, and probably will not be 
>> around for long this time, as I'm pretty buried in several projects 
>> that haven't left me much spare time.  But I wanted to announce my 
>> current project.  I'll check in regularly for a while to read responses.
>> [...]
> 
> Would you mind giving me an update on things since our last conversations? 
> 
> https://groups.google.com/d/topic/jsmentors/0Cj7AEH5Oic/discussion
> https://groups.google.com/d/topic/jsmentors/wH6X8SDPnbw/discussion

Regarding ideas about functional composition discussed in one of those 
threads, this library does not attempt to address anything but the 
standard notion of `compose` used in many FP contexts, although it 
also adds `pipe`, which simply does the same thing with the arguments 
in the reverse order.  For example,

    var factorial = compose(product, range(1), add(1));

is equivalent to 

    var factorial = pipe(add(1), range(1), product);

(As discussed previously, our `range` is inclusive on the left, 
exclusive on the right, which necessitates the `add(1)` call.)

I find `pipe` more intuitive than `compose`, but obviously there's not 
much difference.  We do have one other compose-like function included, 
the `useWith` mentioned in the OP.  I have given a brief talk on 
functional composition in several forums; the slides are here:

    <http://scott.sauyet.com/Javascript/Talk/Compose/>

------------------------------ 

The other thread was a long-ranging discussion about the predecessor 
to ramda, a library called eweda.  Although the original goal of eweda 
was to be a practical library, we quickly became seduced by 
implementation elegance and did not build a very performant or, in the 
end, a very useful library.  Ramda takes a very different approach.  
The library tries to be efficient and useful.  It keeps the same API 
as eweda, focusing on simple, composable, pre-curried functions that 
do much of the standard list-, object-, string-, number-, and 
function-manipulation that you might expect.

There are probably few surprises in Ramda for someone who has 
programmed in a functional language.  The ideas was to take some of 
the things that are most sorely missed when switching to Javascript 
and make them available.  Next up will be the algebraic data types.

This library does not have the replaceable core list implementation 
featured in eweda.  Its lists are arrays.  It does, though have the 
ability to deal with infinite lazy lists created by generators.  (We 
are in the process of trying to build a bundling system; these lazy 
lists may well end up being an optional feature not included in the 
core bundle, but the code is available, and still included by default 
at the moment.)

The biggest change from those discussions is one of maturity.  The 
library has grown, become better tested, more hardened, and I'm 
hoping, more all-around useful.  It no longer feels like an API 
experiment; it feels like a working product.

HTH,

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24460

From"Michael Haufe (TNO)" <tno@thenewobjective.com>
Date2014-05-28 16:15 -0700
Message-ID<438d5065-ea6f-437f-a9da-f3712efda2d3@googlegroups.com>
In reply to#24459
On Wednesday, May 28, 2014 5:59:12 PM UTC-5, Scott Sauyet wrote:

> [...]
>
> There are probably few surprises in Ramda for someone who has 
> programmed in a functional language.  The ideas was to take some of 
> the things that are most sorely missed when switching to Javascript  
> and make them available.  Next up will be the algebraic data types.
>
> [...]

I'll try to make time for a better follow-up in a couple days. For now I'd like to forward you the follow reference which you might find useful for ADTs:

<http://w3future.com/weblog/stories/2008/06/16/adtinjs.xml>

1. What version of ECMAScript are you assuming?

2. How do/will you manage a collection of related functions? Since you are avoiding OO, and don't have the luxury of Type Classes, what will you do? This issue will be important for when you get around to things such as Monoids. ADTs could be an escape hatch here.

[toc] | [prev] | [next] | [standalone]


#24462

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-28 17:05 -0700
Message-ID<2d59b8d0-7ca1-4494-a88d-3c171b73abe6@googlegroups.com>
In reply to#24460
Michael Haufe (TNO) wrote:
> Scott Sauyet wrote:
>> [...]
>> There are probably few surprises in Ramda for someone who has 
>> programmed in a functional language.  The ideas was to take some of 
>> the things that are most sorely missed when switching to Javascript  
>> and make them available.  Next up will be the algebraic data types.
>> [...]
> 
> I'll try to make time for a better follow-up in a couple days. For 
> now I'd like to forward you the follow reference which you might find 
> useful for ADTs:
> 
> <http://w3future.com/weblog/stories/2008/06/16/adtinjs.xml>

I've glanced through it and it looks interesting.  I will try to give 
it more attention tonight.  But I'm not sure it's really relevant to 
what we're considering.  We really weren't considering a general 
algebraic type solution, but rather a collection of common ones such 
as Functor, Applicative, Monoid, and Monad.  We'd consider 
implementing the FantasyLand specification:

    <https://github.com/fantasyland/fantasy-land>

> 1. What version of ECMAScript are you assuming?

We haven't made any particular assumptions.  But I'm guessing that the 
code will run in ES3.  We want it to work in any modern browser or 
server-side implementation, but don't expect that to be an issue.


> 2. How do/will you manage a collection of related functions? Since 
> you are avoiding OO, and don't have the luxury of Type Classes, what 
> will you do? This issue will be important for when you get around to 
> things such as Monoids. ADTs could be an escape hatch here.

We are not avoiding OO.  So I'm not overly worried.  We are adding 
functional techniques, but we are trying to be practical about the 
fact that this is Javascript.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24476

FromChristoph Michael Becker <cmbecker69@arcor.de>
Date2014-05-30 14:53 +0200
Message-ID<53887f3e$0$6669$9b4e6d93@newsspool3.arcor-online.net>
In reply to#24462
Scott Sauyet wrote:

> Michael Haufe (TNO) wrote:
>
>> 1. What version of ECMAScript are you assuming?
> 
> We haven't made any particular assumptions.  But I'm guessing that the 
> code will run in ES3.  We want it to work in any modern browser or 
> server-side implementation, but don't expect that to be an issue.

While having a look at the documentation, I noticed that ramda.contains
and ramda.indexOf are using Array.prototype.indexOf, which was
introduced in ES 5.1 only.  IMHO not a problem, but maybe good to be
aware of.

-- 
Christoph M. Becker

[toc] | [prev] | [next] | [standalone]


#24488

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-30 11:14 -0700
Message-ID<967fa4e5-cb69-40a0-b709-68eecd8701b4@googlegroups.com>
In reply to#24476
Christoph Michael Becker wrote:
> Scott Sauyet wrote:
>> Michael Haufe (TNO) wrote:
>>> 1. What version of ECMAScript are you assuming?
>> We haven't made any particular assumptions.  But I'm guessing that the 
>> code will run in ES3.  We want it to work in any modern browser or 
>> server-side implementation, but don't expect that to be an issue.
> 
> While having a look at the documentation, I noticed that ramda.contains
> and ramda.indexOf are using Array.prototype.indexOf, which was
> introduced in ES 5.1 only.  IMHO not a problem, but maybe good to be
> aware of.

You're absolutely right.  I'd forgotten that.  We probably won't be working hard (read: at all) to get this to work with pre-ES5 browsers, so we might well end up insisting on that as a minimal requirement, expecting that those who need to use it in an older environment would need to have at least `Array.prototype.indexOf` shimmed.  But we haven't really made those decisions yet.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24466

FromDr J R Stockton <reply1400@merlyn.demon.co.uk.invalid>
Date2014-05-29 19:40 +0100
Message-ID<micPD5QG83hTFwI8@invalid.uk.co.demon.merlyn.invalid>
In reply to#24448
In comp.lang.javascript message <da2909bd-58cc-4183-8b3c-167039985491@go
oglegroups.com>, Tue, 27 May 2014 20:13:11, Scott Sauyet
<scott.sauyet@gmail.com> posted:

>With the automatic partial application of functions, there is no good
>way to allow for dynamic functions signatures, so I can't simply
>assume that `foldl` with two parameters means something different from
>`foldl` with one.  So a good name to replace `foldl1` would be very
>helpful.  Similarly, of course, for `foldr1`.

Words with meanings like "fold" include "crease", "pleat", "plait",
"enfold", "infold", "embrace", and anything that Google Translate offers
as equivalent for any of those.  For example, "plygu", "cris",
"gofleidio", "falt", "taittaa", "plegar", "ninka", "huaire", "darbiet",
"korukoru", "phinda", etc.

-- 
 (c) John Stockton, nr London, UK.  Mail via homepage.  Turnpike v6.05  MIME.
  Web  <http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms and links;
  Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc.

[toc] | [prev] | [next] | [standalone]


#24469

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-29 17:55 -0700
Message-ID<181c0b33-8dc3-459e-bb3a-f9549ded4276@googlegroups.com>
In reply to#24466
Dr J R Stockton wrote:
> Scott Sauyet posted:

>> With the automatic partial application of functions, there is no good
>> way to allow for dynamic functions signatures, so I can't simply
>> assume that `foldl` with two parameters means something different from
>> `foldl` with one.  So a good name to replace `foldl1` would be very
>> helpful.  Similarly, of course, for `foldr1`.
> 
> Words with meanings like "fold" include "crease", "pleat", "plait",
> "enfold", "infold", "embrace", and anything that Google Translate offers
> as equivalent for any of those.  For example, "plygu", "cris",
> "gofleidio", "falt", "taittaa", "plegar", "ninka", "huaire", "darbiet",
> "korukoru", "phinda", etc.

Thank you.  I'm not even going to try to guess at the languages.  :-)

If you are not familiar with foldl/foldr or their aliases of 
reduce/reduceRight, these are common functional construct that combine 
lists of elements into a single value, accepting an initial value and 
a function that combines the current value and the next list element 
into a new value.  The ES5 specification defines 
`Array.prototype.reduce` [1] and `Array.prototype.reduceRight` [2].  
While these work well in modern implementations, they are not the 
functional constructs that the Ramda library is developing. 

The most obvious difference between foldl and foldr is that foldl 
processes the from the first (leftmost) element of the list to the 
last, whereas foldr processes in ther reverse direction.  That is not 
the only difference, but the other subtleties aren't important here.

The difference between `foldl` and `foldl1` is simply that the former 
is supplied the initial value; the latter extracts it as the first 
element of the list (and therefore requires a non-empty list.)  This 
also means that the type of the accumulators for `foldl1`, and 
therefore also of the output should be the same as the types of the 
elements of the list.  But this, in my experience, is the norm even in 
`foldl`.  Obviously, the same things apply to `foldr1`.

Note that the gap between the definitions of 'fold' and 'reduce', 
which here are used as aliases, make it less likely that  a synonym 
for 'fold' would be a reasonable name to replace 'foldl1' or 'foldr1'.  
Probably the most likely notion of folding that applies is something 
like an accordion fold.  And maybe something along those lines would 
do.  What I was really hoping is that someone with experience with 
this in another functional language would be able to pipe up and say, 
"Oh yes, that's often called 'XYZ'."  But I really don't think it's 
likely.

Thanks for the input!

  -- Scott

[1] http://ecma-international.org/ecma-262/5.1/#sec-15.4.4.21
[2] http://ecma-international.org/ecma-262/5.1/#sec-15.4.4.22

[toc] | [prev] | [next] | [standalone]


#24473

FromChristoph Michael Becker <cmbecker69@arcor.de>
Date2014-05-30 14:05 +0200
Message-ID<53887415$0$6655$9b4e6d93@newsspool3.arcor-online.net>
In reply to#24469
Scott Sauyet wrote:

> Note that the gap between the definitions of 'fold' and 'reduce', 
> which here are used as aliases, make it less likely that  a synonym 
> for 'fold' would be a reasonable name to replace 'foldl1' or 'foldr1'.  
> Probably the most likely notion of folding that applies is something 
> like an accordion fold.  And maybe something along those lines would 
> do.  What I was really hoping is that someone with experience with 
> this in another functional language would be able to pipe up and say, 
> "Oh yes, that's often called 'XYZ'."  But I really don't think it's 
> likely.

There is an overview on Wikipedia[1], which you might not be aware of.
As I have (yet) very little experience with functional programming
(languages), I can't comment on this, though.

[1]
<http://en.wikipedia.org/wiki/Fold_(higher-order_function)#Folds_in_various_languages>

-- 
Christoph M. Becker

[toc] | [prev] | [next] | [standalone]


#24487

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-30 11:10 -0700
Message-ID<132b64cd-f936-431c-8099-08a32e362dd2@googlegroups.com>
In reply to#24473
Christoph Michael Becker wrote:
> Scott Sauyet wrote:
> 
>> Note that the gap between the definitions of 'fold' and 'reduce', 
>> which here are used as aliases, make it less likely that  a synonym 
>> for 'fold' would be a reasonable name to replace 'foldl1' or 'foldr1'.  
>> Probably the most likely notion of folding that applies is something 
>> like an accordion fold.  And maybe something along those lines would 
>> do.  What I was really hoping is that someone with experience with 
>> this in another functional language would be able to pipe up and say, 
>> "Oh yes, that's often called 'XYZ'."  But I really don't think it's 
>> likely.
> 
> There is an overview on Wikipedia[1], which you might not be aware of.
> As I have (yet) very little experience with functional programming
> (languages), I can't comment on this, though.
> 
> [1] <http://en.wikipedia.org/wiki/Fold_(higher-order_function)#Folds_in_various_languages>

I hadn't seen that, and it looks as though it might be quite helpful.  Thank you.

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24478

FromJohn C <rescattered@gmail.com>
Date2014-05-30 06:25 -0700
Message-ID<02dfeef2-b8fa-4cc3-8c6f-d375a43278ca@googlegroups.com>
In reply to#24448
On Tuesday, May 27, 2014 11:13:11 PM UTC-4, Scott Sauyet wrote:
> I've been away from this group a while, and probably will not be 
> 
> around for long this time, as I'm pretty buried in several projects 
> 
> that haven't left me much spare time.  But I wanted to announce my 
> 
> current project.  I'll check in regularly for a while to read responses.
> 
> 
> 
> I'm looking for feedback on a new functional programming library for 
> 
> Javascript that I've been developing with a friend.  This may seem 
> 
> very familiar to those who saw a similar request a year ago.  That was 
> 
> for a different library, which turned out to be more of academic 
> 
> interest.  This one was originally based on that project, eweda, but 
> 
> with a more practical bent.
> 
> 
> 
> The library is called "ramda", which is just a silly pun on "lambda".
> 
> 
> 
> My co-author has just published a brief introduction at
> 
> 
> 
>     <http://buzzdecafe.github.io/code/2014/05/16/introducing-ramda/>
> 
> 
> 
> The project is on Github, at 
> 
> 
> 
>     <https://github.com/CrossEye/ramda> 
> 
> 
> 
> and the library is (temporarily, at least) in a single source file: 
> 
> 
> 
>     <https://github.com/CrossEye/ramda/blob/master/ramda.js> 
> 
> 
> 
> You can install it for a Node.js project with
> 
> 
> 
>     npm install ramda
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> The API has a sizable overlap with Underscore [1] and LoDash [2].  But 
> 
> its motivations are closer to allong.es [3] or Lemonad [4] or 
> 
> Functional Javascript [5].  It's an attempt to do in Javascript 
> 
> something more akin to normal functional programming, as would be 
> 
> found in Haskell, ML, Scheme, or LISP. 
> 
> 
> 
> The library's functions are available as properties on the main 
> 
> object, `ramda`: 
> 
> 
> 
>     var square = function(x) {return x * x;}; 
> 
>     var nbrs = ramda.range(1, 5); // => [1, 2, 3, 4] 
> 
>     var squares = ramda.map(square, nbrs); // => [1, 4, 9, 16] 
> 
> 
> 
> But they can be attached to any object, including the global object 
> 
> via `ramda.installTo()`.  This will pollute the global namespace with 
> 
> a number of functions, but is one possible means of using the library. 
> 
> After that, you could just call 
> 
> 
> 
>     var squares2 = map(square, range(1, 5)); // => [1, 4, 9, 16] 
> 
> 
> 
> You might note something surprising here.  Even when it has the same 
> 
> functions as Underscore/LoDash, its parameter order often differs. 
> 
> This is intentional.  Underscore's API was built out of the native, 
> 
> OO- first functions on `Array.prototype` and other similar structures. 
> 
> Ramda's API, on the other hand is designed around composition and 
> 
> partial application (or currying.)  You can create new functions 
> 
> easily by not passing all the arguments to something like `map`: 
> 
> 
> 
>     var squareAll = map(square); 
> 
>     squareAll(range(1, 6)); // => [1, 4, 9, 16, 25] 
> 
> 
> 
> In all cases, functions that take one list as a parameter, have it as 
> 
> their last parameter.  And those that take one function as a parameter 
> 
> have it as their first one.  The API should be internally consistent, 
> 
> even if it's a bit different from other libraries. 
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> There is a fairly large set of tests (using Mocha), but they are by no 
> 
> means comprehensive, serving more as an API guide than as an 
> 
> exhaustive analysis of edge cases.  They are in the folder `tests`, 
> 
> and can be run in a modern browser at 
> 
> 
> 
>     <https://rawgit.com/CrossEye/ramda/master/test/index.html> 
> 
> 
> 
> The only documentation beyond the test suite is a Docco-annotated 
> 
> version of the source, available at 
> 
> 
> 
>     <https://rawgit.com/CrossEye/ramda/master/docs/ramda.html> 
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> The functions we include are mostly standard functional library list 
> 
> functions, ones like `map`, `foldl`, `foldr`, `filter`, `take`, 
> 
> `skip`, some object-based ones like `prop`and `func`, plain function 
> 
> manipulations like `compose`, `flip`, `memoize` and various partials, 
> 
> as well as a few arithmetic and logic functions.  There are over 100 
> 
> functions now, with some dozen aliases. (`reduce` is the same as 
> 
> `foldl`.)  
> 
> 
> 
> I'd love for experienced people to look at the functions and see what 
> 
> is missing, what is totally unnecessary, and what could use a better 
> 
> name or at least an alias.  In the latter category, I really would 
> 
> like to find a better name for `foldl1`, whose name was borrowed from 
> 
> Haskell.  It's the difference between a left fold with an explicit 
> 
> accumulator supplied: 
> 
> 
> 
>     var total = foldl(add, 0, range(1, 11)) // => 55 
> 
> 
> 
> and one where the first value of the (non-empty) list is taken as the 
> 
> accumulator: 
> 
> 
> 
>     var total2 = foldl1(add, range(1, 11)); // => 55 
> 
> 
> 
> With the automatic partial application of functions, there is no good 
> 
> way to allow for dynamic functions signatures, so I can't simply 
> 
> assume that `foldl` with two parameters means something different from 
> 
> `foldl` with one.  So a good name to replace `foldl1` would be very 
> 
> helpful.  Similarly, of course, for `foldr1`. 
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> We also have a few functions that we think are unique to Ramda.  Two 
> 
> examples are:
> 
> 
> 
>   - `when` is similar to functions in other libraries that accept an 
> 
>     object specification and return a predicate that can be used to 
> 
>     test additional objects.  Ramda's `when` takes more than just 
> 
>     individual values for specification, though; it can also take 
> 
>     functions:
> 
> 
> 
>         isTriangular = where({
> 
>           sides: 3,
> 
>           a: function(a, t) {return a < t.b + t.c;},
> 
>           b: function(b, t) {return b < t.a + t.c;},
> 
>           c: function(c, t) {return c < t.a + t.b;}
> 
>         });
> 
> 
> 
>         isTriangular({sides: 5}); //=> false
> 
>         isTriangular({sides: 3, a: 2, b: 1, c: 7}); //=> false
> 
>         isTriangular({sides: 3, a: 3, b: 4, c: 5}); //=> true
> 
> 
> 
>   - `useWith`.  We still haven't decided which of the two APIs 
> 
>     for this function we prefer, and for the moment are including     
> 
>     both.  This function combines a number of configuration functions 
> 
>     with a single gathering function and returns a new function.  When 
> 
>     the resulting function is called, the arguments are supplied, 
> 
>     respectively, to each of the configuration functions, and the 
> 
>     results of these functions are all passed to the gathering 
> 
>     function.  This allows us to define Codd's `project` (similar to 
> 
>     SQL `select`) for lists of objects with quite simple code:
> 
> 
> 
>         project = useWith(map, pickAll, identity); // OR (other API)
> 
>         project = use(map).over(pickAll, identity);
> 
> 
> 
>     This would get used like this:
> 
> 
> 
>         var kids = [
> 
>           {name: 'Abby', age: 7, hair: 'blond'},
> 
>           {name: 'Fred', age: 12, hair: 'brown'},
> 
>           {name: 'Rusty', age: 10, hair: 'brown'},
> 
>           {name: 'Alois', age: 15, disposition: 'surly'}
> 
>         ];
> 
>         filter(propEq("hair", "brown"), kids);
> 
>         //=> Fred and Rusty
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> The library has a facility for creating lazy infinite lists; we're in 
> 
> the process of pulling that out of the core and making it a separate 
> 
> extension.  In fact we want to have a bundle-building mechanism to 
> 
> allow you to create your own package, the way Modernizr and David 
> 
> Mark's MyLibrary (is that still around?) do.
> 
> 
> 
> But that infrastructure work has never really made it to the top of 
> 
> our list of priorities.  We've just picked up a volunteer to help with 
> 
> documentation, so soon the library might be better documented.
> 
> 
> 
> But we're still mostly focused on code.  And perhaps the biggest thing 
> 
> left is to implement some of the standard algebraic types, such as 
> 
> Functor, Applicative, Monoid, and Monad, as well as some standard 
> 
> objects implementing those, such as Maybe, Either, and IO.  This is 
> 
> well underway, and will probably be ready within weeks.
> 
> 
> 
> ------------------------------ 
> 
> 
> 
> In any case, this is a very long post.  I'd love to hear any feedback 
> 
> you have to offer.  I'd especially love to hear suggestions about the 
> 
> API design. 
> 
> 
> 
> Thanks,
> 
> 
> 
>   -- Scott,
> 
> 
> 
> _____ 
> 
> [1] http://underscorejs.org/ 
> 
> [2] http://lodash.com/ 
> 
> [3] https://github.com/raganwald/allong.es 
> 
> [4] http://fogus.github.io/lemonad/ 
> 
> [5] http://osteele.com/posts/2007/07/functional-javascript

As far as your name for foldl1 goes -- how about selfFoldl since in that case 
it folds in on itself (as opposed to folding on an externally given item)?
Another idea is something like "rollUp"

[toc] | [prev] | [next] | [standalone]


#24489

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-30 11:23 -0700
Message-ID<2c61b020-8e0c-4a3b-a021-f7058aed52dc@googlegroups.com>
In reply to#24478
John C wrote:
> Scott Sauyet wrote:
>> [ ... ]
>>     <https://github.com/CrossEye/ramda> 
>> [ ... ]
>> I'd love for experienced people to look at the functions and see what 
>> is missing, what is totally unnecessary, and what could use a better 
>> name or at least an alias.  In the latter category, I really would 
>> like to find a better name for `foldl1`, whose name was borrowed from 
>> Haskell.  It's the difference between a left fold with an explicit 
>> accumulator supplied: 
>> 
>>     var total = foldl(add, 0, range(1, 11)) // => 55 
>> 
>> and one where the first value of the (non-empty) list is taken as the accumulator: 
>> 
>>     var total2 = foldl1(add, range(1, 11)); // => 55 
>> 
>> With the automatic partial application of functions, there is no good 
>> way to allow for dynamic functions signatures, so I can't simply 
>> assume that `foldl` with two parameters means something different from 
>> `foldl` with one.  So a good name to replace `foldl1` would be very 
>> helpful.  Similarly, of course, for `foldr1`.  [ ... ]

> As far as your name for foldl1 goes -- how about selfFoldl since in 
> that case it folds in on itself (as opposed to folding on an externally
> given item)? Another idea is something like "rollUp"

Those both sound quite good.  Thank you for the suggestions.

The funny thing is that I'd forgotten we'd taken these out of the library in response to a disagreement over how to handle the case where the user supplied an empty list.  At some point we'll probably put them back, but they're not there now.  When they do come back, maybe we'll use `selfFoldl`.

Thanks,

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24493

FromJohn C <rescattered@gmail.com>
Date2014-05-30 12:44 -0700
Message-ID<72aa659a-997d-4d1a-97bb-87ffef38978c@googlegroups.com>
In reply to#24489
On Friday, May 30, 2014 2:23:48 PM UTC-4, Scott Sauyet wrote:
> John C wrote:
> 
> > Scott Sauyet wrote:
> 
> >> [ ... ]
> 
> >>     <https://github.com/CrossEye/ramda> 
> 
> >> [ ... ]
> 
> >> I'd love for experienced people to look at the functions and see what 
> 
> >> is missing, what is totally unnecessary, and what could use a better 
> 
> >> name or at least an alias.  In the latter category, I really would 
> 
> >> like to find a better name for `foldl1`, whose name was borrowed from 
> 
> >> Haskell.  It's the difference between a left fold with an explicit 
> 
> >> accumulator supplied: 
> 
> >> 
> 
> >>     var total = foldl(add, 0, range(1, 11)) // => 55 
> 
> >> 
> 
> >> and one where the first value of the (non-empty) list is taken as the accumulator: 
> 
> >> 
> 
> >>     var total2 = foldl1(add, range(1, 11)); // => 55 
> 
> >> 
> 
> >> With the automatic partial application of functions, there is no good 
> 
> >> way to allow for dynamic functions signatures, so I can't simply 
> 
> >> assume that `foldl` with two parameters means something different from 
> 
> >> `foldl` with one.  So a good name to replace `foldl1` would be very 
> 
> >> helpful.  Similarly, of course, for `foldr1`.  [ ... ]
> 
> 
> 
> > As far as your name for foldl1 goes -- how about selfFoldl since in 
> 
> > that case it folds in on itself (as opposed to folding on an externally
> 
> > given item)? Another idea is something like "rollUp"
> 
> 
> 
> Those both sound quite good.  Thank you for the suggestions.
> 
> 
> 
> The funny thing is that I'd forgotten we'd taken these out of the library in response to a disagreement over how to handle the case where the user supplied an empty list.  At some point we'll probably put them back, but they're not there now.  When they do come back, maybe we'll use `selfFoldl`.
> 
> 
> 
> Thanks,
> 
> 
> 
>   -- Scott

Out of curiosity -- what was the disagreement? Returning undefined
seems like the natural choice since the result is, well, undefined 
in this case. Is the concern with the way undefined is sometimes
quirky in javascript? 

[toc] | [prev] | [next] | [standalone]


#24498

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-30 13:39 -0700
Message-ID<0eda5ddb-5a7a-4fa6-8d4c-219034645bcb@googlegroups.com>
In reply to#24493
John C wrote:
>  Scott Sauyet wrote:
>> The funny thing is that I'd forgotten we'd taken these out of the 
>> library in response to a disagreement over how to handle the case 
>> where the user supplied an empty list. At some point we'll probably 
>> put them back, but they're not there now. When they do come back, 
>> maybe we'll use `selfFoldl`. 

(I'm sorry about the poor formatting earlier.  The updated Google Groups
was one of the reasons I've been gone for a while.  I'm sorry to see
that it's as bad as ever!)
 
> Out of curiosity -- what was the disagreement? Returning undefined
> seems like the natural choice since the result is, well, undefined 
> in this case. Is the concern with the way undefined is sometimes
> quirky in javascript?

Then you will agree with my coauthor, who argued for the same thing.
We had a long discussion about this, captured here:

    <https://github.com/CrossEye/ramda/issues/20>
    
The original implementation, following Haskell, raised an exception in 
this case. My coauthor didn't like this, thinking that we should return 
`undefined`. I, in turn, didn't like returning anything that might make 
the user have to type-check her results. Neither of us was really 
willing to budge, and as these were not very important to either of us, 
it was easier to simply remove the functions and see if something didn't 
settle out of it eventually. This was, I think, the only significant 
disagreement we've had over the time we've spent on this. 

Eventually, it came down to his preference list, which looked like this:

    1. remove foldl1/foldr1 from the library
    2. return undefined for empty list
    3. throw exception

and mine, which looked like this:
    
    1. throw exception
    2. remove foldl1/foldr1 from the library
    3. return undefined for empty list
    
At that point, it was pretty clear that the easiest thing was to remove 
these functions. They are easy enough to add back if someone wants. And 
maybe we will at some point. 

  -- Scott

[toc] | [prev] | [next] | [standalone]


#24501

FromJohn C <rescattered@gmail.com>
Date2014-05-30 19:17 -0700
Message-ID<6adc900a-ed11-45f5-b7bf-413a2b5018a6@googlegroups.com>
In reply to#24498
On Friday, May 30, 2014 4:39:21 PM UTC-4, Scott Sauyet wrote:
> John C wrote:
> 
> >  Scott Sauyet wrote:
> 
> >> The funny thing is that I'd forgotten we'd taken these out of the 
> 
> >> library in response to a disagreement over how to handle the case 
> 
> >> where the user supplied an empty list. At some point we'll probably 
> 
> >> put them back, but they're not there now. When they do come back, 
> 
> >> maybe we'll use `selfFoldl`. 
> 
> 
> 
> (I'm sorry about the poor formatting earlier.  The updated Google Groups
> 
> was one of the reasons I've been gone for a while.  I'm sorry to see
> 
> that it's as bad as ever!)
> 
>  
> 
> > Out of curiosity -- what was the disagreement? Returning undefined
> 
> > seems like the natural choice since the result is, well, undefined 
> 
> > in this case. Is the concern with the way undefined is sometimes
> 
> > quirky in javascript?
> 
> 
> 
> Then you will agree with my coauthor, who argued for the same thing.
> 
> We had a long discussion about this, captured here:
> 
> 
> 
>     <https://github.com/CrossEye/ramda/issues/20>
> 
>     
> 
> The original implementation, following Haskell, raised an exception in 
> 
> this case. My coauthor didn't like this, thinking that we should return 
> 
> `undefined`. I, in turn, didn't like returning anything that might make 
> 
> the user have to type-check her results. Neither of us was really 
> 
> willing to budge, and as these were not very important to either of us, 
> 
> it was easier to simply remove the functions and see if something didn't 
> 
> settle out of it eventually. This was, I think, the only significant 
> 
> disagreement we've had over the time we've spent on this. 
> 
> 
> 
> Eventually, it came down to his preference list, which looked like this:
> 
> 
> 
>     1. remove foldl1/foldr1 from the library
> 
>     2. return undefined for empty list
> 
>     3. throw exception
> 
> 
> 
> and mine, which looked like this:
> 
>     
> 
>     1. throw exception
> 
>     2. remove foldl1/foldr1 from the library
> 
>     3. return undefined for empty list
> 
>     
> 
> At that point, it was pretty clear that the easiest thing was to remove 
> 
> these functions. They are easy enough to add back if someone wants. And 
> 
> maybe we will at some point. 
> 
> 
> 
>   -- Scott

I guess I was thinking in terms of the Principle of Least Astonishment (POLA). 
JavaScript already has some functional features, so I would think that 
a library for functional programming in JavaScript should extend what is
already there rather than rewriting it. It should be possible to take 
an existing program in JavaScript which has strong functional features 
and somewhat easily rewrite it using the library. In particular -- code 
which already uses JavaScript's reduce should be easily modified to run
using the new folding functions that you provide. Thus, I would expect 
that selfFold would be more or less equivalent to:

function selfFold(f,xs) 
{
    return xs.slice(1).reduce(f,xs[0]);
}

with e.g. add(x,y) defined as {return x+y;} this yields

selfFold(add,[3,5,7]); // => 15, as expected

but we also have

selfFold(add,[]); // => undefined

which is also completely expected to a JavaScript programmer. 
Thus *unless there is a compelling reason to do otherwise*, POLA would 
suggest that an implementation of selfFold would return undefined on an
empty list. 

On the other hand, I haven't thought about the issue much, and am open to
the claim that in e.g. the importance of having a consistent approach to error
handling across a library might outweigh POLA in this case.

[toc] | [prev] | [next] | [standalone]


#24507

FromScott Sauyet <scott.sauyet@gmail.com>
Date2014-05-31 09:52 -0700
Message-ID<f2386144-c7df-4280-8af9-9258919a9a66@googlegroups.com>
In reply to#24501
John C wrote:
> Scott Sauyet wrote:

>> [ ... re: when foldl1/foldr1 is called with no accumulator ...]

>> The original implementation, following Haskell, raised an exception in 
>> this case. My coauthor didn't like this, thinking that we should return 
>> `undefined`. I, in turn, didn't like returning anything that might make 
>> the user have to type-check her results. 

> I guess I was thinking in terms of the Principle of Least 
> Astonishment (POLA). JavaScript already has some functional 
> features, so I would think that a library for functional programming 
> in JavaScript should extend what is already there rather than 
> rewriting it. 

I'm afraid that we might then be disappointing you.  For the most 
part, the array processing functions are all hand-written.  
(Christoph Becker notes some exceptions earlier in this thread.)  We 
do this for various reasons, but the biggest one is to be in control 
of the API.  On the other hand, we do have a function `invoker` 
which turns a method on an object (usually a prototype) into a plain 
function, and we use it to expose much of the String.prototype as
functions.  For instance,

    ramda.substring = invoker("substring", String.prototype);

which we could use like this:

    map(substring(0, 2), ["Fools", "rush", "in"]);
    //=> ["Fo", "ru", "in"]


So in one sense it sounds as though we're being inconsistent.  But 
there are problems combining the native functional array methods 
with other built-in functions.  The classic example is

    ["1.1", "2.2", "3.3"].map(parseFloat); //=> [1.1, 2.2, 3.3]
    ["1", "2", "3"].map(parseInt);         //=> [1, NaN, NaN]

The problem is that the native `Array.prototype.map` passes 
additional arguments to its callback functions: the index and the 
entire list.  This isn't a problem for `parseFloat`, which only uses 
the first parameter.  But `parseInt` takes an optional second 
parameter, the radix:

    parseInt("1", 0) //=> parseInt("1", 10) => 1
    parseInt("2", 1) //=> NaN
    parseInt("3", 2) //=> NaN

For our purposes, we want to be able to do this:

    map(parseInt, ["1", "2", "3"]); //=> [1, 2, 3]

or maybe this, if we want to be careful about the radix:

    map(flip(parseInt)(10), ["1", "2", "3"]); //=> [1, 2, 3]

so our `map` (similarly our `filter`, `foldl/foldr`, `forEach`, 
etc.) only accept the element.  Recognizing that there are 
legitimate uses for the multiple parameter calls, we do offer 
variants that pass them along, but they're not the baseline calls:

    map.idx(fn, list); // callback: fn(element, index, list)

> It should be possible to take an existing program in JavaScript 
> which has strong functional features and somewhat easily rewrite it 
> using the library. In particular -- code which already uses 
> JavaScript's reduce should be easily modified to run using the new 
> folding functions that you provide. Thus, I would expect that 
> selfFold would be more or less equivalent to:

 
> function selfFold(f,xs) 
> {
>     return xs.slice(1).reduce(f,xs[0]);
> }

Minus the error-checking, it was, in fact, written like this:

    ramda.foldl1 = curry(function (fn, list) {
        return foldl(fn, head(list), tail(list));
    }

which isn't all that different, but depends on our foldl function 
rather than the native one.


> with e.g. add(x,y) defined as {return x+y;} this yields
> 
>     selfFold(add,[3,5,7]); // => 15, as expected
> 
> but we also have
> 
>     selfFold(add,[]); // => undefined

Yes.  That was part of our discussion.  And it's almost compelling 
to me.  But not quite.  If the user of foldl uses a function that 
always returns an element with a certain interface and supplies one 
like that as the accumulator, then foldl will always return one with 
that same interface, and the user has to do no further type-checking 
on the result.  If she were to switch to foldl1, and she happens to 
supply an empty list, obviously she cannot get back that interface 
(for how would we call her function?)  So then we're left with three 
real possibilities: return something else, return nothing, or throw 
an error.  Throwing something else -- even null -- seems pretty 
crazy.  You're argument for returning nothing/undefined is 
reasonable.  Mine is that this is essentially an unrecoverable error 
unless we as developers of the library want to insist that users 
wrap type-checking around the results of calling selfFold; I think 
it's also a reasonable argument for throwing an error in this 
circumstance.


> which is also completely expected to a JavaScript programmer. Thus 
> *unless there is a compelling reason to do otherwise*, POLA would 
> suggest that an implementation of selfFold would return undefined on 
> an empty list. 

I'm not sure that an argument about one possible implementation of 
an idea can really carry the weight of the Principle of Least 
Astonishment.  

Here is another perfectly reasonable version of selfFold:

    function selfFold(f,xs) {
        return xs.reduce(f);
    }

`Array.prototype.reduce` takes a function and *optionally* the 
initial accumulator value.  If one isn't supplied, it takes the
first item in the list as its value, and starts processing with
the second one.  This might be an even more obvious way to use
the native version than your suggestion.  But note:

   [1, 2, 3].reduce(add); //=> 6
   [1].reduce(add); //=> 1
   [].reduce(add); //=> TypeError: Reduce of empty array with 
                   //   no initial value

I didn't think of this argument in the discussion I had with Ramda's 
coauthor, but it's an interesting point: It's not just how Haskell 
does it; it's also the native JS answer.


> On the other hand, I haven't thought about the issue much, and am 
> open to the claim that in e.g. the importance of having a consistent 
> approach to error handling across a library might outweigh POLA in 
> this case.

My point wasn't about consistent error-handling.  We really haven't
figured that out yet.  My main concern was as a user of the library
to never have the library return bad data to me.

Thank you very much for your interesting feedback,

  -- Scott

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.javascript


csiph-web