Hướng dẫn disadvantages of using functions in python - nhược điểm của việc sử dụng các hàm trong python

Người dân nói rằng thực hành Zen là khó khăn, nhưng có một sự hiểu lầm về lý do tại sao.

Trong chương cuối cùng tôi đã xem xét lợi ích của lập trình chức năng, và như tôi đã chỉ ra, có khá nhiều. Trong chương này, tôi sẽ xem xét những nhược điểm tiềm năng của FP.

Giống như tôi đã làm trong chương trước, lần đầu tiên tôi sẽ đề cập đến những nhược điểm của chương trình chức năng nói chung.

  1. Viết các chức năng thuần túy là dễ dàng, nhưng kết hợp chúng thành một ứng dụng hoàn chỉnh là nơi mọi thứ trở nên khó khăn.
  2. Thuật ngữ toán học tiên tiến [monad, monoid, functor, v.v.] làm cho FP đáng sợ.
  3. Đối với nhiều người, đệ quy không cảm thấy tự nhiên.
  4. Bởi vì bạn có thể đột biến dữ liệu hiện có, thay vào đó bạn sử dụng một mẫu mà tôi gọi, cập nhật khi bạn sao chép.
  5. Các chức năng thuần túy và I/O don lồng thực sự pha trộn.
  6. Chỉ sử dụng các giá trị bất biến và đệ quy có khả năng dẫn đến các vấn đề về hiệu suất, bao gồm sử dụng RAM và tốc độ.

Sau đó, tôi sẽ xem xét các nhược điểm cụ thể hơn của chương trình chức năng trong Scala,:

  1. Bạn có thể trộn các kiểu FP và OOP.
  2. Scala không có một thư viện FP tiêu chuẩn.

1] Viết các chức năng thuần túy là dễ dàng, nhưng kết hợp chúng thành một ứng dụng hoàn chỉnh là nơi mọi thứ trở nên khó khăn

Viết một chức năng thuần túy nói chung là khá dễ dàng. Khi bạn có thể xác định chữ ký loại của mình, các hàm thuần túy sẽ dễ dàng hơn để viết vì không có các biến có thể thay đổi, đầu vào ẩn, trạng thái ẩn và I/O. Ví dụ: hàm

def updateHealth[delta: Int]: Game[Int] = StateT[IO, GameState, Int] { [s: GameState] =>
    val newHealth = s.player.health + delta
    IO[[s.copy[player = s.player.copy[health = newHealth]], newHealth]]
}
9 trong mã này:

val possiblePlays = OffensiveCoordinator.determinePossiblePlays[gameState]

là một chức năng thuần túy, và đằng sau nó là hàng ngàn dòng mã chức năng khác. Viết tất cả các chức năng thuần túy này đã mất thời gian, nhưng nó không bao giờ khó khăn. Tất cả các chức năng tuân theo cùng một mẫu:

  1. Dữ liệu trong
  2. Áp dụng một thuật toán [để chuyển đổi dữ liệu]
  3. Dữ liệu ra

Điều đó đang được nói, phần khó là, Làm thế nào để tôi dán tất cả các chức năng thuần túy này với nhau theo kiểu FP? Câu hỏi đó có thể dẫn đến mã tôi đã trình bày trong chương đầu tiên:

def updateHealth[delta: Int]: Game[Int] = StateT[IO, GameState, Int] { [s: GameState] =>
    val newHealth = s.player.health + delta
    IO[[s.copy[player = s.player.copy[health = newHealth]], newHealth]]
}

Như bạn có thể biết, khi lần đầu tiên bạn bắt đầu lập trình theo kiểu FP thuần túy, hãy dán các chức năng thuần túy với nhau để tạo ra một ứng dụng FP hoàn chỉnh là một trong những khối vấp ngã lớn nhất mà bạn gặp phải. Trong các bài học sau trong cuốn sách này, tôi hiển thị các giải pháp về cách dán các hàm tinh khiết cùng nhau vào một ứng dụng hoàn chỉnh.

2] Thuật ngữ toán học nâng cao làm cho FP đáng sợ

Tôi không biết về bạn, nhưng khi tôi lần đầu tiên nghe các thuật ngữ như tổ hợp, monoid, monad và functor, tôi không biết mọi người đang nói về cái gì. Và tôi đã được trả tiền để viết phần mềm từ đầu những năm 1990.

Như tôi đã thảo luận trong chương tiếp theo, các thuật ngữ như thế này đang đáng sợ, và yếu tố sợ hãi của Hồi giáo trở thành một rào cản đối với việc học FP.

Bởi vì tôi đề cập đến chủ đề này trong chương tiếp theo, tôi đã giành được viết thêm về nó ở đây.

3] Đối với nhiều người, đệ quy không cảm thấy tự nhiên

Một lý do tôi có thể không biết về các thuật ngữ toán học đó là vì bằng cấp của tôi là về kỹ thuật hàng không vũ trụ, không phải khoa học máy tính. Có thể vì lý do tương tự, tôi biết về đệ quy, nhưng không bao giờ phải sử dụng nó. Đó là, cho đến khi tôi trở nên nghiêm túc về việc viết mã FP thuần túy.

Như tôi đã viết trong "FP là gì?" Chương, điều xảy ra khi bạn chỉ sử dụng các hàm thuần túy và giá trị bất biến là bạn phải sử dụng đệ quy. Trong mã FP thuần túy, bạn không còn sử dụng các trường

val names = List["chris", "ed", "maurice"]
0 với các vòng
val names = List["chris", "ed", "maurice"]
1, vì vậy cách duy nhất để lặp qua các phần tử trong một bộ sưu tập là sử dụng đệ quy.

May mắn thay, bạn có thể học cách viết mã đệ quy. Nếu có một bí mật cho quá trình này, thì đó là cách học cách để suy nghĩ trong đệ quy. Khi bạn có được suy nghĩ đó và thấy rằng có các mô hình để các thuật toán đệ quy, bạn sẽ thấy rằng đệ quy trở nên dễ dàng hơn, thậm chí tự nhiên.

Hai đoạn trước tôi đã viết, Cách duy nhất để lặp lại các yếu tố trong một bộ sưu tập là sử dụng đệ quy, nhưng điều đó không đúng 100%. Ngoài việc đạt được một tư duy suy nghĩ đệ quy của người Viking, ở đây, một bí mật khác: Một khi bạn hiểu các phương pháp của Bộ sưu tập Scala, bạn đã giành được việc sử dụng đệ quy thường xuyên như bạn nghĩ. Theo cùng một cách mà các phương thức của Bộ sưu tập là các phương thức thay thế cho các vòng lặp

val names = List["chris", "ed", "maurice"]
1 tùy chỉnh, chúng cũng thay thế cho nhiều thuật toán đệ quy tùy chỉnh.

Như một ví dụ về điều này, khi bạn lần đầu tiên bắt đầu làm việc với Scala và bạn có một

val names = List["chris", "ed", "maurice"]
3 như thế này:

val names = List["chris", "ed", "maurice"]

Nó tự nhiên để viết một biểu thức ____ 21/________ 25 như thế này:

val capNames = for [e 

Bài Viết Liên Quan

Chủ Đề