Liệu sự bất biến trong lập trình chức năng có thực sự tồn tại?


9

Mặc dù tôi làm việc như một lập trình viên trong cuộc sống hàng ngày và sử dụng tất cả các ngôn ngữ hợp thời (Python, Java, C, v.v.) Tôi vẫn chưa có cái nhìn rõ ràng về lập trình chức năng là gì. Từ những gì tôi đã đọc, một thuộc tính của các ngôn ngữ chức năng là cấu trúc dữ liệu là bất biến . Đối với tôi điều này một mình đặt ra rất nhiều câu hỏi. Nhưng trước tiên tôi sẽ viết một chút về những gì tôi hiểu về sự bất biến và nếu tôi sai, hãy thoải mái sửa sai cho tôi.

Sự hiểu biết của tôi về sự bất biến:

  • Khi một chương trình bắt đầu, nó có cấu trúc dữ liệu cố định với dữ liệu cố định
  • Người ta không thể thêm dữ liệu mới vào các cấu trúc này
  • Không có biến trong mã
  • Bạn chỉ có thể "sao chép" từ dữ liệu đã có hoặc dữ liệu hiện được tính
  • Bởi vì tất cả ở trên, tính bất biến làm tăng thêm độ phức tạp không gian cho một chương trình

Những câu hỏi của tôi:

  1. Nếu cấu trúc dữ liệu được cho là vẫn như cũ (không thay đổi), làm thế nào mà ai đó thêm một mục mới trong danh sách?
  2. Điểm quan trọng trong việc có một chương trình không thể có được dữ liệu mới là gì? Giả sử bạn có một cảm biến được gắn vào máy tính muốn cung cấp dữ liệu cho chương trình. Điều đó có nghĩa là chúng ta không thể lưu trữ dữ liệu đến ở bất cứ đâu?
  3. Làm thế nào là lập trình chức năng tốt cho học máy trong trường hợp đó? Vì học máy được xây dựng từ giả định cập nhật "nhận thức" của chương trình - do đó lưu trữ dữ liệu mới.

2
Tôi không đồng ý với bạn khi bạn nói rằng không có biến trong mã chức năng. Có các biến trong ý nghĩa toán học của Số lượng có thể giả sử bất kỳ một trong các tập hợp các giá trị. Họ không thể thay đổi , chắc chắn, nhưng họ cũng không phải là toán học.
Édouard

1
Tôi nghĩ rằng sự nhầm lẫn của bạn là bởi vì bạn đang suy nghĩ về các ngôn ngữ chức năng một cách trừu tượng. Chỉ cần lấy bất kỳ chương trình nào trong Haskell - ví dụ: chương trình đọc danh sách các số từ bảng điều khiển, sắp xếp nhanh và đưa ra - và tìm ra cách thức hoạt động và cách loại bỏ những nghi ngờ của bạn. Không có cách nào để thực sự làm sáng tỏ mọi thứ mà không nhìn vào các ví dụ về các chương trình thực tế hơn là triết lý. Bạn sẽ tìm thấy nhiều chương trình trong bất kỳ hướng dẫn Haskell nào.
jkff

@jkff Bạn đang cố nói gì vậy? Haskel có các tính năng không chức năng. Câu hỏi không phải là về Haskell, mà là về lập trình chức năng. Hay bạn đang khẳng định rằng tất cả những gì là chức năng? Làm sao? Vì vậy, những gì nên sai với triết lý, như bạn nói. Những gì trừu tượng gây nhầm lẫn? Câu hỏi OP là một câu hỏi rất hợp lý.
babou 24/2/2015

@babou Tôi đang cố gắng nói rằng cách tốt nhất để hiểu làm thế nào một ngôn ngữ lập trình chức năng thuần túy có thể thực hiện hiệu quả các thuật toán và cấu trúc dữ liệu là xem xét các ví dụ về thuật toán và cấu trúc dữ liệu được triển khai hiệu quả trong ngôn ngữ lập trình chức năng. Dường như với tôi rằng OP đã cố gắng hiểu làm thế nào nó có thể về mặt khái niệm - tôi nghĩ cách nhanh nhất để hiểu đó là xem xét các ví dụ, thay vì đọc một lời giải thích khái niệm, bất kể chi tiết như thế nào.
jkff

