2011-06-27 26 views
25

Tôi đã viết đoạn mã sau, lấy một số điểm và vẽ chúng trên màn hình bằng cách sử dụng thư viện gloss.là mã điểm miễn phí hiệu quả hơn hay chỉ là terser?

let s = blocks pes 
    pts = map (map mkPt) s {- stitches to points-} 
    lines = map Line pts {-points to lines -} 
    pict = Pictures lines {- lines to a picture -} 
    in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

Nó hoạt động tốt, nhưng nó xảy ra với tôi rằng có một mô hình lặp đi lặp lại: một chuỗi các cuộc gọi hàm, kết quả của mỗi lần đưa vào đối số cuối cùng tiếp theo. Vì vậy, tôi refactored bằng cách loại bỏ các biến trung gian, đảo ngược thứ tự và chaining các chức năng với hàm hợp ("") như sau:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes 
       in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

Happily, điều này chỉ hoạt động tốt quá. Nhưng tôi tự hỏi nếu tôi đang căng thẳng khả năng đọc, hoặc nếu tôi chỉ không được sử dụng để đọc & viết mã phong cách miễn phí điểm. Ngoài ra, làm cách nào để tôi giải thích về mã này? Là phiên bản thứ hai hiệu quả hơn, hoặc chỉ terser? Có điều gì tôi có thể làm theo phong cách để làm cho nó rõ ràng hơn không?

Trả lời

31

Một vài gợi ý nhanh chóng:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

Bạn đã có một số nội dung không cần thiết mà có thể được gỡ bỏ hoàn toàn:

let pict = Pictures . map Line . (map $ map mkPt) . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

Bạn sẽ không tránh ngoặc anyway với thuật ngữ map (map mkPt), do đó, có loại bỏ các $:

let pict = Pictures . map Line . map (map mkPt) . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

Bạn có thể wri te chuỗi sáng tác trên nhiều dòng cho rõ ràng:

let pict = Pictures 
     . map Line 
     . map (map mkPt) 
     . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

Khối do là không cần thiết bởi vì nó chỉ có một tuyên bố, và bạn có thể di chuyển các ứng dụng chính thức bên ngoài định nghĩa:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white 
       . Pictures 
       . map Line 
       . map (map mkPt) 
       . blocks 
in displayPict pes 

Bạn có thể kết hợp hai số map s:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white 
       . Pictures 
       . map (Line . map mkPt) 
       . blocks 
in displayPict pes 

Thỉnh thoảng nó cũng dễ đọc hơn đối với các chuỗi dài sử dụng nhạc nền được đảo ngược tor từ Control.Arrow:

let displayPict = blocks 
        >>> map (Line . map mkPt) 
        >>> Pictures 
        >>> displayInWindow "My Window" (200, 200) (10, 10) white 
in displayPict pes 

Nhưng tất cả đều là tùy chọn; lấy mã của bạn để nếm thử.

Về chủ đề hiệu quả, tôi thấy không có lý do gì để nghĩ rằng cả hai sẽ khác nhau, một khi trình tối ưu hóa của GHC đi qua với mã.

+4

Thật vậy, mã được tạo phải giống nhau đối với phiên bản miễn phí điểm. Không có bất kỳ tối ưu hóa nào, mã miễn phí điểm sẽ kém hiệu quả hơn, bởi vì nó có nhiều cuộc gọi chức năng hơn (thành phần). – augustss

+0

Chà, thật tuyệt, tôi không biết về toán tử thành phần được đảo ngược. Cảm ơn! – nont

+1

@augustss: Cảm ơn bạn đã xác nhận - Tôi không chắc chắn, nhưng các sắp xếp lại là tất cả khá tầm thường và dường như không có bất kỳ sự khác biệt nào về khả năng tái diễn của các biểu thức con. Tôi có xu hướng không lo lắng về trường hợp "không tối ưu hóa" trừ khi sự khác biệt là nghiêm trọng, ví dụ: dựa vào máy phân tích nghiêm ngặt để biến 'foldl' thành' foldl'' khiến tôi khó chịu. –

4

Điểm kiểu miễn phí có thể tốt để hiển thị rất rõ ràng rằng một hàm chỉ đơn giản là một loạt các phép biến đổi trên đầu vào. Nó thực sự dễ dàng để đọc một cái gì đó như:

foo = map show . doThis . doThat . etc 

vì nó trông giống như điển hình điểm mã miễn phí, vì vậy ai quen thuộc với nó sẽ có thể nhìn thấy chính xác những gì là quan trọng, không có tiếng ồn. Hãy so sánh này để:

foo x = d 
    where 
     a = etc x 
     c = doThis b 
     b = doThat a 
     d = map show c 

Rõ ràng, đây là một chút giả tạo, nhưng ý tưởng là các định nghĩa thêm cần được đọc và trả chặt chẽ chú ý đến để hiểu những gì foo được thực sự làm.Có phải a được sử dụng làm đối số cho nhiều chức năng trợ giúp không? Điều gì về b? Luồng dữ liệu có thông qua các chức năng trợ giúp này theo cách bất ngờ không? Điểm kiểu tự do trong trường hợp này là nói "Mọi thứ chỉ đang được biến đổi trong một đường ống, không có sự kỳ quặc nào bạn cần phải suy nghĩ về"

Trong các trường hợp khác, kiểu điểm không thể thực sự làm xáo trộn mọi thứ. Nói chung đó là khi bạn sẽ phá vỡ các cho phép và wheres. Vì vậy, terseness không thực sự là mục tiêu duy nhất, giảm tải tâm thần là quan trọng là tốt. (Như những người khác đã nhận xét, điểm phong cách miễn phí không nên có sự khác biệt về hiệu suất trong mã được tối ưu hóa).

Các vấn đề liên quan