ANN: Ramda, a new functional programming library

229 views
Skip to first unread message

Scott Sauyet

unread,
May 27, 2014, 11:13:11 PM5/27/14
to
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

John C

unread,
May 28, 2014, 12:00:35 AM5/28/14
to
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.

Scott Sauyet

unread,
May 28, 2014, 7:36:35 AM5/28/14
to
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

Scott Sauyet

unread,
May 28, 2014, 7:37:07 AM5/28/14
to
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

Michael Haufe (TNO)

unread,
May 28, 2014, 11:49:03 AM5/28/14
to
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

Scott Sauyet

unread,
May 28, 2014, 6:59:12 PM5/28/14
to
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

Michael Haufe (TNO)

unread,
May 28, 2014, 7:15:52 PM5/28/14
to
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.

Scott Sauyet

unread,
May 28, 2014, 8:05:12 PM5/28/14
to
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

Dr J R Stockton

unread,
May 29, 2014, 2:40:06 PM5/29/14
to
In comp.lang.javascript message <da2909bd-58cc-4183-8b3c-167039985491@go
oglegroups.com>, Tue, 27 May 2014 20:13:11, Scott Sauyet
<scott....@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.

Scott Sauyet

unread,
May 29, 2014, 8:55:17 PM5/29/14
to
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

Christoph Michael Becker

unread,
May 30, 2014, 8:05:49 AM5/30/14
to
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

Christoph Michael Becker

unread,
May 30, 2014, 8:53:27 AM5/30/14
to
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

John C

unread,
May 30, 2014, 9:25:03 AM5/30/14
to
On Tuesday, May 27, 2014 11:13:11 PM UTC-4, Scott Sauyet wrote:
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"

Scott Sauyet

unread,
May 30, 2014, 2:10:44 PM5/30/14
to
I hadn't seen that, and it looks as though it might be quite helpful. Thank you.

-- Scott

Scott Sauyet

unread,
May 30, 2014, 2:14:09 PM5/30/14
to
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

Scott Sauyet

unread,
May 30, 2014, 2:23:48 PM5/30/14
to
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

John C

unread,
May 30, 2014, 3:44:57 PM5/30/14
to
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?

Scott Sauyet

unread,
May 30, 2014, 4:39:21 PM5/30/14
to
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

John C

unread,
May 30, 2014, 10:17:12 PM5/30/14
to
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.

Scott Sauyet

unread,
May 31, 2014, 12:52:15 PM5/31/14
to
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

Christoph Michael Becker

unread,
May 31, 2014, 3:00:05 PM5/31/14
to
Scott Sauyet wrote:

> John C wrote:
>
>> 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`.

Um, foldl1() and foldr1() are in current master[1], though. :)

BTW: there is a mistake in the documentation of deepClone, where it says:

| Create a shallow copy of an array.

[1] <https://github.com/CrossEye/ramda/blob/master/ramda.js#L562>

--
Christoph M. Becker

Christoph Michael Becker

unread,
May 31, 2014, 4:24:06 PM5/31/14
to
Scott Sauyet wrote:

> 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. [...]

Addtionally it should be noted, that several of the ECMAScript Array
methods are destructive, which is not desirable in the functional
programming paradigm, unless for performance reasons. It might be
interesting to have some benchmarks available, comparing e.g.
Array.prototype.reverse() and ramda.reverse().

--
Christoph M. Becker

Scott Sauyet

unread,
Jun 1, 2014, 9:54:39 AM6/1/14
to
Christoph Michael Becker wrote:
> Scott Sauyet wrote:
>> John C wrote:
>>
>>> 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`.
>
> Um, foldl1() and foldr1() are in current master[1], though. :)

Yeah, I noticed that yesterday. I did take them out, I swear it!
We must have had a bad merge that put them back in, which neither of
us noticed. When I talk to the co-author, we'll work out whether
they should stay, and if so, how to handle the issue of whether to
throw or return undefined when an empty list is supplied.


> BTW: there is a mistake in the documentation of deepClone, where it says:
>
> | Create a shallow copy of an array.
>
> [1] <https://github.com/CrossEye/ramda/blob/master/ramda.js#L562>

