1. Trang chủ
  2. » Thể loại khác

lap trinh ham trong net

12 103 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 12
Dung lượng 265,5 KB

Nội dung

lap trinh ham trong net tài liệu, giáo án, bài giảng , luận văn, luận án, đồ án, bài tập lớn về tất cả các lĩnh vực kinh...

Trong năm gần đây, ngơn ngữ lập trình Microsoft xuất nhiều kỹ thuật mà có thay đổi nhanh chóng cú pháp, câu lệnh Những thay đổi có nguồn gốc từ mơ hình lập trình có từ lâu: lập trình “hàm số” hay Functional Programming Trong năm gần đây, ngơn ngữ lập trình Microsoft khơng xuất nhiều kỹ thuật mà có thay đổi nhanh chóng cú pháp, câu lệnh Cách viết đoạn mã chương trình ngắn gọn dễ quản lý trước nhiều đặc biệt, dòng lệnh đơi mang tính ước lượng giá trị biểu thức toán học đơn thi hành tập dòng lệnh Những thay đổi có nguồn gốc từ mơ hình lập trình có từ lâu: lập trình “hàm số” hay Functional Programming (FP) ĐƠI NÉT VỀ LẬP TRÌNH FP Mơ hình FP xuất sớm so với lập trình mệnh lệnh (Imperative Programming) lập trình hướng đối tượng (Object Oriented Programming) Tuy nhiên, ngôn ngữ thơng dụng Java, C++ hay VB.Net, C# thích hợp cho lập trình OOP FP Đối với ngôn ngữ này, biến (variable) phương tiện lưu liệu giá trị biến bị truy xuất thay đổi liên tục Biến tồn cục (global) truy cập thay đổi giá trị từ class khác khơng định nghĩa Chính điều gây lỗi gọi “hiệu ứng lề” ứng dụng có nhiều luồng (threads) xử lý đồng thời chia sẻ biến luồng Ngược lại, lập trình FP túy, khái niệm biến khơng tồn mà có “identifier” Các identifier gán giá trị thay đổi Đây điểm quan trọng lập trình FP: hạn chế tác động từ bên làm thay đổi giá trị identifier hay giá trị trả hàm Hàm sở lập trình FP, đoạn mã chương trình có dạng hàm mang biến số để ước lượng giá trị biểu thức toán học Trong Net, hàm ước lượng độ dài chuỗi string.Length() cho kết trả hoàn toàn phụ thuộc vào trạng thái chuỗi lúc gọi Ngược lại, hàm lập trình FP phải ln ln trả giá trị biến số hàm giống Hàm thay đổi giá trị trả biến số hàm thay đổi Chính nhờ ưu điểm không chịu ảnh hưởng từ bên hay giá trị hàm nên lập trình FP giải nhiều vấn đề phức tạp lập trình đa luồng mà trước người lập trình phải đối mặt tranh chấp liệu, đồng liệu hay tình trạng “deadlock” trường hợp luồng phải xử lý Hiện nay, phần mềm đứng trước yêu cầu phải tận dụng sức mạnh xử lý đa nhân FP xem mơ hình thích hợp cho yêu cầu LẬP TRÌNH FP TRONG C# 2.0 Xu hướng hỗ trợ lập trình FP Net bắt đầu xuất C# 2.0 với số kỹ thuật Anonymous method, Generics delegate, Currying hay Closure Anonymous method: Là method không tên định nghĩa với từ khóa “delegate” Anonymous method C# 2.0 khắc phục nhược điểm “Delegate” phiên C# 1.x Nó cho phép “inline code” giúp giảm thiểu số dòng lệnh hay hàm khơng cần thiết đơi gọi lần Thí dụ so sách cách viết hai phương pháp với hàm f(x,y) = x + y Thí dụ 1: Delegate delegate int Demo(int x, int y); public static int Exec(int x, int y) { Demo d = new Demo(AddNumber); return d(x, y); } static int AddNumber(int x, int y) { return x + y; } Anonymous Method delegate int Demo(int x, int y); public static int Exec(int x, int y) { Demo d = delegate(int a, int b) { return a + b; }; return d(x,y); } Bên từ khoá delegate Anonymous Method hàm trả giá trị hàm f Rõ ràng cách viết inline gọn Generics delegate: để hiểu Generics delegate, trước tiên suy luận cú pháp hàm biến “f: D ? R: f(x) = x” ngôn ngữ C Nếu D R có kiểu integer: f: integer ? integer: f(x) = x Trong ngôn ngữ C, hàm f mô tả dạng: R f (D) Và chuyển vào ngơn ngữ lập trình, cú pháp hàm f đuợc viết thành: int f(int) Cũng với hàm f, thay biểu diễn dạng “R f (D)”, Generics delegate cho phép biến đổi dạng “Func” Và cú pháp ngơn ngữ lập trình trở thành: Func Trở lại hàm hai biến f(x, y), đoạn mã chương trình cộng hai biến x y: int add(int x, int y) { return x + y; } Áp dụng Generics delegate cho hàm f(x,y): “Func” hay “Func” Func f = add ; Thay hàm add inline code (Anonymous Method), hàm f(x,y) viết lại thành: Thí dụ 2: Func f = delegate(int x, int y) { return x + y; }; Closure: khả đoạn mã bên delegate tham chiếu đến giá trị biến khơng nằm phạm vi khai báo Xét thí dụ đây: Thí dụ 3: delegate int Demo(int x); static int ClosureDemo(int x) { int y = 1; Demo myClosure = delegate(int z) { return z + y; }; y = 99; return myClosure(x); } ClosureDemo(1); Biến “y = 1” lệnh gán “y = 99” hoàn toàn nằm phạm vi “delegate(int z) {return z + y; }” Kết trả hàm “ClosureDemo(1)” “1+1= 2” mà “100” “myClosure” khơng lấy giá trị “y=1” mà tham chiếu đến biến “y” cần Do đảm bảo giá trị sử dụng Ứng Dụng Closure giải tranh chấp liệu lập trình đa luồng: Trong lập trình đa luồng xử lý đồng thời, người lập trình thường phải giải khó khăn phải dùng chung biến luồng Giả sử có u cầu tìm kiếm tên danh sách đoạn mã chương trình mơ yêu cầu này: Thí dụ 4: static string g_Name; static List people = new List { new Person{ Name=”An”, Age=41, Salary = 500}, new Person{ Name=”Huy”, Age=26, Salary = 300}, new Person{ Name=”Thanh”, Age=30, Salary = 400}, }; static bool SearchName(Person p) { return p.Name.Equals(g_Name); } static List PersonListName(Person p) { g_Name = p.Name; return people.FindAll(SearchName); } Chương trình tìm danh sách tên “Thanh” hồn tồn xác luồng xử lý: p.Name = “Thanh”; list resultList = PersonListName(p); Tuy nhiên, vấn đề xảy từ biến chia sẻ g_Name ứng dụng đa luồng xử lý Luồng thứ tìm tên “Thanh” ( g_Nam= “Thanh”), luồng thứ hai tìm tên “An” (g_Name=“An”) Do kết tìm kiếm luồng thứ sai hoàn toàn biến “g_Name” bị thay đổi Nếu giải cách luồng phải đợi biến “g_Name” giải phóng khơng giải pháp hay, đơi gây tình trạng tắc nghẽn hay deadlock Kỹ thuật Closure không dùng biến “g_Name” kết hợp hai hàm SearchName, PersonListName thành một: Thí dụ 5: static List PersonListName(string name) { return people.FindAll(delegate(Person p) {return p.Name.Equals(name); }); } Hàm PersonListName hoàn toàn không sử dụng biến dùng chung biến g_Name, Closure áp dụng lên biến name Do khơng xảy lỗi dùng chung biến luồng Currying: Là phép biến đổi hàm có hai hay nhiều biến số hàm đơn giản hơn, có biến số Kỹ thuật Currying dựa lý thuyết hàm f(x, y) tồn hàm f’(x) , (f’(x)) (y) = f(x, y) Điều đồng nghĩa với phép biến đổi: Func ? Func< A, Func> Hàm f(x,y) với kỹ thuật Currying viết sau: Thí dụ 6: Func> add = delegate(int x) { return delegate(int y) { return x + y; }; }; int result = add(1)(2); Ứng dụng Curring Patial Application: “Partial application” kỹ thuật truyền biến số cho hàm nhiều biến Lệnh “int result = add(1)(2)” thí dụ thay bằng: Thí dụ 7: Func sum = add(1); int three = sum(2); LẬP TRÌNH FP TRONG C# 3.0 Người lập trình dễ dàng tiếp cận với lập trình FP nhiều kỹ thuật C# 3.0 có điểm chung với FP Đối với người lập trình OOP, cảm nhận làm việc với C# 3.0 thay đổi cú pháp lập trình với kỹ thuật Anonymous type, Lambda Expression hay Lazy evaluation Kết hợp kỹ thuật lại với giảm thiểu số lượng công việc áp lực cơng việc cho người lập trình, đồng thời làm tăng tính hiệu sản phẩm code nhỏ, gọn, Type Inference – Anonymous type: Type Inference: Được dùng để khai báo biến với từ khóa “var” mà khơng cần định nghĩa kiểu liệu Trình biên dịch tự động suy luận kiểu cách tham chiếu đến giá trị gán cho biến Tuy nhiên kiểu khai báo sử dụng phạm vi local var Name =”An”; var Age = “1/1/1980”; var Numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Anonymous type: xây dựng khái niệm “Tuple” - tập dãy liệu Thí dụ có Tuple Name:An salary:300 City: Ho Chi Minh Anonymous type dùng để định nghĩa kiểu liệu không cần rõ tên cấu trúc liệu var myInfo = new {Name =”An”, Age=”1/1/1980”, Salary=300}; var mySalary = myInfo.Salary * 2; Biến myInfo khởi tạo với kiểu liệu hoàn tồn khơng định nghĩa cấu trúc rõ ràng Phép tốn “var mySalary = myInfo.Salary*2” khơng gây lỗi trình biên dịch hiểu rõ cấu trúc kiểu liệu myInfo Một ưu điểm Anonymous type kết hợp với Type Inference việc tham chiếu liệu Ứng dụng Type Inference – Anonymous type việc tham chiếu liệu: dự án hay nhiều liên quan đến tương tác với liệu người lập trình phải viết đoạn mã để lọc tập liệu từ tập liệu ban đầu Tập liệu field hay kết hợp với tập liệu khác nhiều field Công việc gọi tham chiếu hay “Projection” Trước công việc thường tốn nhiều thời gian phải định nghĩa cấu trúc liệu, viết mã lưu liệu vào cấu trúc mà cấu trúc liệu sử dụng hàm Amonumous type trở nên hiệu yêu cầu Với tập liệu thí dụ 4, yêu cầu tạo danh sách người tên “Huy” danh sách với lấy hai field Name Salary thêm field Allowance xử lý sau: Thí dụ 8: var searchList = from r in people where r.Name == “Huy” select new { r.Name, r.Salary, Allowance = r.Salary * 0.7 }; Kiểu liệu “searchList” với field “Name, Salary, Allowance” tạo mà khơng cần đòi hỏi q nhiều thời gian cho việc định nghĩa cấu trúc, viết code hay phát lỗi Tuy nhiên “Anonymous type” sử dụng pham vi local Lambda Expression: Anonymous method hỗ trợ cách viết inline code chưa có thay đổi đáng kể cú pháp câu lệnh Lambda Expression phát triển Anonymous method, giúp giải gánh nặng người lập trình việc viết đoạn mã Có thể hiểu Lambda Expression hàm mang biến số Cú pháp “x => x+1” giống hàm có biến “x” giá trị trả hàm “x+1” Lambda Expression xây dựng lý thuyết “Lambda calculus” phát minh thập niên 1930 Kí tự Lambda (?) người Hy Lạp dùng đặt phía trước biến số hàm Thí dụ biểu diễn hàm biến hàm hai biến Lambda Expression cú pháp ngôn ngữ C# 3.0 f(x) = x f(x,y) = x + y Lambda Expression x ? x (x,y) ? x + y C# 3.0 x => x (x,y) => x + y Nhờ vào cú pháp đơn giản, nên dòng lệnh đơn giản Thí du 9: Func Add = (x, y) => x + y; Lambda Expression khơng có tham số (parameter) có nhiều parameter parameter khai báo kiểu không cần khai báo kiểu n => (n-1)*(n-2) x => (x % 2) == (int x) => (x % 2) == p => p.Name == “Huy” && p.Age > 25 Các kỹ thuật Closure hay Currying sử dụng Lambda Expression Closure Lambda Expression khả hiểu kiểm sốt biến khơng nằm phạm vi biểu thức Thí dụ 10: int x = 99; Func add = y => y + x; int firstResult = add(1); // 99 + = 100 int secondResult = add(2); // 99 + = 101 Tuy “y” không biến local khơng parameter method chương trình khơng báo lỗi xem biến “tự do” Kết biểu thức firstResult 100 trường hợp Closure có vai trò lưu trạng thái giá trị biến để sử dụng lại sau Currying Lambda Expression cho hàm f(x,y): static Func f(int x) { Func add = (y, z) => y + z; return y => add(x, y); } var Currying = f(1); int three = Currying(2); // = + int four = Currying(3); // = + Thật khó để thấy ứng dụng Currying vào thực tế Tuy nhiên thích hợp khoa học máy tính cho việc chia nhỏ hàm tốn học có n biến chứa phép toán phức tạp thành n-1 hàm đơn giản Query Expression: Đây hỗ trợ ngôn ngữ LINQ cho C# 3.0 việc xây dựng câu truy vấn inline Ngồi câu lệnh trơng giống ngơn ngữ SQL “Select”, “From”, “Where” (thí dụ 8) việc ứng dụng “Lambda Expression” vào “Query Expression” làm đơn giản công việc truy vấn liệu Các câu lệnh truy vấn trở nên ngắn gọn dễ hiểu Thí dụ viết lại “Lambda Expression”: Thí dụ 11: var searchList = people Where(p => p.Name == “Huy”) Select(p => new { p.Name, p.Salary, allowance = p.Salary * 0.7 }); Một thí dụ tìm tuổi lớn danh sách, trước người lập trình phải viết stored procedure hay đoạn mã so sánh phần tử danh sách với C# 3.0 cần lệnh: int maxAge = people.Max(p => p.Age); Một kỹ thuật hữu ích Query Expression Extension Method Trước đây, class thuộc hãng thứ ba hay class lý khai báo đóng kín, người lập trình thường gặp nhiều khó khăn khơng phép thay đổi hay thêm method cho phù hợp với yêu cầu Thí dụ class Integer C#, người lập trình khơng thể thêm method Square lệnh gọi đây: Thí dụ 12: int myValue = 2; myValue.Square(); Class Integer C# hồn tồn khơng có method Square Nhờ kỹ thuật Extention Method, người lập trình làm việc với yêu cầu Giả sử class ListPerson cung cấp hàm tìm kiếm theo tên thừa kế hay thêm vào class Nếu có u cầu tìm kiếm theo tuổi người lập trình khơng thể tự giải vấn đề Dùng kỹ thuật Extention Method định nghĩa class dạng static bên class định nghĩa static method với từ khóa this cho biến số method Method Square định nghĩa: public static int Square(this int myNumber) { return myNumber * myNumber; } Trở lại yêu cầu tìm kiếm theo tuổi danh sách, tạo method tên MyQuery: namespace MyExtentionMethod { delegate R Func(T t); static class PersonExtensions { public static IEnumerable MyQuery(this IEnumerable sequence, Func predicate) { foreach (T item in sequence) if (predicate(item)) yield return item; } } } Tìm nhân viên có tuổi lớn 29 hay có lương lớn 400: ListPerson person = new ListPerson(people); var myListAge = person.MyQuery(p => p.Age > 29); var myListSalary = person.MyQuery(p => p.Salary > 400 ); Trông method MyQuery thuộc vào class ListPerson (person.MyQuery) class định nghĩa PersonExtensions Lazy evaluation: Đây kỹ thuật ngơn ngữ lập trình quan tâm, Lazy evaluation C# 3.0 tự nhiên đơn giản Giả sử f(x,y) = x+y xảy thỏa điều kiện x >= y >= 0: Thí dụ 13: static Func Add = (x, y) => x + y; static int MyLazyEvaluation(int x, int y, int function) { if (x p.Name.Equals(“An”)); Như “Filter” C# 2.0 tương đồng với “Where” C# 3.0 Map: Dùng để tạo dãy từ dãy ban đầu theo phép toán tương ứng Hàm ConvertAll() “Map” Parameter hàm hàm ảnh hưởng lên phần tử dãy Câu lệnh tạo danh sách với mức lương nhân với hệ số “0.7”: var allowanceSalary = people.ConvertAll(delegate(Person p) { return p.Salary *= 0.7; }); viết lại với C# 3.0: var allowanceSalary = people.ConvertAll(p => p.Salary * 0.7); hay var allowanceSalary = people.Select(p => p.Salary * 0.7); Như “Map” C# 2.0 tương đồng với “Select” C# 3.0 Reduce: Còn hiểu “Fold” lập trình FP Đây khả tính tốn giá trị dãy cách lướt qua tất phần tử dãy Tính tổng tiền lương danh sách: int total = people.Aggregate(0, delegate(int currentSum, Person p) { return currentSum + p.Salary; }); C# 3.0: var total = people.Select(p => p.Salary).Aggregate(0, (x, y) => x + y); NET Framework 3.5 cung cấp số hàm tính tốn cho dãy Sum, Average, Count, Min, Max Do thấy Filter hay Map C# 2.0 không thích hợp cho C# 3.0 Lambda Expression hồn tồn thay LINQ ngày phổ biến Thí dụ tính tổng số lương người có tuổi lớn 29: var total = people.Where(p => p.Age>29).Select(p => p.Salary).Sum(); hay var total = (from p in people where (p.Age > 29) select p.Salary).Sum(); KẾT LUẬN Lập trình FP Net hạn chế, tiếp cận với kỹ thuật giúp người lập trình tiết kiệm nhiều thời gian việc viết quản lý code phát lỗi, đồng nghĩa với tiết kiệm chi phí nhân cho dự án Và nữa, FP cho phép khai thác sức mạnh xử lý đa nhân ... “myClosure” khơng lấy giá trị “y=1” mà tham chiếu đến biến “y” cần Do đảm bảo giá trị sử dụng Ứng Dụng Closure giải tranh chấp liệu lập trình đa luồng: Trong lập trình đa luồng xử lý đồng thời,... myInfo Một ưu điểm Anonymous type kết hợp với Type Inference việc tham chiếu liệu Ứng dụng Type Inference – Anonymous type việc tham chiếu liệu: dự án hay nhiều liên quan đến tương tác với liệu... hàm biến “f: D ? R: f(x) = x” ngôn ngữ C Nếu D R có kiểu integer: f: integer ? integer: f(x) = x Trong ngôn ngữ C, hàm f mô tả dạng: R f (D) Và chuyển vào ngơn ngữ lập trình, cú pháp hàm f đuợc

Ngày đăng: 21/12/2017, 12:12

w