Là lập trình chức năng chỉ khác nhau, hoặc nó thực sự khó khăn hơn?


12

Là lập trình chức năng chỉ khác nhau , hoặc nó thực sự khó khăn hơn ?

Nói rằng ai đó chưa bao giờ học lập trình trước đây, và được dạy lập trình chức năng. vs một người chưa bao giờ học lập trình trước đây và được dạy lập trình mệnh lệnh. cái nào anh ta sẽ tìm thấy khó khăn hơn? hay giống nhau?

Câu hỏi của tôi: nói vấn đề bây giờ là trường hợp đầu vào lạc đà,

như vậy qwe_asd_zxc_rty_fgh_vbntrở thànhqweAsdZxcRtyFghVbn

Cách thức thủ tục là:

  1. chia nó dọc theo _
  2. lặp qua mảng bỏ qua mục đầu tiên
  3. cho mỗi mục, chúng tôi viết hoa chữ cái đầu tiên
  4. tham gia kết quả cùng nhau

Cách thức chức năng là:

  1. nếu không thể tìm thấy sự _trở lạiinput
  2. cắt inputdọc theo đầu tiên _(như vậy chúng ta có được qweasd_zxc_rty_gfh_cvb)
  3. viết hoa chữ cái đầu tiên headvà concat mà vớif(tail)

Ok nếu bạn có một nền tảng chức năng VÀ có kinh nghiệm đáng kể về lập trình thủ tục, tôi muốn hỏi: bạn sẽ mất nhiều thời gian hơn để tìm ra cách thức thủ tục hay bạn sẽ mất nhiều thời gian hơn để tìm ra cách thức chức năng?

Nếu bạn có nền tảng về thủ tục nhưng có nhiều năm kinh nghiệm về lập trình chức năng, tôi muốn hỏi một câu hỏi tương tự: bạn sẽ mất nhiều thời gian hơn để tìm ra cách thức thủ tục hay bạn sẽ mất nhiều thời gian hơn để tìm ra chức năng đường?


5
Ehrm, "cách thức thủ tục" có vẻ hoàn hảo đối với tôi nếu chúng ta sử dụng mapbước 3 thay vì vòng lặp đột biến. Cách tiếp cận thứ hai là điều tôi chỉ xem xét nếu không có chức năng phân tách trong thư viện chuẩn (trong trường hợp đó nên so sánh với một giải pháp bắt buộc không sử dụng split).
sepp2k

8
Không có gì đặc biệt về chức năng hoặc thủ tục về một trong các ví dụ của bạn. Tôi nghe có vẻ như bạn đang cố gắng ngoại suy từ một sự hiểu biết sai lầm về lập trình chức năng. Không có gì ngạc nhiên khi bạn nhận được kết quả bất thường.
Rein Henrichs

Tôi không nghĩ rằng lập trình chức năng là khó khăn, nó chỉ khác nhau. Nếu bạn không có kinh nghiệm lập trình thì cũng dễ học như vậy, nhưng vì một số lý do một khi bạn học lập trình bắt buộc, lập trình chức năng trở nên khó khăn.
dan_waterworth

1
Tôi nghĩ rằng sự khác biệt giữa chức năng và thủ tục trở thành tranh luận, vì việc duy trì các ngôn ngữ như JavaScript, C #, Groovy chứa ngày càng nhiều tính năng chức năng.
user281377

2
Lập trình mệnh lệnh khó hơn nhiều và phản trực giác đối với những người không có kinh nghiệm lập trình trước đó. Một biểu hiện như x=x+1có thể làm nổ tung một bộ não không giới hạn. Lập trình hàm là tự nhiên, nó không có gì khác hơn là các hàm toán học thuần túy và thuận tiện.
SK-logic

Câu trả lời:


12

Chỉ khác nhau. Lập trình hàm có liên quan chặt chẽ hơn nhiều với toán học, điều mà hầu hết mọi người đều quen thuộc. Toàn bộ điều "biến bất biến" chỉ gây sốc cho các lập trình viên cấp bách nơi tư duy "đột biến" đã ăn sâu.

Đối với người mới, thường khá trực quan rằng bạn không thể thay đổi giá trị của một cái gì đó.

Khi tôi học CS, chúng tôi được dạy một ngôn ngữ chức năng như là khóa học đầu tiên của chúng tôi. Và mọi người đã học C ++ hoặc Java trước đây đã vật lộn với nó. Những người mới lập trình đã chọn nó khá dễ dàng.


Bạn có phải là một trong những người mới lập trình và chọn nó khá dễ dàng không?
Pacerier

Tôi đã ở đâu đó ở giữa. Tôi đã tìm hiểu một chút về C ++ và một số PHP trước đó, nhưng không đủ để thực sự quen với lối tư duy cấp bách. Mô hình khá rõ ràng khi bạn nhìn toàn bộ lớp học. Ngoài ra, đây là gần một thập kỷ trước đây, vì vậy không, tôi không hoàn toàn mới để lập trình ngày hôm nay;)
jalf

