2016-12-09 17 views
8

Tôi đã cố gắng tìm hiểu tôi một số F # bằng cách xem xét các giải pháp AdventOfCode năm qua. Tôi đã xem qua neat peice of code này, mà tôi không thể phân tích ở tất cả:Gỡ lỗi Seq.sumBy

i 1|>Seq.sumBy(" (".IndexOf) 

Lưu ý, tôi tin rằng tôi hiểu được những dòng trước đó (trong liên kết):

let i n=System.IO.File.ReadAllText(sprintf "%s/input/input%d.txt"__SOURCE_DIRECTORY__ n) 

nào tạo một hàm i mà phải mất một integer n và đọc tệp inputN.txt và trả về tệp dưới dạng chuỗi. Do đó, i 1 trả lại input1.txt làm chuỗi.

Sau đó |> chỉ là đường ống chuỗi (hoặc mảng các ký tự?) Là param đầu tiên chức năng tiếp theo, đó là Seq.sumBy

Nhưng sau đó mọi thứ bắt đầu phá vỡ ...

sumBy dường như thẳng chuyển tiếp đủ:

Trả về tổng các kết quả được tạo bằng cách áp dụng hàm cho từng phần tử trong danh sách.

Nhưng IndexOf của chuỗi " (" đã khiến tôi bối rối.

Bây giờ, tôi không thực sự muốn bất kỳ loài cá nào ở đây, điều tôi muốn biết là đây. Là một newbie cho ngôn ngữ nước ngoài này, khi tôi học cách làm việc nhiều bit hơn của F #, làm thế nào tôi có thể lấy đoạn mã này và phân tích nó thành những phần nhỏ hơn để kiểm tra nó để tìm ra những gì đang xảy ra? Đó là lái xe cho tôi hạt mà tôi có giải pháp, có google/như vậy, và tôi vẫn không thể hiểu được mã này.

Ai đó có thể chỉ cho tôi một số đoạn trích nhỏ hơn để tôi có thể tự mình khám phá câu trả lời không?

+0

tôi ban đầu chấp nhận câu trả lời Reed, mà đã giúp tôi vô cùng. Nhưng câu trả lời của Mark đánh vào phần "giúp tôi gỡ rối" một cách tuyệt vời với các ví dụ mô tả của ông trong FSI. Cả hai đều tuyệt vời. Và những gì một cộng đồng F # tuyệt vời để giúp tôi. Thật thú vị khi bỏ đi một tương tác muốn nhiều hơn nữa! Công việc tuyệt vời cho tất cả mọi người trong cộng đồng này. Cảm ơn bạn! –

Trả lời

7

FSI là bạn của bạn, tôi thường sử dụng nó để hiểu các hàm có thể được chia nhỏ như thế nào, nếu bạn nhìn vào biểu thức " (".IndexOf vào FSI, thì có vẻ như nó không giúp ích gì:

> " (".IndexOf;; 

    " (".IndexOf;; 
    ^^^^^^^^^^^^ 

stdin(12,1): error FS0041: A unique overload for method 'IndexOf' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: System.String.IndexOf(value: char) : int, System.String.IndexOf(value: string) : int 

Như bạn đã biết, " (" là một chuỗi và IndexOf là phương thức trên string. Trên thực tế, có quite a few overloads của phương pháp đó, nhưng chỉ có hai với arity 1.

Một trong những quá tải này lấy một đầu vào là char làm đầu vào và cái kia lấy string làm đầu vào.

Biểu thức " (".IndexOf nếu có chức năng. Đó là hình thức ngắn của fun x -> " (".IndexOf x.

Bạn cũng đã được xác định rằng string thực hiện char seq, vì vậy khi bạn sử dụng mô-đun Seq trên đó, bạn đang xem từng phần tử của chuỗi. Trong trường hợp này, mỗi phần tử là char, vì vậy tình trạng quá tải sử dụng ở đây phải là một trong đó lấy một char làm đầu vào.

Bây giờ bạn đã tìm ra quá tải đang sử dụng, bạn có thể bắt đầu thử nghiệm với nó trong FSI:

