Chúng ta có thể làm mọi thứ bằng các ngôn ngữ bắt buộc với một ngôn ngữ chức năng nếu nó không cho phép 'trạng thái' không?


7

Tôi đã đọc Cấu trúc và Giải thích các Chương trình Máy tính (SICP), MIT. Điều tôi đã hiểu là trong ngôn ngữ lập trình chức năng thuần túy, không có thứ gọi là trạng thái cục bộ. SICP, trang 230 nói:

"Lập trình mà không sử dụng các bài tập, như chúng tôi đã làm trong suốt hai chương cuối của cuốn sách này, theo đó được gọi là lập trình chức năng."

Tôi đến từ một nền tảng lập trình bắt buộc và dường như tôi không thể hiểu được cách thiết kế một chương trình mô hình hóa một hệ thống thế giới thực (như một ngân hàng đơn giản hoặc một phần mềm quản lý thư viện) mà không có ý tưởng về nhà nước.

Nếu lập trình chức năng không có ý tưởng về một trạng thái, làm thế nào để chúng ta làm điều này?

Câu trả lời:


8

Chìa khóa với lập trình chức năng không phải là không có trạng thái, mà là có trạng thái rõ ràng .

Điều này có nghĩa là, trạng thái của bạn được truyền xung quanh như là một tham số cho các chức năng của bạn. Đó là một giá trị thực tế, mà bạn có thể nắm trong tay, nhìn vào và chuyển sang các chức năng khác.

Ví dụ: chúng ta hãy xem phương pháp Lập trình động để tính toán các số Fibonacci. Trong một ngôn ngữ bắt buộc, bạn sẽ có một cái gì đó như thế này:

def fib(n):
  A = {}
  A[0] = 0
  A[1] = 1
  for i in [2 .. n+1]:
      A[i] = A[i-1] + A[i-2]
  return A[n]

Để làm điều này mà không có nhà nước, bạn chỉ cần thông qua cửa hàng của bạn xung quanh. Sử dụng cú pháp Haskell-ish:

fib n = fibHelper 2 n {(1,1), (0,0)}

fibHelper i end cache = 
  if 
    i > end
  then 
    lookup end cache
  else
    let
      newVal = (lookup (i-1) cache) + (lookup (i-2) cache)
      newCache = insert i newVal cache
    in
      fibHelper (i+1) end newCache

Bây giờ, đây là một chút khó khăn, vì bạn không cần toàn bộ mảng cho các số Fibonacci, nhưng bạn có thể tưởng tượng sử dụng điều này cho các vấn đề lập trình động phức tạp hơn như Knapsack, nơi bạn cần toàn bộ các giá trị được tính toán trước đó.

Điều quan trọng cần hiểu ở đây là insertmột chức năng lấy một cửa hàng và trả về một cửa hàng mới, bằng với giá trị ban đầu với một giá trị gia tăng mới. Giá trị ban đầu của cachekhông bị phá hủy, vì vậy nếu bạn có một ứng dụng mà bạn cần một số hoạt động "hoàn tác", bạn có thể theo dõi lịch sử của tiểu bang của mình.

Bạn có thể nói "nhưng điều đó có vẻ không hiệu quả! Bạn đang tạo một cửa hàng hoàn toàn mới mỗi lần!" Tuy nhiên, thông thường trong các ngôn ngữ chức năng, những điều này được triển khai một cách khéo léo bằng cách sử dụng các tham chiếu, do đó không có các bản sao hoàn toàn mới của dữ liệu nằm xung quanh.

Điều đáng nói là mô hình này có một tham số trạng thái, chuyển nó xung quanh khi quá trình tính toán của bạn tiến triển và sửa đổi nó, là rất phổ biến. Mọi người đã phát minh ra sự trừu tượng, như Nhà nước đơn nguyên , cho phép bạn viết những thứ có vẻ bắt buộc, nhưng hoàn toàn là chức năng "dưới mui xe".

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.