Thanks. That's been fixed. This turns out to be another place where
the code depends on something not available in the older browsers: a
native JSON implementation.

-- Scott

Scott Sauyet

unread,
Jun 1, 2014, 9:55:12 AM6/1/14
to
It might be interesting. In the case of `reverse`, Ramda would of
necessity be slower than the native version, as it depends upon that
version and also uses a `clone` function (which is just a native
`concat` call and should be reasonably quick, but still...) In some
others, I'm guessing that Ramda's versions would be faster than their
native counterparts, and in many cases, there would probably not be
enough of a difference for me to care about. I do know that we
reimplemented `slice` internally, because our internal version was
much faster than the native counterpart.

But I haven't had any reason to worry about this since we stopped
the predeccesor project, Eweda, which used more LISP-like
techniques, heavy on the recursion, and ended up too slow for
practical work. It would probably be worth knowing the results of
such performance analysis, and might help us find places ripe for
some optimizations, but it's not particularly high on my priority
list right now.

But the broader point, that ramda's functions are not destructive,
is spot on. That is fundamental. Javascript is a multi-paradigm
language. It's easy to combine Object-Oriented techniques with
functional ones. There have been plenty of tools to help with the
OO-side of things. Ramda is designed to help the user work
functionally. This means that it should never mutate arguments to
its functions.

-- Scott

Dr J R Stockton

unread,
Jun 1, 2014, 2:05:11 PM6/1/14
to
In comp.lang.javascript message <da2909bd-58cc-4183-8b3c-167039985491@go
oglegroups.com>, Tue, 27 May 2014 20:13:11, Scott Sauyet
<scott....@gmail.com> posted:

>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.

If the library is not being written IN JavaScript (or even if it is),
you could consider implementing (maybe more efficiently) the improved
date object in <http://www.merlyn.demon.co.uk/js-dobj2.htm>.

Note that for the Russian market one should add a routine for Julian
Easter, carefully considering the consequences of the differing lengths
of the Julian & Gregorian Years.

--
(c) John Stockton, nr London, UK. E-mail, see Home Page. Turnpike v6.05.
Website <http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
PAS EXE etc. : <http://www.merlyn.demon.co.uk/programs/> - see in 00index.htm
Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.

Scott Sauyet

unread,
Jun 1, 2014, 10:28:38 PM6/1/14
to
Dr J R Stockton wrote:
> Scott Sauyet posted:
>
>> I'm looking for feedback on a new functional programming library for
>> Javascript that I've been developing with a friend. [ ... ]
>
> If the library is not being written IN JavaScript (or even if it is),
> you could consider implementing (maybe more efficiently) the improved
> date object in <http://www.merlyn.demon.co.uk/js-dobj2.htm>. [ ... ]

Although that looks to be interesting code, and an improvement on
the existing Date constructor function in several important ways, I
don't think it would be a good fit for Ramda.

Ramda is about offering functional programming (FP) tools to the
user. Javascript, with heritage from both Self and Scheme has both
object-oriented and functional roots. There are plenty of tools to
help with the OO side, but far fewer for the FP paradigm. That's
where Ramda fits in. It offers things like improved `map`,
`reduce`, `filter`, and similar list-handling features, functional
composition and currying, the reification of numerous functions from
the String, Array, and Object prototypes, some SQL-like functions to
query lists of objects, and various other techniques to work with
immutable objects.

DATE2 is an OO construct, a constructor function with a beefy
prototype object. It creates mutable objects, usually a no-no in FP
code, and it carries a great deal of inaccessible internal state.
These features are fine for OO, but not for FP.

I have a talk I've given several times discussing the ideas involved
in functional programming as applied to Javascript. [1] In this I
work through an example of some of the common functional programming
tools in Javascript, developing this fairly simple FP function of
the parameter `memberName`:

fetchData()
.then(get('tasks'))
.then(filter(propEq('member', memberName)))
.then(reject(propEq('complete', true)))
.then(map(pick(['id', 'dueDate', 'title', 'priority'])))
.then(sortBy(get('dueDate')));

