2010-02-28 49 views
12

cách chuyển đổi từ danh sách ký tự thành chuỗi?Chuyển đổi danh sách ký tự (hoặc mảng) thành chuỗi

Nói cách khác, làm cách nào để đảo ngược List.ofSeq "abcd"?

CẬP NHẬT: new System.String (List.ofSeq "abcd" |> List.toArray) |> printfn "%A" có vẻ hoạt động tốt, có hoặc không có new, nhưng List.ofSeq "abcd" |> List.toArray) |> new System.String |> printfn "%A" không thành công. Tại sao?

Trả lời

20

Tôi đã hỏi similar question một lần trước đây. Có vẻ như các nhà xây dựng đối tượng không phải là composable nên bạn không thể chuyển chúng thành một hàm.

List.ofSeq "abcd" |> List.toArray |> (fun s -> System.String s) |> printfn "%A" 
List.ofSeq "abcd" |> List.toArray |> (fun s -> new System.String(s)) |> printfn "%A" 

Cập nhật Constructors là chức năng hạng nhất như F # 4,0

List.ofSeq "abcd" |> List.toArray |> System.String |> printfn "%A" 
+0

OK, hạn chế này có ý nghĩa hiệu suất-khôn ngoan (tạo ra một lambda có lẽ khó có thể tối ưu hóa hiệu suất đi có lẽ có thể bị tổn thương theo cách đó rất khó để phát hiện). Bất kỳ con trỏ nào về lý do tại sao 'mới' là tùy chọn? Để tạo ra các đối tượng bằng cách phản ánh pha trộn tốt hơn với cú pháp Ocaml/F #? Cảm ơn! –

+0

Rất khó để chọn một trong các câu trả lời, tôi sẽ chọn câu trả lời này vì nó tham chiếu đến một câu hỏi liên quan khác. :-) –

+0

"Có vẻ như các nhà xây dựng đối tượng không phải là composable nên bạn không thể chuyển chúng thành một hàm." Điều này cuối cùng đã thay đổi. https://github.com/fsharp/FSharpLangDesign/blob/master/FSharp-4.0/ClassNamesAsFunctionsDesignAndSpec.md – Endrju

4

cách tiếp cận của bạn:

new System.String (listOfChars |> List.toArray) 

là giải pháp tôi thường kết thúc với quá.

Hệ thống suy luận ngữ pháp/kiểu của F # dường như không thể nhận ra một hàm tạo .NET như new String như một hàm được kết xuất (ngăn bạn sử dụng pipelining).

10

Làm việc với chuỗi trong F # là đôi khi một chút không thoải mái. Tôi có lẽ sẽ sử dụng cùng một mã như Dario. Ngữ pháp F # không cho phép sử dụng các hàm tạo như các hàm lớp đầu tiên, do đó bạn không thể thực hiện toàn bộ quá trình xử lý trong một đường ống đơn. Nói chung, bạn có thể sử dụng các thành viên tĩnh và các phương thức ví dụ như các hàm lớp đầu tiên, nhưng không sử dụng các đặc tính cá thể hoặc các hàm tạo.

Dù sao, có một mẹo thực sự khó chịu mà bạn có thể sử dụng để biến một hàm tạo thành một giá trị hàm. Tôi sẽ không khuyên bạn nên thực sự sử dụng nó, nhưng tôi đã khá ngạc nhiên khi thấy rằng nó thực sự hoạt động, vì vậy tôi nghĩ rằng nó có thể có giá trị chia sẻ nó:

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

này định nghĩa một hàm sẽ được inlined tại thời gian biên dịch, mà yêu cầu tham số kiểu đầu tiên có một hàm khởi tạo lấy giá trị của tham số kiểu thứ hai. Điều này được xác định như là một ràng buộc thời gian biên dịch (vì các Generics .NET không thể diễn tả điều này). Ngoài ra, F # không cho phép bạn chỉ định điều này bằng cách sử dụng cú pháp thông thường để xác định các ràng buộc của hàm khởi tạo (mà phải tham số unit làm đối số), nhưng bạn có thể sử dụng tên của các hàm tạo đã biên dịch. Bây giờ bạn có thể viết ví dụ:

// just like 'new System.Random(10)' 
let rnd = ctor<System.Random, _> 10 
rnd.Next(10) 

Và bạn cũng có thể sử dụng kết quả của ctor như chức năng hạng nhất:

let chars = [ 'a'; 'b'; 'c' ] 
let str = chars |> Array.ofSeq |> ctor<System.String, _> 

Như tôi đã nói, tôi nghĩ rằng đây là chủ yếu một sự tò mò, nhưng một khá thú vị một :-).

+0

+1: coolness !!! – Juliet

0

Chỉ phải đối mặt với vấn đề tương tự, và đã đưa ra các giải pháp này:

List.fold (fun str x -> str + x.ToString()) "" (List.ofSeq "abcd") 
Các vấn đề liên quan