Tại sao nó không tốt để dựa vào thay đổi trạng thái?


16

Câu hỏi này xuất phát từ câu hỏi /software/25569/is-haskell-worth-learning

Nói chung, một vài câu thường được lặp đi lặp lại, về cách Haskell cải thiện kỹ năng mã hóa của bạn bằng các ngôn ngữ khác, và hơn nữa, điều này là do Haskell không trạng thái, và đó là một điều tốt.

Tại sao?

Tôi đã thấy ai đó so sánh điều này với việc chỉ gõ bằng tay trái, hoặc có thể nhắm mắt trong một ngày và chỉ dựa vào cảm ứng. Chắc chắn có nhiều hơn thế?

Liệu nó có liên quan đến truy cập bộ nhớ phần cứng, hoặc một cái gì đó khác là một hiệu suất lớn?


2
Haskell là học tập. Tôi sẽ xem một số bài giảng của Rich Hickey về Clojure - ở đó anh ta đưa ra những lập luận thực dụng của kẻ giết người (tương tự như 3 điểm của Javier, nhưng cũng được thực hiện một cách đơn giản).
Công việc


6
Chỉ vì Haskell là "hàn lâm" không có nghĩa là nó không thực tế hoặc không thực dụng.
Tikhon Jelvis

Câu trả lời:


17

có ít nhất ba lợi thế lớn ngoài đỉnh đầu của tôi:

  1. nó làm cho các chương trình gần hơn với các biểu thức toán học. Trong toán học, xkhông thay đổi, bạn chỉ không biết nó là gì cho đến khi bạn giải phương trình.

  2. Cuối cùng, có thay đổi trạng thái (sau khi tất cả, đó là cách các máy tính làm việc ở cấp độ thấp); nhưng nó bị giới hạn bởi ngôn ngữ đến những nơi cụ thể. cho phép trình biên dịch có cơ hội lớn để di chuyển mã xung quanh để tối ưu hóa nó, vì nó biết rằng nó không thay đổi bất cứ điều gì mà mã khác phụ thuộc vào.

  3. Mã đồng thời không cần phải đồng bộ hóa để truy cập dữ liệu không thay đổi, do đó đồng thời được tăng cường, cả trong các hệ thống bộ nhớ chia sẻ SMP (tất cả các hệ thống đa lõi ngày nay) và trên các cụm liên kết lỏng lẻo.


3
Các dự đoán về lập trình chức năng đặt phần lớn căng thẳng # 3, tức là proramming dễ dàng hơn.
Mchl

4
@Mchl: Theo kinh nghiệm của tôi, họ nhấn mạnh nhất vào "Dễ hiểu và lý do hơn", loại này tương ứng với 1. Mặc dù tôi cho rằng điều đó có thể khác nhau giữa các cộng đồng ngôn ngữ.
sepp2k

+1, câu trả lời rất đầy đủ. @ sepp2k: tôi đoán cả hai đều quan trọng. Lý do về một chương trình là những gì chúng ta làm hàng ngày và đúng là nếu bạn không phải kiểm tra xem trạng thái không thay đổi trong một số chức năng ẩn sâu thì việc đọc các phương pháp cấp cao và nắm bắt những gì đang diễn ra sẽ dễ dàng hơn nhiều. Thông minh về phần cứng: vì chúng ta đang hướng tới đa lõi và đa bộ xử lý ngày càng nhiều hơn (mặc dù tôi đoán rằng sẽ mất một thời gian trước khi máy tính gia đình có được nhiều bộ xử lý), có một ngôn ngữ hỗ trợ lập trình đồng thời là một ưu điểm.
Matthieu M.

Câu trả lời hay, # 2 là những gì tôi cho là câu trả lời, và mặc dù tôi thường đọc về những lợi thế đa xử lý, nó hiếm khi được nêu là rõ ràng, công việc tuyệt vời.
ocodo

1
@Yttrill, các ngôn ngữ chức năng không phải là duy nhất trong việc phụ thuộc vào bộ sưu tập rác và bộ sưu tập rác dễ dàng hơn rất nhiều khi bạn xử lý dữ liệu bất biến. Thực hiện bất kỳ tính toán nào trên kiến ​​trúc dựa trên hướng dẫn có nghĩa là sửa đổi trạng thái, điều đó không có nghĩa là các ngôn ngữ chức năng khó khăn hơn để song song hóa. Ngôn ngữ chức năng đá song song; tra cứu dữ liệu song song Haskell, đó là một tính năng gần như không thể thêm vào một ngôn ngữ bắt buộc.
dan_waterworth

4

Đây là một lợi thế khác: giảm khớp nối. Nếu bạn có mã như:

 function doStuff(x) { return x + y;}

và những nơi khác bạn có:

 function doOtherStuff(x) { y++; return y + x;}

sau đó hai chức năng được phụ thuộc ngầm . Không có cách nào dễ dàng để nói rằng cuộc gọi doStuffbị ảnh hưởng bởi cuộc gọi doOtherStuff. Nếu không có trạng thái có thể thay đổi, bạn sẽ phải làm cho kết nối rõ ràng.