Một cách để xem xét lập trình chức năng là nói rằng đó là lập trình mà không có tác dụng phụ. Bạn có thể làm điều đó bằng ngôn ngữ "hợp thời" của bạn. Chỉ cần tránh tất cả các đánh giá lại: ví dụ: trong Java, tất cả các biến của bạn sẽ là cuối cùng và tất cả các phương thức của bạn sẽ chỉ đọc.
Revierpost

Câu trả lời:


10

Khi một chương trình bắt đầu, nó có cấu trúc dữ liệu cố định với dữ liệu cố định

Đây là một chút quan niệm sai lầm. Nó có một hình thức cố định và một bộ quy tắc viết lại cố định nhưng những quy tắc viết lại này có thể bùng nổ thành một cái gì đó lớn hơn nhiều. Ví dụ, biểu thức [1..100000000] trong Haskell được biểu thị bằng một lượng mã rất nhỏ nhưng dạng thông thường của nó là rất lớn.

Người ta không thể thêm dữ liệu mới vào các cấu trúc này

Có và không. Tập hợp con hoàn toàn chức năng của một ngôn ngữ như Haskell hoặc ML không thể lấy dữ liệu từ thế giới bên ngoài nhưng bất kỳ ngôn ngữ nào để lập trình thực tế đều có cơ chế chèn dữ liệu từ thế giới bên ngoài vào tập hợp con hoàn toàn có chức năng. Trong Haskell điều này được thực hiện rất cẩn thận nhưng trong ML bạn có thể làm điều này bất cứ khi nào bạn muốn.

Không có biến trong mã

Điều này khá đúng nhưng đừng nhầm lẫn điều này với ý tưởng rằng không có gì có thể được đặt tên. Bạn đặt tên cho các biểu thức hữu ích mọi lúc và liên tục sử dụng lại chúng. Cả ML và Haskell, mọi Lisp tôi đã thử và các giống lai như Scala, đều có phương tiện tạo biến. Chúng không được sử dụng phổ biến. Và một lần nữa các tập hợp con hoàn toàn chức năng của các ngôn ngữ như vậy không có chúng.

Bạn chỉ có thể "sao chép" từ dữ liệu đã có hoặc dữ liệu hiện được tính

Bạn có thể thực hiện tính toán bằng cách giảm xuống dạng bình thường. Điều tốt nhất để làm có lẽ là viết các chương trình bằng ngôn ngữ chức năng để xem cách chúng thực hiện trong thực tế tính toán.

Ví dụ: "sum [1..1000]" không phải là phép tính tôi muốn thực hiện nhưng nó được Haskell thực hiện khá thủ công. Chúng tôi đã cho nó một biểu thức nhỏ có ý nghĩa với chúng tôi và Haskell đã cho chúng tôi số tương ứng. Vì vậy, nó chắc chắn thực hiện tính toán.

Nếu cấu trúc dữ liệu được cho là vẫn như cũ (không thay đổi), làm thế nào mà ai đó thêm một mục mới trong danh sách?

Bạn không thêm một mục mới vào danh sách, bạn tạo một danh sách mới từ danh sách cũ. Bởi vì cái cũ không thể bị thay đổi, nó hoàn toàn an toàn để sử dụng nó trong danh sách mới, hoặc bất cứ nơi nào bạn muốn. Nhiều dữ liệu hơn có thể được chia sẻ một cách an toàn trong lược đồ này.

Điểm quan trọng trong việc có một chương trình không thể có được dữ liệu mới là gì? Giả sử bạn có một cảm biến được gắn vào máy tính muốn cung cấp dữ liệu cho chương trình. Điều đó có nghĩa là chúng ta không thể lưu trữ dữ liệu đến ở bất cứ đâu?

