Hãy tưởng tượng rằng chúng ta muốn áp dụng một loạt các hàm cho xnếu và chỉ khi xkhông phải là null:
if (x !== null) x = a(x);
if (x !== null) x = b(x);
if (x !== null) x = c(x);
Bây giờ, hãy nói rằng chúng ta cần làm như vậy để y:
if (y !== null) y = a(y);
if (y !== null) y = b(y);
if (y !== null) y = c(y);
Và tương tự với z:
if (z !== null) z = a(z);
if (z !== null) z = b(z);
if (z !== null) z = c(z);
Như bạn có thể thấy nếu không có sự trừu tượng thích hợp, chúng ta sẽ kết thúc việc sao chép mã nhiều lần. Một sự trừu tượng như vậy đã tồn tại: đơn nguyên Có thể .
Đơn nguyên Có thể giữ cả giá trị và ngữ cảnh tính toán:
- Đơn nguyên giữ giá trị an toàn và áp dụng các chức năng cho nó.
- Bối cảnh tính toán là một kiểm tra rỗng trước khi áp dụng một hàm.
Một triển khai ngây thơ sẽ trông như thế này:
⚠️ Việc thực hiện này chỉ mang tính chất minh họa! Đây không phải là cách nên làm và sai ở nhiều cấp độ. Tuy nhiên, điều này sẽ cung cấp cho bạn một ý tưởng tốt hơn về những gì tôi đang nói về.
Như bạn có thể thấy, không gì có thể phá vỡ:
- Chúng tôi áp dụng một loạt các chức năng cho giá trị của chúng tôi
- Nếu tại bất kỳ thời điểm nào, giá trị trở thành null (hoặc không xác định) thì chúng ta sẽ không áp dụng bất kỳ hàm nào nữa.
const abc = obj =>
Maybe
.of(obj)
.map(o => o.a)
.map(o => o.b)
.map(o => o.c)
.value;
const values = [
{},
{a: {}},
{a: {b: {}}},
{a: {b: {c: 42}}}
];
console.log(
values.map(abc)
);
<script>
function Maybe(x) {
this.value = x; //-> container for our value
}
Maybe.of = x => new Maybe(x);
Maybe.prototype.map = function (fn) {
if (this.value == null) { //-> computational context
return this;
}
return Maybe.of(fn(this.value));
};
</script>
Phụ lục 1
Tôi không thể giải thích monads là gì vì đây không phải là mục đích của bài đăng này và có những người ngoài kia giỏi hơn tôi. Tuy nhiên, như Eric Elliot đã nói trong bài đăng trên blog lịch sử JavaScript Monads Made Simple :
Bất kể trình độ kỹ năng của bạn hay sự hiểu biết về lý thuyết danh mục, việc sử dụng monads giúp mã của bạn dễ làm việc hơn. Việc không tận dụng được các monads có thể khiến mã của bạn khó làm việc hơn (ví dụ: địa ngục gọi lại, các nhánh có điều kiện lồng nhau, nhiều chi tiết hơn).
Phụ lục 2
Đây là cách tôi giải quyết vấn đề của bạn bằng cách sử dụng đơn nguyên Có thể từmoneyjs
const prop = key => obj => Maybe.fromNull(obj[key]);
const abc = obj =>
Maybe
.fromNull(obj)
.flatMap(prop('a'))
.flatMap(prop('b'))
.flatMap(prop('c'))
.orSome('🌯')
const values = [
{},
{a: {}},
{a: {b: {}}},
{a: {b: {c: 42}}}
];
console.log(
values.map(abc)
);
<script src="https://www.unpkg.com/monet@0.9.0/dist/monet.js"></script>
<script>const {Maybe} = Monet;</script>
try..catchcâu lệnh. Điều đó nói rằng, một mảng có chứa các phần tử hoàn toàn không đồng nhất trông giống như một vấn đề thiết kế đối với tôi.