Tất nhiên, đây không phải là một vấn đề với tất cả các trạng thái có thể thay đổi - vấn đề là với trạng thái đột biến lan tỏa. Giải pháp thực sự là có sự bất biến theo mặc định và một số cách "đánh dấu" và hạn chế trạng thái có thể thay đổi đến nơi bạn cần.


+1. Nhiều lập trình viên có kinh nghiệm biết không viết mã như trên và đây không phải là một bước lớn để chuyển từ "trạng thái có thể thay đổi là xấu trong tình huống này" sang "hãy giảm nghiêm trọng lượng trạng thái chúng ta có thể thay đổi và viết nhiều chức năng hơn", nhưng đó là một bước điều đó thật đáng thất vọng
dan_waterworth

2

Một câu trả lời đơn giản là: khi bạn nhìn thấy một tên trong một ngôn ngữ chức năng thuần túy, bạn biết giá trị liên quan là gì bằng cách tra cứu định nghĩa đơn giản của nó. Nếu bạn có các biến có thể thay đổi, bạn chỉ có thể biết được trong số các phép gán nào được thực hiện sau cùng, do đó bạn cũng phải phân tích luồng điều khiển, do đó có thể có điều kiện, khiến bạn có nhiều khả năng. Để có được một vụ nổ theo cấp số nhân, bạn chỉ cần xem xét rằng RHS của các bài tập tự phụ thuộc vào các biến, vì vậy bạn cũng phải phân tích đệ quy chúng.

Điểm mấu chốt trong phân tích ở trên là không thể thực hiện được nếu không có ý kiến ​​giải thích ý định, bất biến và ngữ nghĩa: những điều này có thể khó diễn giải và có thể khó xác minh ngữ nghĩa được tuân thủ trong mã thực tế.

Câu trả lời này về cơ bản là sự mở rộng điểm 1 của @ Javier.

Tôi nghĩ đó cũng là một lời giải thích về sự phổ biến của chế độ OO lừa đảo: với OO, trạng thái đột biến được gói gọn giúp phân tích dễ dàng hơn nhiều bằng cách khoanh vùng các đột biến ở một mức độ nào đó, và cho phép biểu hiện và xác minh ngữ nghĩa mạnh mẽ hơn nhiều.

Có lưu ý rằng, lập trình chức năng không phải là câu trả lời. Câu trả lời đúng là một hệ thống hỗ trợ cả lập trình quy nạp (chức năng) và lập trình (thủ tục), vì vậy các công cụ phù hợp có thể xử lý cả lập trình trạng thái và trạng thái. Chỉ là lý thuyết mang tính xây dựng (chức năng) được thiết lập tốt trong khi lý thuyết quản lý nhà nước vẫn còn ở giai đoạn sơ khai.


Trộn chương trình chức năng và bắt buộc là chính xác những gì Haskell làm - các chức năng bình thường là chức năng trong khi các tính toán trạng thái có thể được biểu thị bằng ký hiệu cho phép bạn cách ly cẩn thận và kiểm soát trạng thái có thể thay đổi (trong số những thứ khác). Đây là lý do tại sao ngôn ngữ có triển khai STM thực tế nhất là Haskell .
Tikhon Jelvis

Ký hiệu không thực sự có bất cứ điều gì để tính toán trạng thái mỗi se . Ký hiệu chỉ là một cú pháp đơn giản hơn trên đầu các đường ống chức năng đơn âm. Tính toán trạng thái chỉ là một trong những điều có thể được thể hiện bằng cách sử dụng các đơn nguyên, và do đó ký hiệu.
Jonathan Sterling

Lập trình hỗn hợp chức năng và mệnh lệnh là điều mà hầu hết mọi ngôn ngữ trong sự tồn tại đều làm. Haskell có thể đã cung cấp một cách để cô lập các phần trạng thái, nhưng điều đó không làm cho nó trở thành một hỗn hợp thích hợp: Từ thiện giống như cách nó nên (IMHO).
Yttrill

2

Là tác giả của Siege , một DBMS được viết bằng Haskell, một số người có thể gọi quan điểm của tôi về trạng thái có thể thay đổi bị xung đột. Tôi hy vọng thể hiện khác.

Mục đích của trạng thái có thể thay đổi là để mô tả trạng thái hiện tại của một hệ thống. Giả sử bạn có một blog và nó là phụ trợ bởi cơ sở dữ liệu, cơ sở dữ liệu mô tả các bài đăng mà bạn có trên blog của mình tại thời điểm bạn truy vấn nó Có bao nhiêu bài viết tồn tại ngay bây giờ?

Tương phản điều này với trạng thái bất biến được sử dụng để truyền đạt sự thật. Có bao nhiêu bài viết vào ngày 12 tháng 8?

Sự thật là dễ dàng để lý do về, trạng thái đột biến là không. Tuy nhiên, trạng thái đột biến không phải là một số hiệu ứng ô uế xấu xa nên bị trục xuất khỏi tầm với của tâm trí chúng ta; chúng ta thường cần nó cùng tồn tại trong thế giới đột biến mà chúng ta đang sống, chúng ta chỉ cần sử dụng nó một cách tiết kiệm hơn.

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.