Tôi tin rằng tôi đã học được một số / nhiều / hầu hết các khái niệm cơ bản về lập trình chức năng trong JavaScript. Tuy nhiên, tôi gặp khó khăn khi đọc mã chức năng, thậm chí mã tôi đã viết và tự hỏi liệu có ai có thể cho tôi bất kỳ gợi ý, mẹo, thực tiễn tốt nhất, thuật ngữ, v.v. có thể giúp ích không.
Lấy mã dưới đây. Tôi đã viết mã này. Nó nhằm mục đích gán một sự tương đồng phần trăm giữa hai đối tượng, giữa nói {a:1, b:2, c:3, d:3}
và {a:1, b:1, e:2, f:2, g:3, h:5}
. Tôi đã tạo mã để trả lời câu hỏi này trên Stack Overflow . Bởi vì tôi không chắc chắn chính xác loại phần trăm mà poster đã hỏi về, nên tôi đã cung cấp bốn loại khác nhau:
- phần trăm các khóa trong đối tượng thứ 1 có thể được tìm thấy trong phần 2,
- phần trăm của các giá trị trong đối tượng thứ 1 có thể được tìm thấy trong phần 2, bao gồm các mục trùng lặp,
- phần trăm của các giá trị trong đối tượng thứ 1 có thể được tìm thấy trong phần 2, không cho phép trùng lặp và
- tỷ lệ phần trăm của các cặp {key: value} trong đối tượng thứ 1 có thể tìm thấy trong đối tượng thứ 2.
Tôi bắt đầu với mã bắt buộc hợp lý, nhưng nhanh chóng nhận ra rằng đây là một vấn đề rất phù hợp cho lập trình chức năng. Cụ thể, tôi nhận ra rằng nếu tôi có thể trích xuất một hoặc ba hàm cho mỗi trong bốn chiến lược trên đã xác định loại tính năng tôi đang tìm cách so sánh (ví dụ: các khóa hoặc giá trị, v.v.), thì tôi có thể có thể giảm (bỏ qua cách chơi chữ) phần còn lại của mã thành các đơn vị lặp lại. Bạn biết đấy, giữ cho nó KHÔ. Thế là tôi chuyển sang lập trình chức năng. Tôi khá tự hào về kết quả, tôi nghĩ rằng nó khá thanh lịch và tôi nghĩ tôi hiểu những gì tôi đã làm khá tốt.
Tuy nhiên, ngay cả khi đã tự viết mã và hiểu từng phần của nó trong quá trình xây dựng, khi tôi nhìn lại nó, tôi tiếp tục gặp khó khăn hơn cả về cách đọc bất kỳ nửa dòng cụ thể nào, cũng như cách "Grok" những gì bất kỳ nửa dòng mã cụ thể đang thực sự làm. Tôi thấy mình đang tạo ra những mũi tên tinh thần để kết nối những phần khác nhau nhanh chóng biến thành một mớ mì spaghetti.
Vì vậy, bất cứ ai cũng có thể cho tôi biết làm thế nào để "đọc" một số đoạn mã phức tạp hơn theo cách vừa súc tích vừa góp phần vào sự hiểu biết của tôi về những gì tôi đang đọc? Tôi đoán những phần khiến tôi thích thú nhất là những phần có nhiều mũi tên béo liên tiếp và / hoặc những phần có nhiều dấu ngoặc đơn liên tiếp. Một lần nữa, ở cốt lõi của chúng, cuối cùng tôi cũng có thể tìm ra logic, nhưng (tôi hy vọng) có một cách tốt hơn để đi nhanh chóng và rõ ràng và trực tiếp "tiếp nhận" một dòng lập trình JavaScript chức năng.
Vui lòng sử dụng bất kỳ dòng mã nào từ bên dưới, hoặc thậm chí các ví dụ khác. Tuy nhiên, nếu bạn muốn một số gợi ý ban đầu từ tôi, đây là một vài. Bắt đầu với một cách hợp lý đơn giản. Từ gần cuối mã, có cái này được truyền dưới dạng tham số cho hàm : obj => key => obj[key]
. Làm thế nào để một người đọc và hiểu điều đó? Một ví dụ dài hơn là một hàm đầy đủ từ gần đầu : const getXs = (obj, getX) => Object.keys(obj).map(key => getX(obj)(key));
. Phần cuối cùng map
làm cho tôi đặc biệt.
Xin lưu ý, tại thời điểm này tôi không tìm kiếm tài liệu tham khảo về Haskell hoặc ký hiệu trừu tượng tượng trưng hoặc các nguyên tắc cơ bản của cà ri, v.v. Điều tôi đang tìm kiếm là những câu tiếng Anh mà tôi có thể im lặng trong khi nhìn vào một dòng mã. Nếu bạn có tài liệu tham khảo cụ thể giải quyết chính xác điều đó, thật tuyệt, nhưng tôi cũng không tìm kiếm câu trả lời rằng tôi nên đọc một số sách giáo khoa cơ bản. Tôi đã làm điều đó và tôi nhận được (ít nhất là một lượng đáng kể) logic. Cũng lưu ý, tôi không cần câu trả lời thấu đáo (mặc dù những nỗ lực như vậy sẽ được hoan nghênh): Ngay cả những câu trả lời ngắn cung cấp cách đọc thanh lịch cho một dòng cụ thể của mã rắc rối khác sẽ được đánh giá cao.
Tôi cho rằng một phần của câu hỏi này là: Tôi thậm chí có thể đọc mã chức năng một cách tuyến tính, bạn biết đấy, từ trái sang phải và từ trên xuống dưới? Hay là người ta buộc phải tạo ra một bức tranh tinh thần về hệ thống dây điện giống như spaghetti trên trang mã được quyết định không tuyến tính? Và nếu người ta phải làm điều đó, chúng ta vẫn phải đọc mã, vậy làm thế nào để chúng ta lấy văn bản tuyến tính và nối dây spaghetti?
Bất kỳ lời khuyên sẽ được đánh giá cao.
const obj1 = { a:1, b:2, c:3, d:3 };
const obj2 = { a:1, b:1, e:2, f:2, g:3, h:5 };
// x or X is key or value or key/value pair
const getXs = (obj, getX) =>
Object.keys(obj).map(key => getX(obj)(key));
const getPctSameXs = (getX, filter = vals => vals) =>
(objA, objB) =>
filter(getXs(objB, getX))
.reduce(
(numSame, x) =>
getXs(objA, getX).indexOf(x) > -1 ? numSame + 1 : numSame,
0
) / Object.keys(objA).length * 100;
const pctSameKeys = getPctSameXs(obj => key => key);
const pctSameValsDups = getPctSameXs(obj => key => obj[key]);
const pctSameValsNoDups = getPctSameXs(obj => key => obj[key], vals => [...new Set(vals)]);
const pctSameProps = getPctSameXs(obj => key => JSON.stringify( {[key]: obj[key]} ));
console.log('obj1:', JSON.stringify(obj1));
console.log('obj2:', JSON.stringify(obj2));
console.log('% same keys: ', pctSameKeys (obj1, obj2));
console.log('% same values, incl duplicates:', pctSameValsDups (obj1, obj2));
console.log('% same values, no duplicates: ', pctSameValsNoDups(obj1, obj2));
console.log('% same properties (k/v pairs): ', pctSameProps (obj1, obj2));
// output:
// obj1: {"a":1,"b":2,"c":3,"d":3}
// obj2: {"a":1,"b":1,"e":2,"f":2,"g":3,"h":5}
// % same keys: 50
// % same values, incl duplicates: 125
// % same values, no duplicates: 75
// % same properties (k/v pairs): 25