Biến bất biến? Không phải toán học là một ngôn ngữ lập trình chức năng? các biến trong mathicala chắc chắn có thể thay đổi, không?
dùng56834

20

Nó chỉ khác

Khi bạn lập trình về cơ bản, bạn dịch cách bạn suy luận thành mã, khoảng cách giữa suy nghĩ của bạn và giải pháp cuối cùng có thể được gọi là "khoảng cách nhận thức". Khoảng cách càng lớn thì bạn càng khó có thể vượt qua nó.

Nếu bạn đến từ một nền tảng thủ tục, bạn sẽ tự rèn luyện suy nghĩ về thủ tục để khoảng cách sẽ ít hơn đối với mã chức năng và ngược lại.

Cách duy nhất để mô hình lập trình trở nên dễ dàng hơn bất kỳ thứ gì khác là nếu nó được ánh xạ tới thứ bạn đã biết, như ngôn ngữ thông thường, vì vậy bạn sẽ bắt đầu với một khoảng cách ngắn hơn.

Chức năng và thủ tục là một khái niệm khá trôi chảy và chúng có xu hướng chồng chéo


4

Đúng, lập trình chức năng có xu hướng khó hiểu đối với nhiều người (tôi có xu hướng nói, đặc biệt là những người đã tiếp xúc với lập trình thủ tục trước tiên).

Tôi cũng nói rằng ví dụ về lập trình chức năng của bạn không thực sự là một ví dụ rất hay về lập trình chức năng. Đó là sử dụng đệ quy và chỉ soạn kết quả thay vì sửa đổi trạng thái, nhưng không nhiều hơn thế.

Để có được một ví dụ tốt hơn về lập trình chức năng, hãy xem xét một vấn đề tổng quát hơn: thay vì "tìm kiếm một dấu gạch dưới và chuyển chữ cái tiếp theo thành chữ hoa", hãy coi đây chỉ là một trường hợp đặc biệt của việc tìm kiếm một mẫu và thực thi một số mã tùy ý khi nó được tìm thấy.

Rất nhiều ngôn ngữ hỗ trợ điều đó, nhưng để làm như vậy, chúng yêu cầu chúng tôi chỉ định mẫu giống như một biểu thức thông thường. Tuy nhiên, các biểu thức chính quy không có gì nhiều hơn hoặc ít hơn một ngôn ngữ lập trình có mục đích đặc biệt và triển khai RE là trình biên dịch và / hoặc trình thông dịch cho ngôn ngữ đó. Kết quả biên dịch RE về cơ bản là một hàm thực thi (trong một máy ảo RE đặc biệt) để khớp với biểu thức với một số đầu vào.

Trong một cái gì đó giống như Perl, bạn sử dụng một ngôn ngữ đặc biệt để chỉ định mẫu và trình biên dịch đặc biệt để chuyển đổi chuỗi đó thành một thứ giống như chức năng và một trình thông dịch đặc biệt để thực hiện điều đó giống như chức năng đó. Trong ngôn ngữ chức năng, thông thường bạn sẽ sử dụng chính ngôn ngữ đó để chỉ định mẫu và sử dụng trình biên dịch riêng của ngôn ngữ để tạo ra một hàm thực . Chúng ta có thể tạo hàm đó một cách nhanh chóng (giống như chúng ta có thể biên dịch RE khi chúng ta muốn), nhưng khi chúng ta làm, kết quả có thể thực thi như bất kỳ hàm nào khác trong ngôn ngữ thay vì cần các công cụ RE đặc biệt để thực hiện.

Kết quả là chúng ta có thể khái quát hóa vấn đề trên tương đối dễ dàng. Tuy nhiên, thay vì mã hóa cứng '_' và "chữ hoa" trực tiếp vào chuyển đổi, chúng ta có thể có một cái gì đó như:

s&r(pattern, transform, string) {
    if (!pattern(string))
        return string
    else
        return transform(matched part of string) + s&r(rest of string);
}

Nhưng, không giống như một cái gì đó mà chúng ta chỉ định mẫu là RE, chúng ta có thể chỉ định mẫu trực tiếp như một hàm thực và vẫn sử dụng nó, đại loại như:

my_pattern(string) return beginning(string) == '_';

Và sau đó chúng ta chuyển chức năng đó cho s & r. Ngay bây giờ, đó là một chức năng khá nhỏ và chúng tôi đã mã hóa nó hoàn toàn tĩnh. Một ngôn ngữ chức năng phần lớn trở nên thú vị khi chúng ta sử dụng nó như chúng ta có thể RE và tạo ra một chức năng hoàn toàn mới một cách nhanh chóng dựa trên thứ gì đó như đầu vào của người dùng, nhưng không giống như RE mà chức năng đó không cần trình thông dịch RE đặc biệt để chạy - đó là chỉ là một chức năng bình thường như bất kỳ khác.