out of this much more lengthy procedural version:

fetchData()
.then(function(data) {
return data.tasks;
})
.then(function(tasks) {
var results = [];
for (var i = 0, len = tasks.length; i < len; i++) {
if (tasks[i].member == memberName) {
results.push(tasks[i]);
}
}
return results;
})
.then(function(tasks) {
var results = [];
for (var i = 0, len = tasks.length; i < len; i++) {
if (!tasks[i].complete) {
results.push(tasks[i]);
}
}
return results;
})
.then(function(tasks) {
var results = [], task;
for (var i = 0, len = tasks.length; i < len; i++) {
task = tasks[i];
results.push({
id: task.id,
dueDate: task.dueDate,
title: task.title,
priority: task.priority
})
}
return results;
})
.then(function(tasks) {
tasks.sort(function(first, second) {
return first.dueDate - second.dueDate;
});
return tasks;
});

The first block is the kind of code we're trying to promote through
Ramda.

So thank you for your offer. And if you have other tools that you
think might fit, do please let us know.

-- Scott

[1] <http://scott.sauyet.com/Javascript/Talk/FunctionalProgramming>

Dr J R Stockton

unread,
Jun 3, 2014, 5:01:45 PM6/3/14
to
In comp.lang.javascript message <586acd4a-249d-4a91-a71a-9cd6187634dd@go
oglegroups.com>, Sun, 1 Jun 2014 19:28:38, Scott Sauyet
<scott....@gmail.com> posted:

>Dr J R Stockton wrote:
>> Scott Sauyet posted:
>>
>>> I'm looking for feedback on a new functional programming library for
>>> Javascript that I've been developing with a friend. [ ... ]
>>
>> If the library is not being written IN JavaScript (or even if it is),
>> you could consider implementing (maybe more efficiently) the improved
>> date object in <http://www.merlyn.demon.co.uk/js-dobj2.htm>. [ ... ]
>
>Although that looks to be interesting code, and an improvement on
>the existing Date constructor function in several important ways, I
>don't think it would be a good fit for Ramda.
>
>Ramda is about offering functional programming (FP) tools to the
>user.
> ...

Not only do I not understand how to use FP, I don't understand many of
the words used in writing about it. And I doubt whether I ever will.

>DATE2 is an OO construct, a constructor function with a beefy
>prototype object. It creates mutable objects, usually a no-no in FP
>code, and it carries a great deal of inaccessible internal state.
>These features are fine for OO, but not for FP.

Inaccessible internal state? AFAIR, and you'll have noticed the date of
the page, there should not be any. There is accessible state such as
DATE2.GMT, and there are internal variables in methods, and there is the
accessible date value. Otherwise, could you name an example?

The beefiness to which you refer is, I think, because DATE2 handles for
I/O many standard date formats, including ISO week numbering and (IIRC)
YMD using a single Roman character for the month, I-XII or i-xii. Also
it has to work round vexing features of the standard Object, such as
new Date(14, 7, 4) giving the (UK) start of WWI rather than a date in
the Year of the Consulship of Pompeius and Appuleius (767 AUC).

I think it would look simpler if it were implemented not IN JavaScript
but BY those who have coded the JavaScript Date Object in whatever
language was used.

OTOH, the Object does not do as much as it could about the dates of
Summer Time (I've only recently discovered that the end of Summer Time
can depend on the date of Easter Sunday).



>I have a talk I've given several times discussing the ideas involved
>in functional programming as applied to Javascript. [1]

>[1] <http://scott.sauyet.com/Javascript/Talk/FunctionalProgramming>

Includes "Not available in current versions Javascript" on slide 22.
Trivial - needs an "of". Important - Web pages persist, so there should
be a "current date" value given at the beginning.

Scott Sauyet