> " (".IndexOf '(';; 
val it : int = 1 
> " (".IndexOf 'f';; 
val it : int = -1 
> " (".IndexOf 'o';; 
val it : int = -1 
> " (".IndexOf ' ';; 
val it : int = 0 

Rõ ràng, chức năng tìm kiếm các chỉ số của mỗi đầu vào char trong " (", vì vậy mỗi khi bạn vượt qua trong '(' bạn nhận được 1 (vì nó không được lập chỉ mục) và khi đầu vào là ' ', giá trị trả lại là 0. Đối với tất cả các giá trị khác, giá trị trả lại là -1.

Chuỗi đầu vào như "(foo bar)" cũng là char seq. Thay vì làm một sumBy, bạn có thể thử ống nó vào Seq.map để hiểu làm thế nào mỗi người trong số các yếu tố đang được dịch:

> "(foo bar)" |> Seq.map (" (".IndexOf) |> Seq.toList;; 
val it : int list = [1; -1; -1; -1; 0; -1; -1; -1; -1] 

Bây giờ, Seq.map chỉ dịch, nhưng Seq.sumBy mất tất cả những con số và thêm chúng lại với nhau :

> "(foo bar)" |> Seq.sumBy (" (".IndexOf);; 
val it : int = -6 

tôi vẫn không thể đoán mục đích là gì, nhưng sau đó, tôi chưa bao giờ thấy chuỗi đầu vào ...

+1

Đánh dấu, câu trả lời của bạn quá rực rỡ. Cảm ơn bạn. Ngôn ngữ ngớ ngẩn này không có dấu ngoặc đơn hay dấu phẩy chỉ là giết tôi ! ;-) Nhưng lời giải thích của bạn đã giúp làm rõ. Cảm ơn bạn đã trả lời chi tiết của bạn (và nhiều đóng góp của bạn để giảng dạy nói chung! –

8

Vì vậy, chúng tôi có thể chia nhỏ thành nhiều phần.

i 1|>Seq.sumBy(" (".IndexOf) 

Bạn chính xác về phần i 1. Điều này sẽ đọc input1.txt và cung cấp cho bạn toàn bộ văn bản dưới dạng string.

Vì vậy, khóa đầu tiên ở đây là String implements IEnumerable<char> (char seq), có nghĩa là nó có thể được liệt kê.

Tiếp theo, chúng ta hãy nhìn vào phần bên trong dấu ngoặc:

" (".IndexOf 

Phần đầu tiên chỉ là một chuỗi: " (", và IndexOf là một phương pháp trên chuỗi. Nó trả về chỉ số dựa trên 0 của một ký tự cụ thể, hoặc -1 nếu nó không tồn tại.

Vì nó là một phương pháp, bạn có thể sử dụng nó như một chức năng - vì vậy " (".IndexOf có thể được coi như:

(fun someChar -> 
       let str = " (" 
       str.IndexOf(someChar)) 

--------- Dừng ở đây, trừ khi bạn muốn câu trả lời đầy đủ giải thích chi tiết --------

 

 

 

 

 

 

 

 

 

 

Trong trường hợp này, nếu nhân vật đầu vào là ' ', nó sẽ trở về 0, nếu nó '(', nó sẽ trở lại 1, và nếu nó là bất cứ điều gì khác, nó sẽ trở lại -1.

Seq.sumBy lấy từng ký tự của chuỗi đầu vào và đặt nó vào hàm này, sau đó tính tổng kết quả. Điều này có nghĩa là mỗi đầu vào '(' sẽ thêm 1, mỗi đầu vào ' ' sẽ thêm 0 và mọi thứ khác sẽ thêm -1 (trong trường hợp này, là ')' ký tự. Một chuỗi như thế này "()" sẽ thêm 1, sau đó thêm -1, dẫn đến 0, phù hợp với số goal of the day 1 advent challenge

+2

Tôi nghĩ rằng điều này "" (". IndexOf' cuối cùng đã ném tôi ra. Thực tế là bạn có thể làm một indexOf của nhiều" ký tự ". Và' fun' của bạn mang lại ánh sáng! Tất cả những gì khác phù hợp với nhau. nhìn vào Ngày 1, phần 2! Cảm ơn Reed (và cảm ơn vì - Dừng ở đây --- ;-) –