4

Đây là mã hoàn chỉnh trong Vợt :

;; camelize : string -> string
(define (camelize str)
  (let ([parts (regexp-split #rx"_" str)])
    ;; result of regexp-split is never empty
    (apply string-append
           (first parts)
           (map string-titlecase (rest parts)))))

(camelize "qwe_asd_zxc_rty_fgh_vbn")
;; => "qweAsdZxcRtyFghVbn"

Là một lập trình viên chức năng có kinh nghiệm về thủ tục, tôi không nghĩ rằng tôi sẽ mất nhiều thời gian hơn để "tìm ra" một giải pháp thủ tục, nhưng chắc chắn tôi sẽ mất nhiều thời gian hơn để gõ nó.

BTW, ví dụ kết quả mong đợi trong bài viết gốc là sai: nó thiếu một "h" gần cuối.


gd cho chỉ ra rằng. đã chỉnh sửa
Pacerier

3

Lý thuyết thú cưng của tôi là các mô hình lập trình dễ hiểu hơn khi chúng gần với hoạt động thực tế của máy tính. Con trỏ rất khó hiểu cho đến khi bạn nhận ra rằng về cơ bản chúng là địa chỉ máy. Đệ quy là khó hiểu cho đến khi bạn có ý thức bước qua một ví dụ nhỏ, nhìn thấy các khung ngăn xếp và nhận ra nơi các giá trị khác nhau của cùng một biến được lưu trữ. Điều đó không có nghĩa là lập trình trình biên dịch dễ hơn lập trình cấp cao, nhưng đã thấy nó được thực hiện như thế nào đối với mô hình tinh thần là chìa khóa cho sự thành thạo - cho dù là lập trình hay nói chung là khả năng sử dụng.

Bây giờ, mô hình thủ tục có phần gần với kiến ​​trúc máy thông thường: các bài tập là bộ nhớ (hoặc thanh ghi) ghi. Các cuộc gọi thủ tục thực sự chỉ là các bước nhảy ưa thích, ifthực sự là một bước nhảy có điều kiện, v.v. Nhưng trong Lisp, chẳng hạn, không có mức độ thấp đơn giản tương đương với một ràng buộc từ vựng hoặc biểu thức lambda. Hiểu nó đòi hỏi bạn phải tưởng tượng một cỗ máy chức năng trừu tượng hoàn toàn tách biệt giữa trình độ ngôn ngữ và cỗ máy vật lý, bởi vì và rõ ràng hầu hết mọi người không bao giờ đi xa đến thế.

(Tôi quen thuộc với ý tưởng rằng kiến trúc von Neumann là cuối cùng tùy ý, và chúng ta không nên đầu óc thành kiến mới bắt đầu với các chi tiết không liên quan như kiến trúc máy, và thay vào đó trực tiếp giới thiệu họ đến ngữ nghĩa của ngôn ngữ lập trình. Trong thực tế, tôi đã Tôi đã tự dạy một vài khóa học như vậy. Nhưng càng ngày tôi càng cảm thấy rằng đây là một mục tiêu cao cả nhưng sai lầm, mọi người học lập trình bằng cách xây dựng sự hiểu biết từ dưới lên, và cách lập trình chức năng chỉ đơn giản là lâu hơn một chút.)


7
Theo logic đó, Trình biên dịch phải là ngôn ngữ dễ học nhất :)
Homde

4
Lập trình chức năng là khá dễ hiểu nếu bạn đến từ nó đúng hướng. "Máy chức năng trừu tượng" mà bạn đề cập chỉ đơn giản là đại số . Đánh giá được thực hiện bằng cách viết lại thuật ngữ; ứng dụng chức năng được thực hiện bằng cách thay thế. Các lập trình viên học cách giải quyết các vấn đề bằng cách sử dụng các công cụ tương tự mà họ đã thấy trong nhiều năm học toán. Nếu họ theo đuổi CS, sẽ có đủ thời gian để gặp gỡ rùa sau đó; nếu không, họ vẫn học được các kỹ năng giải quyết vấn đề hữu ích và các nguyên tắc thiết kế. Hãy xem cách thiết kế chương trình .
Ryan Culpepper

2
@mko Không, theo logic này, mã byte thực tế 011011001001101...sẽ là ngôn ngữ dễ học nhất!
MarkJ

2
@konrad: Trình biên dịch RISC có lẽ là ngôn ngữ dễ học nhất. Để biết làm thế nào để làm cho nó làm một cái gì đó hữu ích là một câu chuyện khác cùng nhau ...
Bryan Boettcher
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.