Theo như đầu vào của người dùng, bất kỳ ngôn ngữ lập trình thực tế nào cũng có cách lấy đầu vào của người dùng. Điều này xảy ra. Tuy nhiên, có một tập hợp con đầy đủ chức năng của các ngôn ngữ này mà bạn viết hầu hết mã của mình và bạn gặt hái được những lợi thế theo cách này.

Làm thế nào là lập trình chức năng tốt cho học máy trong trường hợp đó? Vì học máy được xây dựng từ giả định cập nhật "nhận thức" của chương trình - do đó lưu trữ dữ liệu mới.

Đây sẽ là trường hợp cho học tập tích cực nhưng hầu hết học máy tôi đã làm việc (tôi làm việc như một con khỉ mã trong một nhóm học máy và đã làm như vậy trong một vài năm) có một quá trình học tập một lần trong đó tất cả các dữ liệu đào tạo được tải trong cùng một lúc Nhưng để học tập tích cực, bạn không thể thực hiện 100% chức năng hoàn toàn. Bạn sẽ phải đọc một số dữ liệu từ thế giới bên ngoài.


Tôi cảm thấy như bạn thuận tiện bỏ qua những gì có thể được cho là điểm quan trọng nhất trong bài đăng của @ Pithikos, đó là vấn đề không gian - các chương trình chức năng sử dụng nhiều không gian hơn các mệnh lệnh bắt buộc (bạn không thể viết thuật toán tại chỗ và như vậy)
user541686

2
Điều này chỉ đơn giản là không đúng sự thật. Việc thiếu đột biến phần lớn được bù đắp bằng cách chia sẻ và trên hết là sự khác biệt về kích thước mà bạn đề cập là rất nhỏ với các trình biên dịch hiện đại. Hầu hết các mã trong danh sách trong haskell đều có hiệu lực hoặc không sử dụng bộ nhớ nào cả.
Jake

1
Tôi nghĩ rằng bạn nói sai ML một chút. Có, I / O có thể xảy ra ở bất cứ đâu, nhưng cách thông tin mới được đưa vào các cấu trúc hiện có được kiểm soát chặt chẽ.
dfeuer

@Pithikos, Có nhiều biến ở khắp mọi nơi; chúng chỉ khác với những gì bạn đã quen, như Édouard đã chỉ ra. Và mọi thứ liên tục được phân bổ và thu gom rác. Khi bạn thực sự tham gia vào lập trình chức năng, bạn sẽ hiểu rõ hơn về cách nó thực sự diễn ra.
dfeuer

1
Đúng là có các thuật toán không có triển khai chức năng đơn thuần với độ phức tạp cùng thời gian với triển khai mệnh lệnh được biết đến nhiều nhất - ví dụ: cơ sở dữ liệu Union-Find (và, um, mảng :)) Tôi tưởng tượng cũng có những trường hợp như thế này đối với không gian phức tạp. Nhưng đây là những trường hợp ngoại lệ - hầu hết các thuật toán / cơ sở dữ liệu phổ biến đều có các triển khai với độ phức tạp không gian và thời gian tương đương. Đó là vấn đề chủ quan của phong cách lập trình và (với yếu tố không đổi) về chất lượng của trình biên dịch.
jkff

4

Tính không thay đổi hoặc tính đột biến không phải là một khái niệm có ý nghĩa trong lập trình chức năng.

Bối cảnh tính toán

Đây là một câu hỏi rất hay là một câu hỏi thú vị (không phải là một bản sao) cho một câu hỏi gần đây khác: sự khác biệt giữa sự phân công, định giá và ràng buộc tên là gì?

Thay vì trả lời từng câu một của bạn, tôi đang cố gắng cung cấp cho bạn một cái nhìn tổng quan có cấu trúc về những gì đang diễn ra.

