2010-11-06 31 views
7

Mã này đảo ngược một chuỗi:Tôi có thể sử dụng toán tử đường ống trong F # để chuyển đối số cho một hàm tạo không?

let reverse (s : string) = new string(s.ToCharArray() |> Array.rev) 

này có thể được viết lại sử dụng các nhà điều hành đường ống dẫn để vượt qua các đối số bắt buộc để các nhà xây dựng string()? Ví dụ: điều này có vẻ thành ngữ hơn:

// Doesn't compile: 
let reverse (s : string) = s.ToCharArray() |> Array.rev |> new string 

Tương tự, tại sao tôi không thể sử dụng toán tử string theo cách sau?

let reverse2 (s : string) = s.ToCharArray() |> Array.rev |> string 

Đây là nó trong hành động:

> reverse2 "foo" ;; 
val it : string = "System.Char[]" 

Nó trả về kiểu chứ không phải là "oof".

+0

có thể trùng lặp của [Sử dụng ký hiệu ống F # với một hàm tạo đối tượng] (http://stackoverflow.com/questions/531178/using-the-f-pipe-symbol-with-an-object-constructor) – gradbot

+0

Điều này nên có thể trong F # 4.0 khi nó xuất hiện: http://blogs.msdn.com/b/fsharpteam/archive/2014/11/12/announcing-a-preview-of-f-4-0-and-the -visual-f-tools-in-vs-2015.aspx –

Trả lời

9

Không, toán tử đường ống chỉ có thể được sử dụng với hàm F #, nó không thể được sử dụng với các hàm tạo lớp, phương thức thành viên hoặc phương thức tĩnh. Lý do là sự quá tải được hỗ trợ bởi các loại phương pháp này sẽ làm phức tạp suy luận kiểu F #. Tuy nhiên, nếu bạn thực sự muốn sử dụng đường ống, bạn có thể lập bản đồ mỗi phần tử của char mảng vào một String và sau đó ống chuỗi đó vào Seq.concat "":

s.ToCharArray() |> Array.rev |> Seq.map(string) |> String.concat "" 

Hoặc bạn có thể quấn gọi chuỗi nhà xây dựng trong một F # phương pháp:

let stringCArrCtor (carr: char[]) = 
    new string(carr) 

s.ToCharArray() |> Array.rev |> stringCArrCtor 

Và để trả lời câu hỏi cuối cùng của bạn,

s.ToCharArray() |> Array.rev |> string 

không thể được sử dụng bởi vì nó tương đương với

(s.ToCharArray() |> Array.rev).ToString() 

và phương thức ToString() của mảng không được ghi đè để nó chỉ trả về tên kiểu được phản ánh mặc định.

+0

Cảm ơn bạn đã trả lời. Nhìn vào chữ ký kiểu của toán tử 'string', làm thế nào bạn biết rằng nó không chỉ là một hàm lấy một đối tượng và trả về một chuỗi? Tôi vẫn còn mắc kẹt trong câu hỏi cuối cùng của tôi. – royco

+1

@Slack, nếu bạn di chuột qua hàm chuỗi, nó sẽ cho bạn biết rằng đó là một hàm 'T -> chuỗi "chuyển đổi đối số thành chuỗi bằng cách sử dụng ToString()". Bạn cũng có thể thấy rằng nó là một phần của không gian tên Operator, cùng với một số hàm chuyển đổi khác (như int, long, float, ...), nó được xử lý đặc biệt bởi trình biên dịch để chúng hoạt động như các hàm "overloaded" được tối ưu hóa . Xem các dòng 4074-4091 trong prim-types.fs trong mã nguồn. –

9

Như Stephen đã đề cập, điều tốt nhất cần làm là xác định hàm mới gọi hàm tạo. Bạn có thể đặt nó vào một mô-đun có tên là String (trong một số không gian tên của bạn), do đó bạn sẽ có cảm giác tương tự như khi làm việc với các hàm F # khác. Tôi có lẽ sẽ sử dụng:

module String = 
    let create (c:char[]) = new string(c) 

Câu hỏi của việc sử dụng nhà xây dựng như các giá trị hạng nhất xuất hiện trên SO trước đây, nhưng tôi không thể tìm thấy câu trả lời trước đây của tôi nữa - có một mẹo rất điên cung cấp cho bạn khả năng, nhưng nó là một hack khổng lồ (không ai nên sử dụng nó và một số phiên bản tiếp theo của F # là hy vọng sẽ không cho phép điều đó). Dù sao, bạn có thể sử dụng statically resolved type parameters để viết như sau:

let inline ctor< ^R, ^T when ^R : 
     (static member ``.ctor`` : ^T -> ^R)> (arg:^T) = 
    (^R : (static member ``.ctor`` : ^T -> ^R) arg) 

Và sử dụng các chức năng như thế này:

"ABC".ToCharArray() |> Array.rev |> ctor<string, _>;; 

Các ctor chức năng cơ bản yêu cầu các loại quy định như tham số loại đầu tiên có một nhà xây dựng và nó gọi hàm tạo (tham số kiểu khác là đối số cho hàm khởi tạo và được trình biên dịch phỏng đoán). Nhưng điều này thực sự chỉ là một sự tò mò - xác định chức năng của riêng bạn là cách tiếp cận tốt nhất.

+0

Điều đó rất hay. Tôi phải bắt đầu học F # ngay bây giờ! – leppie

+0

Thật lạ lùng khi "hack" vi phạm fsi.exe 3.1 với: lỗi FS3066: Tên thành viên không hợp lệ. Thành viên có thể không có tên '.ctor' hoặc '.cctor' – larsw

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