···11-# Function composition
22-33-I am going to talk a lot about the `compose` function. It is basically function composition:
44-55-```
66- +-------------> f o g ------------+
77- | |
88- | v
99-+-+-+ +------+ +---------+
1010-| x | -> g -> | g(x) | -> f -> | f(g(x)) |
1111-+---+ +------+ +---------+
1212-```
1313-1414-```js
1515-const upcase = x => x.toUpperCase();
1616-const excl = x => `${x}!`;
1717-const shout = x => excl(upcase(x));
1818-1919-console.log(shout("gal is awesome"));
2020-```
2121-2222-The more functions we compose, the ugly it looks. Let's make it better.
2323-2424-```js
2525-const upcase = x => x.toUpperCase();
2626-const excl = x => `${x}!`;
2727-2828-const compose = (f, g) => x => f(g(x));
2929-3030-const shout = compose(upcase, excl); // x => upcase(excl(x))
3131-console.log(shout("gal is more than awesome"));
3232-```
3333-3434-What just happened?
3535-3636-```js
3737-// ("gal")
3838-const shout = compose(upcase, excl);
3939-// ("gal")
4040-const shout = compose(upcase, excl);
4141-// ("gal!")
4242-const shout = compose(upcase, excl);
4343-// ("GAL!")
4444-const shout = compose(upcase, excl);
4545-```
4646-4747-GREAET ANIMATION! And if we'd like to implement `compose` for more than just 2 functions (`sanctuary` doesn't support
4848-it, but `ramda` does)
4949-5050-```js
5151-const upcase = x => x.toUpperCase();
5252-const excl = x => `${x}!`;
5353-const addIrcChatBubble = name => text => `<${name}> ${text}`;
5454-5555-const compose = (...fns) => x => fns.reduceRight((acc, currFn) => currFn(acc), x);
5656-5757-const firstExample = addIrcChatBubble("gal")(upcase(excl("hello everyone")));
5858-const secondExample = compose(addIrcChatBubble("gal"), upcase, excl)("hello everyone"); // extract shout!
5959-6060-console.log({ firstExample, secondExample });
6161-```
+61
talk01/03_function_composition.md
···11+# Function composition
22+33+I am going to talk a lot about the `compose` function. It is basically function composition:
44+55+```
66+ +-------------> f o g ------------+
77+ | |
88+ | v
99++-+-+ +------+ +---------+
1010+| x | -> g -> | g(x) | -> f -> | f(g(x)) |
1111++---+ +------+ +---------+
1212+```
1313+1414+```js
1515+const upcase = x => x.toUpperCase();
1616+const excl = x => `${x}!`;
1717+const shout = x => excl(upcase(x));
1818+1919+console.log(shout("gal is awesome"));
2020+```
2121+2222+The more functions we compose, the ugly it looks. Let's make it better.
2323+2424+```js
2525+const upcase = x => x.toUpperCase();
2626+const excl = x => `${x}!`;
2727+2828+const compose = (f, g) => x => f(g(x));
2929+3030+const shout = compose(upcase, excl); // x => upcase(excl(x))
3131+console.log(shout("gal is more than awesome"));
3232+```
3333+3434+What just happened?
3535+3636+```js
3737+// ("gal")
3838+const shout = compose(upcase, excl);
3939+// ("gal")
4040+const shout = compose(upcase, excl);
4141+// ("gal!")
4242+const shout = compose(upcase, excl);
4343+// ("GAL!")
4444+const shout = compose(upcase, excl);
4545+```
4646+4747+GREAET ANIMATION! And if we'd like to implement `compose` for more than just 2 functions (`sanctuary` doesn't support
4848+it, but `ramda` does)
4949+5050+```js
5151+const upcase = x => x.toUpperCase();
5252+const excl = x => `${x}!`;
5353+const addIrcChatBubble = name => text => `<${name}> ${text}`;
5454+5555+const compose = (...fns) => x => fns.reduceRight((acc, currFn) => currFn(acc), x);
5656+5757+const firstExample = addIrcChatBubble("gal")(upcase(excl("hello everyone")));
5858+const secondExample = compose(addIrcChatBubble("gal"), upcase, excl)("hello everyone"); // extract shout!
5959+6060+console.log({ firstExample, secondExample });
6161+```
-95
talk01/03_lenses.md
···11-# Lenses
22-33-Lenses are a pattern in functional programming to "see" the "world". Lenses can show you the world as it is, you can
44-focus on whatever you want to see, and you can manipulate everything.
55-66-Lenses have 3 methods: `view`, `over` and `set`.
77-88-```js
99-const user = {
1010- name: "gal",
1111- nickname: "schniz"
1212-};
1313-1414-const { lensProp, view, over, set } = require("ramda");
1515-const $name = lensProp("name");
1616-1717-const userName = view($name, user);
1818-console.log(userName);
1919-```
2020-2121-You can say that it isn't impressive. It's just like using `user.name`. But lenses give more than just that. They're
2222-composable.
2323-2424-```js
2525-const user = {
2626- name: "gal",
2727- nickname: "schniz",
2828- hobby: {
2929- name: "talking"
3030- }
3131-};
3232-3333-const { lensProp, view, over, set, compose } = require("ramda");
3434-const $name = lensProp("name");
3535-const $hobby = lensProp("hobby");
3636-3737-const hobbyName = view(compose($hobby, $name), user);
3838-console.log(hobbyName);
3939-```
4040-4141-Still not impressive? yes, still like `user.hobby.name`. Let's see the most powerful thing about lenses.
4242-4343-```js
4444-const { lensProp, view, over, set, compose } = require("ramda");
4545-const $name = lensProp("name");
4646-const $hobby = lensProp("hobby");
4747-4848-const user = {
4949- name: "gal",
5050- nickname: "schniz",
5151- hobby: {
5252- name: "talking",
5353- lovedSince: "forever"
5454- }
5555-};
5656-5757-const userHagever = set($name, "hagever", user);
5858-const userDifferentHobby = set(compose($hobby, $name), "javascripting", user);
5959-console.log({ user, userHagever, userDifferentHobby });
6060-6161-// in plain javascript, using shallow copying, it would be like
6262-6363-const userDifferentHobbyJS = Object.assign({}, user, {
6464- hobby: Object.assign({}, user.hobby, {
6565- name: "javascripting"
6666- })
6767-});
6868-6969-console.log({ userDifferentHobbyJS });
7070-```
7171-7272-Which one is better?
7373-7474-The last function I need to show you is `over`. Well, `over` is like `set`, but more flexible. You can implement `set` with `over`.
7575-`over` takes a function (instead of a new plain value) to apply on the old value - it is something between `view` and `set`.
7676-7777-```js
7878-const { lensProp, view, over, set, compose } = require("ramda");
7979-const $nickname = lensProp("name");
8080-8181-const user = {
8282- name: "gal",
8383- nickname: "schniz",
8484-};
8585-8686-const addHandleIfMissing = nickname => nickname.charAt(0) == '@' ? nickname : `@${nickname}`
8787-const userWithHandle = over($nickname, addHandleIfMissing, user)
8888-console.log({ user, userWithHandle });
8989-9090-// implementing set is easy -
9191-9292-const setWithOver = (lens, value, obj) => over(lens, () => value, obj)
9393-const userWithNewNick = setWithOver($nickname, 'new nick', user)
9494-console.log({ user, userWithNewNick })
9595-```
+95
talk01/04_lenses.md
···11+# Lenses
22+33+Lenses are a pattern in functional programming to "see" the "world". Lenses can show you the world as it is, you can
44+focus on whatever you want to see, and you can manipulate everything.
55+66+Lenses have 3 methods: `view`, `over` and `set`.
77+88+```js
99+const user = {
1010+ name: "gal",
1111+ nickname: "schniz"
1212+};
1313+1414+const { lensProp, view, over, set } = require("ramda");
1515+const $name = lensProp("name");
1616+1717+const userName = view($name, user);
1818+console.log(userName);
1919+```
2020+2121+You can say that it isn't impressive. It's just like using `user.name`. But lenses give more than just that. They're
2222+composable.
2323+2424+```js
2525+const user = {
2626+ name: "gal",
2727+ nickname: "schniz",
2828+ hobby: {
2929+ name: "talking"
3030+ }
3131+};
3232+3333+const { lensProp, view, over, set, compose } = require("ramda");
3434+const $name = lensProp("name");
3535+const $hobby = lensProp("hobby");
3636+3737+const hobbyName = view(compose($hobby, $name), user);
3838+console.log(hobbyName);
3939+```
4040+4141+Still not impressive? yes, still like `user.hobby.name`. Let's see the most powerful thing about lenses.
4242+4343+```js
4444+const { lensProp, view, over, set, compose } = require("ramda");
4545+const $name = lensProp("name");
4646+const $hobby = lensProp("hobby");
4747+4848+const user = {
4949+ name: "gal",
5050+ nickname: "schniz",
5151+ hobby: {
5252+ name: "talking",
5353+ lovedSince: "forever"
5454+ }
5555+};
5656+5757+const userHagever = set($name, "hagever", user);
5858+const userDifferentHobby = set(compose($hobby, $name), "javascripting", user);
5959+console.log({ user, userHagever, userDifferentHobby });
6060+6161+// in plain javascript, using shallow copying, it would be like
6262+6363+const userDifferentHobbyJS = Object.assign({}, user, {
6464+ hobby: Object.assign({}, user.hobby, {
6565+ name: "javascripting"
6666+ })
6767+});
6868+6969+console.log({ userDifferentHobbyJS });
7070+```
7171+7272+Which one is better?
7373+7474+The last function I need to show you is `over`. Well, `over` is like `set`, but more flexible. You can implement `set` with `over`.
7575+`over` takes a function (instead of a new plain value) to apply on the old value - it is something between `view` and `set`.
7676+7777+```js
7878+const { lensProp, view, over, set, compose } = require("ramda");
7979+const $nickname = lensProp("name");
8080+8181+const user = {
8282+ name: "gal",
8383+ nickname: "schniz",
8484+};
8585+8686+const addHandleIfMissing = nickname => nickname.charAt(0) == '@' ? nickname : `@${nickname}`
8787+const userWithHandle = over($nickname, addHandleIfMissing, user)
8888+console.log({ user, userWithHandle });
8989+9090+// implementing set is easy -
9191+9292+const setWithOver = (lens, value, obj) => over(lens, () => value, obj)
9393+const userWithNewNick = setWithOver($nickname, 'new nick', user)
9494+console.log({ user, userWithNewNick })
9595+```