Có một số vấn đề được xem xét để trả lời bạn, bao gồm:

  • Mô hình tính toán là gì và khái niệm nào có ý nghĩa đối với một mô hình nhất định

  • Ý nghĩa của các từ bạn đang sử dụng là gì và nó phụ thuộc vào ngữ cảnh như thế nào

Phong cách lập trình chức năng có vẻ ngớ ngẩn vì bạn nhìn thấy nó với con mắt lập trình mệnh lệnh. Nhưng đó là một mô hình khác nhau, và các khái niệm và nhận thức cấp bách của bạn là xa lạ, không đúng chỗ. Các trình biên dịch không có định kiến ​​như vậy.

Nhưng kết luận cuối cùng là có thể viết các chương trình theo cách hoàn toàn chức năng, bao gồm cả học máy, lập trình chức năng nghĩ không có khái niệm lưu trữ dữ liệu. Tôi dường như không đồng ý ở điểm này với các câu trả lời khác.

Với hy vọng một số ít sẽ được quan tâm mặc dù độ dài của câu trả lời này.

Mô hình tính toán

Câu hỏi là về lập trình chức năng (hay còn gọi là lập trình ứng dụng), một mô hình tính toán cụ thể, có đại diện lý thuyết và đơn giản nhất là phép tính lambda.

Nếu bạn ở mức lý thuyết, có nhiều mô hình tính toán: máy Turing (TM), máy RAM và các loại khác , máy tính lambda, logic tổ hợp, lý thuyết hàm đệ quy, hệ thống bán phần, v.v. các mô hình đã được chứng minh tương đương về những gì họ có thể giải quyết, và đó là ý chính của luận án Church-Turing .

Một khái niệm quan trọng là giảm các mô hình cho nhau, là cơ sở để thiết lập các tương đương dẫn đến luận điểm Church-Turing. Nhìn từ góc độ lập trình viên, việc giảm mô hình này sang mô hình khác là khá nhiều thứ thường được gọi là trình biên dịch. Nếu bạn lấy lập trình logic làm mô hình tính toán, nó hoàn toàn khác với mô hình do PC bạn mua trong cửa hàng cung cấp và trình biên dịch sẽ dịch các chương trình được viết bằng ngôn ngữ lập trình logic sang mô hình tính toán được trình bày bởi PC của bạn (khá nhiều máy tính RAM).

β

Trong thực tế, các ngôn ngữ lập trình mà chúng ta sử dụng có xu hướng trộn các khái niệm từ các nguồn gốc lý thuyết khác nhau, cố gắng làm điều đó để các phần được chọn của chương trình có thể được hưởng lợi từ các thuộc tính của mô hình nào đó khi thích hợp. Tương tự, mọi người xây dựng hệ thống có thể chọn các ngôn ngữ khác nhau cho các thành phần khác nhau, để phù hợp nhất với ngôn ngữ với nhiệm vụ trong tay.

Do đó, bạn hiếm khi thấy một mô hình lập trình ở trạng thái thuần túy trong ngôn ngữ lập trình. Các ngôn ngữ lập trình vẫn được phân loại theo mô hình chi phối, nhưng các thuộc tính của ngôn ngữ có thể bị ảnh hưởng khi các khái niệm từ các mô hình khác có liên quan, thường làm mờ sự khác biệt và các vấn đề khái niệm.

Thông thường, các ngôn ngữ như Haskell và ML hoặc CAML được coi là chức năng, nhưng chúng có thể cho phép hành vi bắt buộc ... Khác tại sao người ta lại nói về " tập hợp con hoàn toàn chức năng "?

Sau đó, người ta có thể khẳng định rằng, bạn có thể làm điều này hoặc bằng ngôn ngữ lập trình chức năng của tôi, nhưng nó không thực sự trả lời một câu hỏi về lập trình chức năng khi nó dựa vào những gì có thể được coi là chức năng bổ sung.