unread,
Jun 3, 2014, 10:15:43 PM6/3/14
to
Dr J R Stockton wrote:
> Scott Sauyet posted:
>>Dr J R Stockton wrote:
>>> Scott Sauyet posted:
>>>
>>>> I'm looking for feedback on a new functional programming library for
>>>> Javascript that I've been developing with a friend. [ ... ]
>>>
>>> If the library is not being written IN JavaScript (or even if it is),
>>> you could consider implementing (maybe more efficiently) the improved
>>> date object in <http://www.merlyn.demon.co.uk/js-dobj2.htm>. [ ... ]
>>
>> Although that looks to be interesting code, and an improvement on
>> the existing Date constructor function in several important ways, I
>> don't think it would be a good fit for Ramda.
>>
>> Ramda is about offering functional programming (FP) tools to the
>> user.
>> ...
>
> Not only do I not understand how to use FP, I don't understand many of
> the words used in writing about it. And I doubt whether I ever will.

Well, I'm no spring chicken, and I find I'm learning it, probably
more slowly than I would have thirty years ago, but still reasonable
well. I find it a more interesting way and a more powerful way to
program than some of the other models I've used.


>> DATE2 is an OO construct, a constructor function with a beefy
>> prototype object. It creates mutable objects, usually a no-no in FP
>> code, and it carries a great deal of inaccessible internal state.
>> These features are fine for OO, but not for FP.
>
> Inaccessible internal state? AFAIR, and you'll have noticed the date of
> the page, there should not be any. There is accessible state such as
> DATE2.GMT, and there are internal variables in methods, and there is the
> accessible date value. Otherwise, could you name an example?

I probably mispoke. There is a real difficulty, in fact a near
impossibility before ES6, in efficiently working with entirely
encapsulated data that is still avaialable to prototype functions.
So there is not likely to be totally inaccessible internal data that
is used by these prototype functions, but the internal Date object,
`this.Q` looks to me like something one *had better not* manipulate
for fear of undermining the integrity of the DATE2 object. Am I
mistaken about that?


> The beefiness to which you refer is, I think, because DATE2 handles for
> I/O many standard date formats, including ISO week numbering and (IIRC)
> YMD using a single Roman character for the month, I-XII or i-xii. Also
> it has to work round vexing features of the standard Object, such as
> new Date(14, 7, 4) giving the (UK) start of WWI rather than a date in
> the Year of the Consulship of Pompeius and Appuleius (767 AUC).

Although I didn't look at every detail, I did see the sorts of
things that this code did. While that's a nice chunk of work,
functional programming is more commonly about exploiting the
similarites between different sorts of objects, abstracting out
common patterns of use into shared functions. That almost necessitates
slim interfaces.


> I think it would look simpler if it were implemented not IN JavaScript
> but BY those who have coded the JavaScript Date Object in whatever
> language was used.

Well Ramda is a library for Javsacript, written in Javascript. So
it's probably no help here.


> OTOH, the Object does not do as much as it could about the dates of
> Summer Time (I've only recently discovered that the end of Summer Time
> can depend on the date of Easter Sunday).

Over the years, you've taught me a few surprising things about
dates, but that one's quite surprising. What are the circumstances
in which this occurs?


>> I have a talk I've given several times discussing the ideas involved
>> in functional programming as applied to Javascript. [1]
>
>> [1] <http://scott.sauyet.com/Javascript/Talk/FunctionalProgramming>
>
> Includes "Not available in current versions Javascript" on slide 22.
> Trivial - needs an "of". Important - Web pages persist, so there should
> be a "current date" value given at the beginning.

That's a very good idea. I will try to fix it next time I'm in
there editing it.


Thanks,

-- Scott

Dr J R Stockton

unread,
Jun 5, 2014, 6:41:50 PM6/5/14
to
In comp.lang.javascript message <d3bc8230-d5ec-4bf6-8cc6-5102cf3a4cc5@go
oglegroups.com>, Tue, 3 Jun 2014 19:15:43, Scott Sauyet
<scott....@gmail.com> posted:

>Dr J R Stockton wrote:

>> OTOH, the Object does not do as much as it could about the dates of
>> Summer Time (I've only recently discovered that the end of Summer Time
>> can depend on the date of Easter Sunday).
>
>Over the years, you've taught me a few surprising things about
>dates, but that one's quite surprising. What are the circumstances
>in which this occurs?

