Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #32193 > unrolled thread
| Started by | justaguy <lichunshen84@gmail.com> |
|---|---|
| First post | 2017-01-18 20:09 -0800 |
| Last post | 2017-01-20 05:02 +0000 |
| Articles | 20 — 6 participants |
Back to article view | Back to comp.lang.javascript
Functional Programming needs some real world use cases justaguy <lichunshen84@gmail.com> - 2017-01-18 20:09 -0800
Re: Functional Programming needs some real world use cases Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-19 20:10 +0000
Re: Functional Programming needs some real world use cases Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-01-19 21:16 +0100
Re: Functional Programming needs some real world use cases Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-19 21:24 +0000
Re: Functional Programming needs some real world use cases justaguy <lichunshen84@gmail.com> - 2017-01-19 12:34 -0800
Re: Functional Programming needs some real world use cases justaguy <lichunshen84@gmail.com> - 2017-01-19 12:41 -0800
Re: Functional Programming needs some real world use cases justaguy <lichunshen84@gmail.com> - 2017-01-19 13:01 -0800
Re: Functional Programming needs some real world use cases justaguy <lichunshen84@gmail.com> - 2017-01-19 17:26 -0800
Re: Functional Programming needs some real world use cases Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-19 21:23 +0000
Re: Functional Programming needs some real world use cases Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-19 21:50 +0000
Re: [Firefox]"print" Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-01-24 01:52 +0100
Re: [Firefox]"print" Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-01-24 05:45 +0100
Re: Functional Programming needs some real world use cases Scott Sauyet <scott@sauyet.com> - 2017-01-20 04:28 +0000
Re: Functional Programming needs some real world use cases justaguy <lichunshen84@gmail.com> - 2017-01-19 21:18 -0800
Re: Functional Programming needs some real world use cases John Harris <niam@jghnorth.org.uk.invalid> - 2017-01-20 10:22 +0000
Re: Functional Programming needs some real world use cases Scott Sauyet <scott@sauyet.com> - 2017-01-21 01:29 +0000
Re: Functional Programming needs some real world use cases Scott Sauyet <scott@sauyet.com> - 2017-01-21 01:15 +0000
Re: Functional Programming needs some real world use cases "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2017-01-21 15:00 -0800
Re: Functional Programming needs some real world use cases Scott Sauyet <scott@sauyet.com> - 2017-01-20 05:00 +0000
Re: Functional Programming needs some real world use cases Scott Sauyet <scott@sauyet.com> - 2017-01-20 05:02 +0000
| From | justaguy <lichunshen84@gmail.com> |
|---|---|
| Date | 2017-01-18 20:09 -0800 |
| Subject | Functional Programming needs some real world use cases |
| Message-ID | <8b2dc802-a0d2-4ae0-ba75-98ecf5989e64@googlegroups.com> |
Hi,
I'm starting to read about Functional Programming. The following is some sample code, which seems concise. In the meantime, I wonder if you have some idea of using other "action" other than "print", and of course, feel free to use other array "values" where appropriate.
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
forEach(["Wampeter", "Foma", "Granfalloon"], print);
Thanks.
[toc] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-19 20:10 +0000 |
| Message-ID | <87bmv2erpx.fsf@bsb.me.uk> |
| In reply to | #32193 |
justaguy <lichunshen84@gmail.com> writes:
> I'm starting to read about Functional Programming. The following is
> some sample code, which seems concise. In the meantime, I wonder if
> you have some idea of using other "action" other than "print", and of
> course, feel free to use other array "values" where appropriate.
>
> function forEach(array, action) {
> for (var i = 0; i < array.length; i++)
> action(array[i]);
> }
>
> forEach(["Wampeter", "Foma", "Granfalloon"], print);
As an exercise, what expression can you write in place of "..." to print
all seven strings (and just those):
forEach([["a","b","c"],["q","r"],["z"]], ...);
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2017-01-19 21:16 +0100 |
| Message-ID | <3131945.LM0AJKV5NW@PointedEars.de> |
| In reply to | #32198 |
Ben Bacarisse wrote:
> justaguy <lichunshen84@gmail.com> writes:
>> function forEach(array, action) {
>> for (var i = 0; i < array.length; i++)
>> action(array[i]);
>> }
>>
>> forEach(["Wampeter", "Foma", "Granfalloon"], print);
>
> As an exercise, what expression can you write in place of "..." to print
> all seven strings (and just those):
>
> forEach([["a","b","c"],["q","r"],["z"]], ...);
Seven?
--
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-19 21:24 +0000 |
| Message-ID | <87r33yd9pp.fsf@bsb.me.uk> |
| In reply to | #32199 |
Thomas 'PointedEars' Lahn <PointedEars@web.de> writes:
> Ben Bacarisse wrote:
>
>> justaguy <lichunshen84@gmail.com> writes:
>>> function forEach(array, action) {
>>> for (var i = 0; i < array.length; i++)
>>> action(array[i]);
>>> }
>>>
>>> forEach(["Wampeter", "Foma", "Granfalloon"], print);
>>
>> As an exercise, what expression can you write in place of "..." to print
>> all seven strings (and just those):
>>
>> forEach([["a","b","c"],["q","r"],["z"]], ...);
>
> Seven?
Thanks, I meant six.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | justaguy <lichunshen84@gmail.com> |
|---|---|
| Date | 2017-01-19 12:34 -0800 |
| Message-ID | <6b8d9806-b427-4b74-b74f-b582cf1ceba1@googlegroups.com> |
| In reply to | #32198 |
On Thursday, January 19, 2017 at 3:10:25 PM UTC-5, Ben Bacarisse wrote:
> justaguy writes:
>
> > I'm starting to read about Functional Programming. The following is
> > some sample code, which seems concise. In the meantime, I wonder if
> > you have some idea of using other "action" other than "print", and of
> > course, feel free to use other array "values" where appropriate.
> >
> > function forEach(array, action) {
> > for (var i = 0; i < array.length; i++)
> > action(array[i]);
> > }
> >
> > forEach(["Wampeter", "Foma", "Granfalloon"], print);
>
> As an exercise, what expression can you write in place of "..." to print
> all seven strings (and just those):
>
> forEach([["a","b","c"],["q","r"],["z"]], ...);
>
> --
> Ben.
console.log
you have three arrays inside an array
[toc] | [prev] | [next] | [standalone]
| From | justaguy <lichunshen84@gmail.com> |
|---|---|
| Date | 2017-01-19 12:41 -0800 |
| Message-ID | <a8be0d39-6f93-4051-9fc9-1827446a02d0@googlegroups.com> |
| In reply to | #32201 |
On Thursday, January 19, 2017 at 3:35:09 PM UTC-5, justaguy wrote:
> On Thursday, January 19, 2017 at 3:10:25 PM UTC-5, Ben Bacarisse wrote:
> > justaguy writes:
> >
> > > I'm starting to read about Functional Programming. The following is
> > > some sample code, which seems concise. In the meantime, I wonder if
> > > you have some idea of using other "action" other than "print", and of
> > > course, feel free to use other array "values" where appropriate.
> > >
> > > function forEach(array, action) {
> > > for (var i = 0; i < array.length; i++)
> > > action(array[i]);
> > > }
> > >
> > > forEach(["Wampeter", "Foma", "Granfalloon"], print);
> >
> > As an exercise, what expression can you write in place of "..." to print
> > all seven strings (and just those):
> >
> > forEach([["a","b","c"],["q","r"],["z"]], ...);
> >
> > --
> > Ben.
>
> console.log
>
> you have three arrays inside an array
console.log is another action, that does not solve your problem. Yours seems tricky.
[toc] | [prev] | [next] | [standalone]
| From | justaguy <lichunshen84@gmail.com> |
|---|---|
| Date | 2017-01-19 13:01 -0800 |
| Message-ID | <dd1317b4-8b1e-4594-bb85-6834f47d477c@googlegroups.com> |
| In reply to | #32203 |
On Thursday, January 19, 2017 at 3:41:27 PM UTC-5, justaguy wrote:
> On Thursday, January 19, 2017 at 3:35:09 PM UTC-5, justaguy wrote:
> > On Thursday, January 19, 2017 at 3:10:25 PM UTC-5, Ben Bacarisse wrote:
> > > justaguy writes:
> > >
> > > > I'm starting to read about Functional Programming. The following is
> > > > some sample code, which seems concise. In the meantime, I wonder if
> > > > you have some idea of using other "action" other than "print", and of
> > > > course, feel free to use other array "values" where appropriate.
> > > >
> > > > function forEach(array, action) {
> > > > for (var i = 0; i < array.length; i++)
> > > > action(array[i]);
> > > > }
> > > >
> > > > forEach(["Wampeter", "Foma", "Granfalloon"], print);
> > >
> > > As an exercise, what expression can you write in place of "..." to print
> > > all seven strings (and just those):
> > >
> > > forEach([["a","b","c"],["q","r"],["z"]], ...);
> > >
> > > --
> > > Ben.
> >
> > console.log
> >
> > you have three arrays inside an array
>
> console.log is another action, that does not solve your problem. Yours seems tricky.
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
// if (Array.isArray(i)) {
if ( i === Array ) {
for (var i2 = 0; i2 < i.length; i2++)
action(i[i2]);
}
else {
action(array[i]);
}
}
I'm a bit puzzled, the above code executes the else portion for
[["a","b","c"],["q","r"],["z"]] data
Probably we should stick with the original code but use another "action", but what's that? Thanks.
[toc] | [prev] | [next] | [standalone]
| From | justaguy <lichunshen84@gmail.com> |
|---|---|
| Date | 2017-01-19 17:26 -0800 |
| Message-ID | <2904795a-c86f-4a52-be28-e4f7bb8efbfe@googlegroups.com> |
| In reply to | #32205 |
On Thursday, January 19, 2017 at 4:01:31 PM UTC-5, justaguy wrote:
> On Thursday, January 19, 2017 at 3:41:27 PM UTC-5, justaguy wrote:
> > On Thursday, January 19, 2017 at 3:35:09 PM UTC-5, justaguy wrote:
> > > On Thursday, January 19, 2017 at 3:10:25 PM UTC-5, Ben Bacarisse wrote:
> > > > justaguy writes:
> > > >
> > > > > I'm starting to read about Functional Programming. The following is
> > > > > some sample code, which seems concise. In the meantime, I wonder if
> > > > > you have some idea of using other "action" other than "print", and of
> > > > > course, feel free to use other array "values" where appropriate.
> > > > >
> > > > > function forEach(array, action) {
> > > > > for (var i = 0; i < array.length; i++)
> > > > > action(array[i]);
> > > > > }
> > > > >
> > > > > forEach(["Wampeter", "Foma", "Granfalloon"], print);
> > > >
> > > > As an exercise, what expression can you write in place of "..." to print
> > > > all seven strings (and just those):
> > > >
> > > > forEach([["a","b","c"],["q","r"],["z"]], ...);
> > > >
> > > > --
> > > > Ben.
> > >
> > > console.log
> > >
> > > you have three arrays inside an array
> >
> > console.log is another action, that does not solve your problem. Yours seems tricky.
>
>
> function forEach(array, action) {
> for (var i = 0; i < array.length; i++)
> // if (Array.isArray(i)) {
> if ( i === Array ) {
> for (var i2 = 0; i2 < i.length; i2++)
> action(i[i2]);
> }
> else {
> action(array[i]);
> }
> }
>
> I'm a bit puzzled, the above code executes the else portion for
> [["a","b","c"],["q","r"],["z"]] data
>
> Probably we should stick with the original code but use another "action", > but what's that? Thanks.
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
// if (Array.isArray(i)) {
/*
if ( i === Array ) {
for (var i2 = 0; i2 < i.length; i2++)
action(i[i2]);
}
else {
action(array[i]);
}
*/
}
var recurse = function (i) {
if ( i === Array ) {
for (var i2 = 0; i2 < i.length; i2++)
// print(i[i2]);
// console.log('element is array:' + i[i2]);
return document.getElementById('output').innerHTML += 'element is array:' + i[i2] + ',';
}
else {
// print([i]);
return document.getElementById('output').innerHTML += [i] + ',';
}
}
caller = forEach([["a","b","c"],["q","r"],["z"]], recurse);
it puts a, b, c, q, r, z on the page. Hmm, I'll see if I can manage to get the browser print function in as well later ...
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-19 21:23 +0000 |
| Message-ID | <87ziimd9rr.fsf@bsb.me.uk> |
| In reply to | #32198 |
ram@zedat.fu-berlin.de (Stefan Ram) writes: > Ben Bacarisse <ben.usenet@bsb.me.uk> writes: >>As an exercise, what expression can you write in place of "..." to print >>all seven strings (and just those): >>forEach([["a","b","c"],["q","r"],["z"]], ...); > > Ok, the easy part is: Why would you post the answer to an exercise? <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-19 21:50 +0000 |
| Message-ID | <87lgu6d8hv.fsf@bsb.me.uk> |
| In reply to | #32206 |
ram@zedat.fu-berlin.de (Stefan Ram) writes: > Ben Bacarisse <ben.usenet@bsb.me.uk> writes: >>ram@zedat.fu-berlin.de (Stefan Ram) writes: >>>Ben Bacarisse <ben.usenet@bsb.me.uk> writes: >>>>As an exercise, what expression can you write in place of "..." to print >>>>all seven strings (and just those): >>>>forEach([["a","b","c"],["q","r"],["z"]], ...); >>>Ok, the easy part is: >>Why would you post the answer to an exercise? > > If it was an exercise made especially for justaguy: > He does not seem to have read my answer. > > Otherwise, if it was an exercise made for everybody: > Then it would have been appropriate for me to answer. Anyone who posts an answer should add a spoiler alert (unless some significant time has elapsed). I should have said "why post the answer to an exercise without a spoiler alert or some obfuscation". You can post answers all you like, but it does not help others if they see them immediately. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2017-01-24 01:52 +0100 |
| Subject | Re: [Firefox]"print" |
| Message-ID | <42447262.MN2xkq1pzW@PointedEars.de> |
| In reply to | #32198 |
Stefan Ram kept talking to himself: > ram@zedat.fu-berlin.de (Stefan Ram) writes: >> Let's look at the property: >> Object.getOwnPropertyDescriptor( this, print ) >> undefined > > Ok, I should have written: > > Object.getOwnPropertyDescriptor( this, "print" ) “print” in Mozilla JavaScript is still something else than “this.print” (in global browser context equivalent to “window.print”): | $ dpkg -l libmozjs-24-bin | grep ^.i | ii libmozjs-24-bin 24.2.0-2 amd64 Spidermonkey JavaScript shell | | $ dpkg -L libmozjs-24-bin | /. | /usr | /usr/bin | /usr/bin/js24 | /usr/share | /usr/share/doc | /usr/share/doc/libmozjs-24-bin | /usr/share/doc/libmozjs-24-bin/changelog.Debian.gz | /usr/share/doc/libmozjs-24-bin/copyright | | $ js24 | js> help(print); | JavaScript-C24.2.0 | print([exp ...]) | Evaluate and print expressions to stdout. | js> By contrast, | $ js --help | head -n 1 | Usage: node [options] [ -e script | script.js ] [arguments] | | $ js -v | v0.10.38 Node.js 0.10.38, … | $ js -e 'console.log(process.versions.v8);' | 3.14.5.8 based on Google V8 JavaScript 3.14.5.8): | $ js -e 'print(42);' | | [eval]:1 | print(42); | ^ | ReferenceError: print is not defined | at [eval]:1:1 | at Object.<anonymous> ([eval]-wrapper:6:22) | at Module._compile (module.js:456:26) | at evalScript (node.js:536:25) | at startup (node.js:80:7) | at node.js:906:3 So this has nothing to do with Firefox and its Web Console, everything with the ECMAScript implementation (provided by the Gecko layout engine) that is used by it. It is most obvious in the result of what you have *not* tried so far: ,-[Iceweasel 38.1.0 Web Console] | | 01:28:04.562 > print(); | 01:28:04.569 < "undefined" | 01:28:09.221 > print | 01:28:09.230 < function JSTH_print() | 01:28:16.522 > this.print | 01:28:16.538 < function print() | 01:31:00.768 > window.print | 01:31:00.775 < function print() | 01:31:13.967 > this.print === window.print | 01:31:13.974 < true | 01:31:49.429 > print(42); | 01:31:49.436 < "42" (Exercise: Try the same in Chromium or Chrome.) -- PointedEars FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix> <https://github.com/PointedEars> | <http://PointedEars.de/wsvn/> Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2017-01-24 05:45 +0100 |
| Subject | Re: [Firefox]"print" |
| Message-ID | <2500325.yaVYbkx8dN@PointedEars.de> |
| In reply to | #32283 |
Thomas 'PointedEars' Lahn wrote: > ,-[Iceweasel 38.1.0 Web Console] > | > | 01:28:04.562 > print(); > | 01:28:04.569 < "undefined" > | 01:28:09.221 > print > | 01:28:09.230 < function JSTH_print() > | 01:28:16.522 > this.print > | 01:28:16.538 < function print() > | 01:31:00.768 > window.print > | 01:31:00.775 < function print() > | 01:31:13.967 > this.print === window.print > | 01:31:13.974 < true > | 01:31:49.429 > print(42); > | 01:31:49.436 < "42" > > (Exercise: Try the same in Chromium or Chrome. […] … What happens and why does it happen?) -- PointedEars FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix> <https://github.com/PointedEars> | <http://PointedEars.de/wsvn/> Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott@sauyet.com> |
|---|---|
| Date | 2017-01-20 04:28 +0000 |
| Message-ID | <o5s3l1$ahq$1@dont-email.me> |
| In reply to | #32193 |
justaguy wrote:
> I'm starting to read about Functional Programming. The following is
> some sample code, which seems concise.
Concise, even elegant, code is one of the hallmarks of functional
programming. But I would suggest that you don't seek it as an initial
goal. Look to other main facets: immutability, referential transparency,
systems built by composing smaller functions.
As you learn functional techniques, concise code will likely emerge on
its own.
> In the meantime, I wonder if you
> have some idea of using other "action" other than "print", and of
> course, feel free to use other array "values" where appropriate.
>
> function forEach(array, action) {
> for (var i = 0; i < array.length; i++)
> action(array[i]);
> }
>
> forEach(["Wampeter", "Foma", "Granfalloon"], print);
`forEach` is not really an example of functional programming. One of the
key tenets of functional programming is that code must be referentially
transparent. This means that any expression could be replaced with its
value with no change to the behavior of the system. For functions this
means that they must be *pure* (their results must depend only on their
parameters) and that they must have no side effects (all they can do is
to return a result.) Your `print` statement fails the last, as do any
reasonable uses of `forEach`.
Note that by this definition, no useful programs can be entirely
functional, since they could never take any input nor return any output.
Although this is often glossed over, the main point is that side effects
should be limited to a very thin shell of your system, leaving a
functional core.
-----
Examples with `map`, `filter`, or `reduce` would demonstrate functional
behavior significantly better. `map` is especially interesting, as it
can expand into discussions of Functors and from there into other
Algebraic Data Types.
Such functions do not have to be considered only as methods of
`Array.prototype`. You can write your own:
function map1(fn, list) {
const result = new Array(list.length);
for (let i = 0; i < list.length; i++) {
result[i] = fn(list[i]);
}
return result;
}
which might be used like this:
const toUpper = (str) => str.toUpperCase();
const square = (n) => n * n;
map1(toUpper, ['foo', 'bar', 'baz']);
//=> ["FOO", "BAR", "BAZ"]
map1(square, [1, 2, 3, 4, 5])
//=> [1, 4, 9, 16, 25]
Or you might make a somewhat more sophisticated version such as this:
function map2(fn, list) {
const m = function(list) {
const result = new Array(list.length);
for (let i = 0; i < list.length; i++) {
result[i] = fn(list[i]);
}
return result;
};
return arguments.length > 1 ? m(list) : m;
}
// works the same for two arguments:
map2(toUpper, ['foo', 'bar', 'baz']);
//=> ["FOO", "BAR", "BAZ"]
map2(square, [1, 2, 3, 4, 5])
//=> [1, 4, 9, 16, 25]
// returns a new function when supplied only the first argument:
const squareAll = map2(square);
squareAll([1, 2, 3, 4, 5]);
//=> [1, 4, 9, 16, 25]
You might wonder why we shouldn't write it like this:
function map3(fn, list) {
return list.map(fn);
}
map3(parseFloat, ['1.1', '2.2', '3.3']);
//=> [1.1, 2.2, 3.3]
We could. But we might run into some unfortunate situations caused by
Array.prototype.map that we don't want to deal with [1]:
map3(parseInt, ['1', '2', '3']);
//=> [1, NaN, NaN]
Or you could use one of the many libraries available to help with
functional programming in JS. I'm one of the principle authors of Ramda
[2], which has become quite a popular library for doing FP in JS. It
provides several hundred functions for working with lists, functions,
objects, strings, and algebraic data types. Sanctuary [3] stated as a
companion library to Ramda, but is growing beyond that. It is a more
principled, and more opinionated library than Ramda, perhaps less
accessible to the beginner, but more aligned with pure FP languages.
Underscore [4] and lodash [5] are more general-purpose libraries, similar
in scope to Ramda: overall more popular, but much less focused on pure FP.
And there are many more.
-----
There are two excellent books online that help teach functional
programming using Javascript. Reg Braithewaite's _JavaScript Allongé_
[6] and Brian Lonsdorf's _Professor Frisby's Mostly Adequate Guide to
Functional Programming_. [7] Braithewaite simply reimagines programming
with the function as its key element and derives some very powerful, and
surprisingly eloquent, principles from that. Lonsdorf builds up much of
the standard functional programming arsenal using nothing but basic
Javascript; although it moves logically, and very clearly, once he builds
up steam, it begins to become challenging to keep up; but the first two
thirds of the book should be accessible to anyone.
_____
[1]: There are many explanations of this around. Here's one: <http://
stackoverflow.com/questions/262427/javascript-arraymap-and-parseint>
[2]: <http://ramdajs.com>
[3]: <https://sanctuary.js.org/>
[4]: http://underscorejs.org/
[5]: https://lodash.com/
[6]: I'm partial to the first edition of this book because of its
simplicity: <https://leanpub.com/javascript-allonge>, but the ES6 edition
may be more practical these days: <https://leanpub.com/
javascriptallongesix/>
[7]: <https://github.com/MostlyAdequate/mostly-adequate-guide>
-- Scott
[toc] | [prev] | [next] | [standalone]
| From | justaguy <lichunshen84@gmail.com> |
|---|---|
| Date | 2017-01-19 21:18 -0800 |
| Message-ID | <42e9d095-5f91-420c-b0a7-4371cce24f8b@googlegroups.com> |
| In reply to | #32213 |
On Thursday, January 19, 2017 at 11:30:01 PM UTC-5, Scott Sauyet wrote:
> justaguy wrote:
>
> > I'm starting to read about Functional Programming. The following is
> > some sample code, which seems concise.
>
> Concise, even elegant, code is one of the hallmarks of functional
> programming. But I would suggest that you don't seek it as an initial
> goal. Look to other main facets: immutability, referential transparency,
> systems built by composing smaller functions.
>
> As you learn functional techniques, concise code will likely emerge on
> its own.
>
>
> > In the meantime, I wonder if you
> > have some idea of using other "action" other than "print", and of
> > course, feel free to use other array "values" where appropriate.
> >
> > function forEach(array, action) {
> > for (var i = 0; i < array.length; i++)
> > action(array[i]);
> > }
> >
> > forEach(["Wampeter", "Foma", "Granfalloon"], print);
>
>
> `forEach` is not really an example of functional programming. One of the
> key tenets of functional programming is that code must be referentially
> transparent. This means that any expression could be replaced with its
> value with no change to the behavior of the system. For functions this
> means that they must be *pure* (their results must depend only on their
> parameters) and that they must have no side effects (all they can do is
> to return a result.) Your `print` statement fails the last, as do any
> reasonable uses of `forEach`.
>
> Note that by this definition, no useful programs can be entirely
> functional, since they could never take any input nor return any output.
> Although this is often glossed over, the main point is that side effects
> should be limited to a very thin shell of your system, leaving a
> functional core.
>
> -----
>
> Examples with `map`, `filter`, or `reduce` would demonstrate functional
> behavior significantly better. `map` is especially interesting, as it
> can expand into discussions of Functors and from there into other
> Algebraic Data Types.
>
> Such functions do not have to be considered only as methods of
> `Array.prototype`. You can write your own:
>
> function map1(fn, list) {
> const result = new Array(list.length);
> for (let i = 0; i < list.length; i++) {
> result[i] = fn(list[i]);
> }
> return result;
> }
>
> which might be used like this:
>
> const toUpper = (str) => str.toUpperCase();
> const square = (n) => n * n;
>
> map1(toUpper, ['foo', 'bar', 'baz']);
> //=> ["FOO", "BAR", "BAZ"]
>
> map1(square, [1, 2, 3, 4, 5])
> //=> [1, 4, 9, 16, 25]
>
> Or you might make a somewhat more sophisticated version such as this:
>
> function map2(fn, list) {
> const m = function(list) {
> const result = new Array(list.length);
> for (let i = 0; i < list.length; i++) {
> result[i] = fn(list[i]);
> }
> return result;
> };
> return arguments.length > 1 ? m(list) : m;
> }
>
> // works the same for two arguments:
>
> map2(toUpper, ['foo', 'bar', 'baz']);
> //=> ["FOO", "BAR", "BAZ"]
> map2(square, [1, 2, 3, 4, 5])
> //=> [1, 4, 9, 16, 25]
>
> // returns a new function when supplied only the first argument:
>
> const squareAll = map2(square);
> squareAll([1, 2, 3, 4, 5]);
> //=> [1, 4, 9, 16, 25]
>
> You might wonder why we shouldn't write it like this:
>
> function map3(fn, list) {
> return list.map(fn);
> }
>
> map3(parseFloat, ['1.1', '2.2', '3.3']);
> //=> [1.1, 2.2, 3.3]
>
> We could. But we might run into some unfortunate situations caused by
> Array.prototype.map that we don't want to deal with [1]:
>
> map3(parseInt, ['1', '2', '3']);
> //=> [1, NaN, NaN]
>
> Or you could use one of the many libraries available to help with
> functional programming in JS. I'm one of the principle authors of Ramda
> [2], which has become quite a popular library for doing FP in JS. It
> provides several hundred functions for working with lists, functions,
> objects, strings, and algebraic data types. Sanctuary [3] stated as a
> companion library to Ramda, but is growing beyond that. It is a more
> principled, and more opinionated library than Ramda, perhaps less
> accessible to the beginner, but more aligned with pure FP languages.
> Underscore [4] and lodash [5] are more general-purpose libraries, similar
> in scope to Ramda: overall more popular, but much less focused on pure FP.
> And there are many more.
>
> -----
>
> There are two excellent books online that help teach functional
> programming using Javascript. Reg Braithewaite's _JavaScript Allongé_
> [6] and Brian Lonsdorf's _Professor Frisby's Mostly Adequate Guide to
> Functional Programming_. [7] Braithewaite simply reimagines programming
> with the function as its key element and derives some very powerful, and
> surprisingly eloquent, principles from that. Lonsdorf builds up much of
> the standard functional programming arsenal using nothing but basic
> Javascript; although it moves logically, and very clearly, once he builds
> up steam, it begins to become challenging to keep up; but the first two
> thirds of the book should be accessible to anyone.
>
>
> _____
>
> [1]: There are many explanations of this around. Here's one: <http://
> stackoverflow.com/questions/262427/javascript-arraymap-and-parseint>
>
> [2]: <http://ramdajs.com>
>
> [3]: <https://sanctuary.js.org/>
>
> [4]: http://underscorejs.org/
>
> [5]: https://lodash.com/
>
> [6]: I'm partial to the first edition of this book because of its
> simplicity: <https://leanpub.com/javascript-allonge>, but the ES6 edition
> may be more practical these days: <https://leanpub.com/
> javascriptallongesix/>
>
> [7]: <https://github.com/MostlyAdequate/mostly-adequate-guide>
>
> -- Scott
Thank you.
[toc] | [prev] | [next] | [standalone]
| From | John Harris <niam@jghnorth.org.uk.invalid> |
|---|---|
| Date | 2017-01-20 10:22 +0000 |
| Message-ID | <l5p38cd873umflfgl2l2r6b50oa4kpsi5i@4ax.com> |
| In reply to | #32213 |
On Fri, 20 Jan 2017 04:28:17 -0000 (UTC), Scott Sauyet <scott@sauyet.com> wrote: <snip> >Note that by this definition, no useful programs can be entirely >functional, since they could never take any input nor return any output. Just like ECMAScript, the core language, then :-) >Although this is often glossed over, the main point is that side effects >should be limited to a very thin shell of your system, leaving a >functional core. <snip> Are the DOM and similar environments a "thin" shell ? John
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott@sauyet.com> |
|---|---|
| Date | 2017-01-21 01:29 +0000 |
| Message-ID | <o5udgu$obk$2@dont-email.me> |
| In reply to | #32221 |
John Harris wrote: > Scott Sauyet wrote: > <snip> >> Note that by this definition, no useful programs can be entirely >> functional, since they could never take any input nor return any >> output. > > Just like ECMAScript, the core language, then :-) Exactly. :-) >> Although this is often glossed over, the main point is that side >> effects should be limited to a very thin shell of your system, leaving >> a functional core. > > Are the DOM and similar environments a "thin" shell ? No, but if you're going to write functional Javascript for a DOM environment, the idea would be to keep all the core data transformations, all the fundamental logic, together and central, and relegate your code that actually interacts with the DOM to the edges of your program. In compile-to-JS languages like PureScript, this may actually be enforced, requiring you to use Monads to encapsulate side effects. (I'm guessing; I have yet to try PureScript, but given it's close ties with Haskell, it seems a likely guess.) In Javascript, you would have to manage this yourself. I've seen people simply physically separate and comment as such the pure code and impure code. Or it could be done via naming conventions, file layout conventions, whatever... -- Scott
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott@sauyet.com> |
|---|---|
| Date | 2017-01-21 01:15 +0000 |
| Message-ID | <o5uco5$obk$1@dont-email.me> |
| In reply to | #32213 |
Stefan Ram wrote: > Scott Sauyet writes: >> key tenets of functional programming is that code must be referentially >> transparent. This means that any expression could be replaced with its >> value with no change to the behavior of the system. > > »2« is an example of an expression. An expression is part of the > source code. > > A value is abstract, it is not source text like an expression. > > Therefore, an expression cannot be replaced by a value in the source > code. Have you been hanging out with the pedants again? "an expression could be replaced with a representation of its value with no change to the behavior of the system." Does that satisfy you? > An expression, however, can be replaced by another expression equal in > value. If this can be done without changing the meaning of a program > it is what Søndergaard and Sestof call »substitutivity of identity«. > [ ... ] Thank you for that reference. I had not read their paper although I'd read many of their sources, including Landin, Strachey, and even Quine (I just knew that philosophy course would come in handy!) I never quite made it through the _Principia_ (ok, I never quite made it through the first 20 pages of the _Principia_; I bore easily!) But I find the meaning as commonly used in computing perfectly reasonable, and don't need to go back to Quine to infer a deeper meaning for the phrase/ > Other concepts that sometimes are used as definitions of »referential > transparency« are extensionality, definiteness and unfoldability, all > independed properties! See also > > http://www.purl.org/stefan_ram/pub/referential_transparency Sure, but I think that for most of us, the definition above has come to dominate the alternatives. At least for the uses in computer science. I know nothing about linguistics or the other such places. -- Scott
[toc] | [prev] | [next] | [standalone]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2017-01-21 15:00 -0800 |
| Message-ID | <66b6ed25-01ad-4ada-aa6d-f08bc69eee7e@googlegroups.com> |
| In reply to | #32213 |
Scott Sauyet wrote:
> Note that by this definition, no useful programs can be entirely
> functional, since they could never take any input nor return any output.
> Although this is often glossed over, the main point is that side effects
> should be limited to a very thin shell of your system, leaving a
> functional core.
Hardly. That is what Codata is all about.
Reading from I/O can be represented by a Stream<T> or Observable<T> depending on whether it is an Interactive (List of all prime numbers) or Reactive (The current system time)
Writing to I/O can be represented by a dual which doesn't have a return type
Sink<T>
Imagine:
interface Console {
write(value: String): Nothing
}
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott@sauyet.com> |
|---|---|
| Date | 2017-01-20 05:00 +0000 |
| Message-ID | <o5s5h9$ahq$2@dont-email.me> |
| In reply to | #32193 |
Stefan Ram wrote:
> justaguy writes:
>> In the meantime, I wonder if you have some idea of using other "action"
>> other than "print", and of course, feel free to use other array
>> "values" where appropriate.
>
> I do not proceed in that way. I do not like the tool-
> looking-for-a-job approach. Rather I am used to start with
> requirements and then search for appropriate tools.
> [ ... ]
ACK
>> function forEach(array, action) {
>> for (var i = 0; i < array.length; i++)
>> action(array[i]);
>> }
>
> To me, pure functional programming (independent of JavaScript) does
> not involve changing state such as »i« above. So I do not deem the
> above to be purely functional.
I think you need to be able to compromise on this a bit in Javascript, at
least until proper tail call optimization is widespread. [1] The
alternative to such iteration is managed with recursion, but that is not
practical for anything but relatively small data structures in JS.
My take, and that of the FP library I help maintain (Ramda [2]) is that
such reassignment must happen inside a function, and ideally inside a
function that's buried in a library, rather than in a user's code.
> Of course, most procedural programs
> contain some parts of functional programming, but in this sense
> "everything" is functional a bit.
I don't follow this. The reverse is clear enough. Any FP program, in
order to interact with the world, must contain some part that is not
entirely pure. But why do you say everything must have functional
sections? I don't see that at all.
> For example, they say C is procedural, not functional. Yet you can
> write
> static void foreach( void( * const f )( char const * const )t
> , ... )
> { va_list ap;
> va_start( ap, f );
> while( 1 )
> { char const * const s = va_arg( ap, char const * const );
^^^^^
> if( s )f( s ); else break; }
> va_end( ap ); }
AFAICT, by reassigning `s` on each iteration, this has the same sort of
behavior. (My always weak C is pretty rusty, though.) I believe you
would need a recursive solution to avoid this.
> Go and read a book about Haskell!
While this is good advice, it doesn't really help answer questions about
how much and what kind of FP one can do in JS.
_____
[1]: Kangax's ES6 tables don't give much hope. At the time of this
writing, they show only the most recent Safari (desktop and iOS 10) and
the Kinoma XS6 server meeting the specification for proper tail calls:
<https://kangax.github.io/compat-table/es6/#test-proper_tail_calls_%
28tail_call_optimisation%29>
-- Scott
[2]: <http://ramdajs.com>
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott@sauyet.com> |
|---|---|
| Date | 2017-01-20 05:02 +0000 |
| Message-ID | <o5s5li$ahq$3@dont-email.me> |
| In reply to | #32193 |
Stefan Ram wrote: > Can Programming Be Liberated from the von Neumann Style? A > Functional Style and Its Algebra of Programs - John Backus (1978-08) > > And IIRC, this is the work that usually is said to have triggered the > interest in functional programming. It may have accelerated interest. But LISP, which is mostly used as a functional language, had already been around two decades by the time Backus published this pager. -- Scott
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web