Các câu trả lời nên liên quan chính xác hơn đến một mô hình cụ thể, không có phần bổ sung.

Một biến là gì?

Một vấn đề khác là việc sử dụng thuật ngữ. Trong toán học, một biến là một thực thể đại diện cho một giá trị không xác định trong một số miền. Nó được sử dụng cho các mục đích khác nhau. Được sử dụng trong một phương trình, nó có thể đại diện cho bất kỳ giá trị nào sao cho phương trình được xác minh. Tầm nhìn này được sử dụng trong lập trình logic dưới tên " biến logic ", có thể là do biến tên đã có ý nghĩa khác khi lập trình logic được phát triển.

Trong lập trình mệnh lệnh truyền thống, một biến được hiểu là một loại vật chứa (hoặc vị trí bộ nhớ) có thể ghi nhớ biểu diễn của một giá trị và có thể thay thế giá trị hiện tại của nó bằng một loại khác).

Trong lập trình hàm, một biến có cùng mục đích trong toán học với tư cách là người giữ chỗ cho một số giá trị, chưa được cung cấp. Trong lập trình mệnh lệnh truyền thống, vai trò này thực sự được chơi bằng hằng số (không bị nhầm lẫn với nghĩa đen được xác định giá trị được biểu thị bằng một ký hiệu cụ thể cho miền giá trị đó, chẳng hạn như 123, true, ["abdcz", 3.14]).

Các biến thuộc bất kỳ loại nào, cũng như hằng số, có thể được biểu thị bằng các định danh.

Biến mệnh lệnh có thể thay đổi giá trị của nó và đó là cơ sở cho tính đột biến. Các biến chức năng không thể.

Ngôn ngữ lập trình thường cho phép xây dựng các thực thể lớn hơn từ các thực thể nhỏ hơn trong ngôn ngữ.

Các ngôn ngữ bắt buộc cho phép các cấu trúc như vậy bao gồm các biến và đó là những gì mang lại cho bạn dữ liệu có thể thay đổi.

Cách đọc chương trình

Một chương trình về cơ bản là một mô tả trừu tượng về thuật toán của bạn là một số ngôn ngữ, cho dù là một thiết kế thực dụng hay một ngôn ngữ thuần túy theo mô hình.

Về nguyên tắc, bạn có thể lấy mọi tuyên bố cho những gì nó được cho là có nghĩa trừu tượng. Sau đó, trình biên dịch sẽ dịch nó sang một số dạng thích hợp để máy tính thực thi, nhưng đó không phải là vấn đề của bạn trong phép tính gần đúng đầu tiên.

Tất nhiên, thực tế thì khắc nghiệt hơn một chút và thường có ý tưởng tốt về những gì xảy ra để tránh các cấu trúc mà trình biên dịch sẽ không biết cách xử lý để thực thi hiệu quả. Nhưng đó đã là tối ưu hóa ... trình biên dịch nào có thể rất tốt, thường tốt hơn so với lập trình viên.

Lập trình chức năng và khả năng biến đổi

Tính tương tác dựa trên sự tồn tại của các biến bắt buộc có thể chứa các giá trị, được thay đổi bằng cách gán. Vì những thứ này không tồn tại trong lập trình chức năng, mọi thứ có thể được xem là bất biến.

Lập trình giao dịch độc quyền với các giá trị.

Bốn tuyên bố đầu tiên của bạn về tính bất biến hầu hết là chính xác, nhưng mô tả với quan điểm bắt buộc một cái gì đó không bắt buộc. Nó hơi giống như mô tả với màu sắc trong một thế giới mà mọi người đều bị mù. Bạn đang sử dụng các khái niệm xa lạ với lập trình chức năng.