In much of Brazil, "Carnaval" is a *major* public festival held on the
weekend before Lent begins. Lent is of course locked to Easter, and in
Brazil occurs in late Summer or early Autumn, like the end of Summer
Time. I gather that they do *NOT* want to have a clock change, with a
repeated hour, during Carnaval. So, if that would happen by the
ordinary rule, TZ = BRT3BRST,M10.3.0/00:00,M2.3.0/00:00, they postpone
the end of Summer Time by a week.

Wikipedia knows about this; start at
<http://en.wikipedia.org/wiki/Daylight_saving_time_in_Brazil>

My js-date5.htm#SLGD has a button which reveals by calculation :-
Postponements in :
2007 2012 2015 2023 2026 2034 2037 2039 2042 2045 2048
2050 2053 2061 2064 2066 2072 2075 2077 2080 2091
2102 2105 2107 2110 2118 2121 2123 2129 2132 2134 2137 2145 2148

I'll have time to consider the rest of your reply tomorrow, I hope.

Scott Sauyet

unread,
Jun 6, 2014, 2:36:06 PM6/6/14
to
Dr J R Stockton wrote:
> Scott Sauyet posted:
>> Dr J R Stockton wrote:

>>> OTOH, the Object does not do as much as it could about the dates of
>>> Summer Time (I've only recently discovered that the end of Summer Time
>>> can depend on the date of Easter Sunday).
>>
>> Over the years, you've taught me a few surprising things about
>> dates, but that one's quite surprising. What are the circumstances
>> in which this occurs?
>
> In much of Brazil, "Carnaval" is a *major* public festival held on the
> weekend before Lent begins. Lent is of course locked to Easter, and in
> Brazil occurs in late Summer or early Autumn, like the end of Summer
> Time. I gather that they do *NOT* want to have a clock change, with a
> repeated hour, during Carnaval. So, if that would happen by the
> ordinary rule, TZ = BRT3BRST,M10.3.0/00:00,M2.3.0/00:00, they postpone
> the end of Summer Time by a week. [ ... ]

Very interesting. Thank you for the information. This stuff is
tricky -- one more reason not to include it in our should-remain-
simple library. :-)


> I'll have time to consider the rest of your reply tomorrow, I hope.

I'll look forward to it.


-- Scott

Dr J R Stockton

unread,
Jun 7, 2014, 6:13:30 PM6/7/14
to
In comp.lang.javascript message <d3bc8230-d5ec-4bf6-8cc6-5102cf3a4cc5@go
oglegroups.com>, Tue, 3 Jun 2014 19:15:43, Scott Sauyet
<scott....@gmail.com> posted:

>Dr J R Stockton wrote:
>> Scott Sauyet posted:
>>>Dr J R Stockton wrote:

>>> DATE2 is an OO construct, a constructor function with a beefy
>>> prototype object. It creates mutable objects, usually a no-no in FP
>>> code, and it carries a great deal of inaccessible internal state.
>>> These features are fine for OO, but not for FP.
>>
>> Inaccessible internal state? AFAIR, and you'll have noticed the date of
>> the page, there should not be any. There is accessible state such as
>> DATE2.GMT, and there are internal variables in methods, and there is the
>> accessible date value. Otherwise, could you name an example?
>
>I probably mispoke. There is a real difficulty, in fact a near
>impossibility before ES6, in efficiently working with entirely
>encapsulated data that is still avaialable to prototype functions.
>So there is not likely to be totally inaccessible internal data that
>is used by these prototype functions, but the internal Date object,
>`this.Q` looks to me like something one *had better not* manipulate
>for fear of undermining the integrity of the DATE2 object. Am I
>mistaken about that?

I hope so. Q should be the only internal state of the Object, and if it
is written to directly in the middle of a piece of code the effect is
the same as writing code with an object D of the built-in Date Object
type and throwing in a D.setTime(x). The DATE2 object is equally
healthy after that, but represents an altered value.

A degree of protection of Q against simpler minds might be obtained by
replacing it in the code with ?, which this mail system will probably
mung - it is the last letter of the real name of the capital city of
Greece, U+0391 - and in the comment and documentation with U+0410.