Bạn chỉ có các giá trị thuần túy và một mảng các số nguyên là một giá trị thuần túy. Để có được một mảng khác chỉ khác nhau trong một phần tử, bạn phải sử dụng một giá trị mảng khác. Thay đổi một yếu tố chỉ là một khái niệm không tồn tại trong bối cảnh này. Bạn có thể có một hàm có một mảng và một số chỉ mục làm đối số và trả về một kết quả là một mảng gần như giống hệt nhau chỉ khác nhau khi được chỉ định bởi các chỉ mục. Nhưng nó vẫn là một giá trị mảng độc lập. Làm thế nào những giá trị này được đại diện không phải là vấn đề của bạn. Có thể họ "chia sẻ" rất nhiều trong bản dịch bắt buộc cho máy tính ... nhưng đó là công việc của nhà soạn nhạc ... và bạn thậm chí không muốn biết nó đang biên dịch loại kiến ​​trúc máy nào.

Bạn không sao chép các giá trị (nó không có ý nghĩa, đó là một khái niệm xa lạ). Bạn chỉ cần sử dụng các giá trị tồn tại trong các miền bạn đã xác định trong chương trình của mình. Hoặc bạn mô tả chúng (dưới dạng chữ) hoặc chúng là kết quả của việc áp dụng hàm cho một số giá trị khác. Bạn có thể đặt tên cho chúng (do đó xác định hằng số) để đảm bảo cùng một giá trị được sử dụng ở những nơi khác nhau trong chương trình. Lưu ý rằng ứng dụng hàm không nên được coi là một tính toán mà là kết quả của ứng dụng cho các đối số đã cho. Viết 5+2hoặc viết 7số tiền như nhau. Mà phù hợp với đoạn trước.

Không có biến số bắt buộc. Không có nhiệm vụ là có thể. Bạn chỉ có thể liên kết tên với các giá trị (để tạo các hằng số), không giống như các ngôn ngữ bắt buộc nơi bạn có thể liên kết tên với các biến có thể gán.

Cho dù điều đó có một chi phí phức tạp là hoàn toàn không rõ ràng. Đối với một điều, bạn tham khảo các mối quan tâm phức tạp bắt buộc. Nó không được định nghĩa như vậy đối với lập trình chức năng, trừ khi bạn chọn đọc chương trình chức năng của mình như một chương trình bắt buộc, đây không phải là mục đích của người thiết kế. Thật vậy, quan điểm chức năng nhằm mục đích cho phép bạn không lo lắng về các vấn đề như vậy và tập trung vào những gì đang được tính toán. Nó là một chút giống như đặc điểm kỹ thuật so với thực hiện.

Trình biên dịch phải quan tâm đến việc thực hiện và đủ thông minh để thích nghi tốt nhất những gì sẽ được thực hiện với phần cứng sẽ làm việc đó, bất kể đó là gì.

Tôi không nói rằng các lập trình viên không bao giờ lo lắng về điều đó. Tôi cũng không nói rằng các ngôn ngữ lập trình và công nghệ trình biên dịch đã trưởng thành như chúng ta mong muốn.

Trả lời câu hỏi

  1. Bạn không sửa đổi giá trị hiện tại (khái niệm người ngoài hành tinh), nhưng tính toán các giá trị mới khác nhau ở nơi mong muốn, có thể bằng cách có thêm một yếu tố, đó là danh sách.

  2. Chương trình có thể nhận dữ liệu mới. Toàn bộ vấn đề là cách bạn thể hiện điều đó bằng ngôn ngữ. Ví dụ, bạn có thể xem xét rằng chương trình hoạt động với một giá trị cụ thể, có thể không bị ràng buộc về kích thước, được gọi là luồng đầu vào. Đó là một giá trị được cho là ngồi ở đó (cho dù nó đã được biết đầy đủ hay chưa không phải là vấn đề của bạn). Sau đó, bạn có một hàm trả về một cặp bao gồm phần tử đầu tiên của luồng và phần còn lại của luồng.

    Bạn có thể sử dụng điều đó để xây dựng mạng lưới các thành phần giao tiếp theo cách hoàn toàn áp dụng (coroutines)

  3. Học máy chỉ là một vấn đề khác khi bạn phải tích lũy dữ liệu và sửa đổi giá trị. Trong lập trình chức năng, bạn không làm điều đó: bạn chỉ cần tính toán các giá trị mới khác nhau phù hợp theo dữ liệu đào tạo. Máy kết quả sẽ làm việc như là tốt. Điều bạn lo lắng là thời gian tính toán và hiệu quả không gian. Nhưng, một lần nữa, đó là một vấn đề khác, lý tưởng đó nên được xử lý bởi trình biên dịch.