Readers can either use the Object with a little care, or take parts from
it; or, if strategically placed in the industry, implement it in the
same manner as the ordinary Object but with some different statements in
the code.

The page was intended mainly to show that a DATE2 Object could have many
more methods than a Date object - useful ones such as ISO Week Numberihg
Dates and Easter Sunday, and less common ones such as single-character
month fields.

Remember that my mind runs on ECMA 262 3rd Edn (& CSS 1), and is
unlikely to be much upgraded.

--
(c) John Stockton, nr London UK Reply address via Merlyn Home Page.
news:comp.lang.javascript FAQ <http://www.jibbering.com/faq/index.html>.
<http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
<http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.

billyro...@gmail.com

unread,
Mar 6, 2016, 1:23:04 PM3/6/16
to
On Tuesday, May 27, 2014 at 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.
>
> 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`.
>
Hi Scott,

I'm a front end developer that discovered Ramda by reading 'Dr Frisby's Mostly Adequate Guide to Functional Programming'.

Toward the end of the book the author starts using Folktale for things like Maybe, Task, IO that you mentioned Ramda might include.

Is there any plan to add these types of constructs to Ramda? Are they already there and I just haven't figured out the synonyms yet?

Either way, Ramda is extremely cool and I am very excited about using it!

Best,
Billy

Scott Sauyet

unread,
Mar 6, 2016, 8:52:35 PM3/6/16
to
billy roberts wrote:
> Scott Sauyet wrote:

(Please don't top-post on USENET, and also please trim your quotes
to only include what's relevant.)

>> RE: nearly two-year old announcement of Ramda, now found at
>> <https://github.com/ramda/ramda>

> I'm a front end developer that discovered Ramda by reading 'Dr
> Frisby's Mostly Adequate Guide to Functional Programming'.

An excellent book, IMHO!

> Toward the end of the book the author starts using Folktale for
> things like Maybe, Task, IO that you mentioned Ramda might include.
>
> Is there any plan to add these types of constructs to Ramda? Are
> they already there and I just haven't figured out the synonyms yet?

We decided not to include them directly in Ramda. Instead Ramda
delegates a number of functions, including nearly all of those in the
Fantasy Land [1] specification to similar method on the data object if
that exists. This means that Ramda should interoperate seamlessly with
any implementation of the Fantasy Land spec. For instance, Folktale's
`Maybe` [2] and `Either` [3] would work perfectly well with Ramda's `map`:

const square = n => n * n;
R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]
R.map(square, Maybe.Just(7)); //=> Maybe.Just(49)
R.map(square, Maybe.Nothing()); //=> Maybe.Nothing()
R.map(square, Either.Left("error msg"); //-=> Either.Left("error msg")
R.map(square, Either.Right(5)); //=> Either.Right(25)

Ramda also has a side project for building these. It is not as well
tested as Folktale's but it seems to be working well. You can find
it at

<https://github.com/ramda/ramda-fantasy>


> Either way, Ramda is extremely cool and I am very excited about
> using it!

Thank you. Although I do participate here and am happy to answer
questions when I can, this list mostly frowns on spending too much
energy on library-specific discussions (now that we seem to be done
endlessly criticizing jQuery for its myriad flaws.) A useful
alternative is Ramda's Gitter discussion list, found at

<https://gitter.im/ramda/ramda>

Welcome aboard!


[1]: <https://gitter.im/fantasyland/fantasy-land>
[2]: <https://github.com/folktale/data.maybe>
[3]: <https://github.com/folktale/data.either>

-- Scott

Evertjan.

unread,
Mar 7, 2016, 4:50:38 AM3/7/16
to
Scott Sauyet <scott....@gmail.com> wrote on 07 Mar 2016 in
comp.lang.javascript:

> (Please don't top-post on USENET, and also please trim your quotes
> to only include what's relevant.)

YES!

Full Definition of relevant:
a : having significant and demonstrable bearing on the matter at hand
b : affording evidence tending to prove or disprove the matter at issue
or under discussion <relevant testimony>
c : having social relevance


--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Reply all
Reply to author
Forward
0 new messages