Chú thích cuối

Rõ ràng, từ các ý kiến ​​hoặc các câu trả lời khác, các ngôn ngữ lập trình chức năng thực tế không hoàn toàn là chức năng. Đó là một phản ánh về thực tế rằng công nghệ của chúng tôi vẫn sẽ được cải thiện, đặc biệt là khi biên dịch có liên quan.

Có thể viết theo phong cách ứng dụng thuần túy? Câu trả lời đã được biết đến trong khoảng 40 năm và đó là "có". Mục đích của ngữ nghĩa học biểu thị khi nó xuất hiện vào những năm 1970 là chính xác để dịch các ngôn ngữ (biên dịch) thành phong cách chức năng thuần túy, được coi là hiểu rõ hơn về mặt toán học và do đó được coi là một nguồn tài chính tốt hơn để xác định ngữ nghĩa của các chương trình.

Khía cạnh thú vị của nó là cấu trúc lập trình bắt buộc, bao gồm các biến, có thể được dịch thành một kiểu chức năng bằng cách giới thiệu các miền giá trị thích hợp, chẳng hạn như một kho lưu trữ dữ liệu. Và mặc dù phong cách chức năng, nó vẫn tương tự đáng ngạc nhiên với mã của trình biên dịch thực tế được viết theo phong cách bắt buộc.


0

Đó là một quan niệm sai lầm rằng các chương trình chức năng không thể lưu trữ dữ liệu và tôi không nghĩ câu trả lời của Jakes thực sự giải thích điều này rất tốt.

Các chương trình chức năng, giống như bất kỳ chương trình nào, thực sự có chức năng ánh xạ các số nguyên thành các số nguyên. Bất kỳ chương trình bắt buộc nào hoạt động trên các cấu trúc dữ liệu có thể thay đổi đều có đối tác chức năng. Đây chỉ là một phương tiện khác để đạt được cùng một kết thúc.

Cách chức năng lưu trữ dữ liệu thử nghiệm từ một số nguồn sẽ gọi hàm lưu trữ với cấu trúc dữ liệu là đối số và đưa ra kết nối cấu trúc dữ liệu hiện có và dữ liệu mới và do đó dữ liệu được lưu trữ mà không có khái niệm cấu trúc dữ liệu có thể thay đổi.

Từ kinh nghiệm của bản thân , tôi nghĩ khái niệm cấu trúc dữ liệu bất biến đang khiến các nhà phát triển thông thường nghĩ rằng có một số điều không thực tế hoặc thậm chí không thể thực hiện được trong một thiết lập chức năng. Đây không phải là trường hợp.


"Các chương trình chức năng, giống như bất kỳ chương trình nào, thực sự có chức năng ánh xạ các số nguyên thành các số nguyên." Làm thế nào là, Minecraft, thực sự là một số nguyên ánh xạ hàm cho số nguyên?
David Richerby

Dễ dàng. Mỗi byte có thể được hiểu là một số nguyên nhị phân. Một trạng thái trong máy tính là một tập hợp các byte. Một chương trình, thậm chí Minecraft, thao túng trạng thái máy tính, ánh xạ nó từ trạng thái này sang trạng thái khác.
Jeppe Hartmund

Đầu vào của người dùng dường như không phù hợp với thế giới này.
David Richerby

Đầu vào của người dùng là một phần của trạng thái máy tính. Nó không chỉ tồn tại trên màn hình của bạn.
Jeppe Hartmund
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.