2010-10-04 10 views
27

Đây là một trình tạo đơn giản trong C#.Tương đương "lợi nhuận" tương đương với ngôn ngữ lập trình D là gì?

IEnumerable<int> Foo() 
    { 
     int a = 1, b = 1; 
     while(true) 
     { 
      yield return b; 
      int temp = a + b; 
      a = b; 
      b = temp; 
     } 
    } 

Làm cách nào để viết trình tạo tương tự trong Kỹ thuật số Mars D?

(Câu hỏi đặt ra là về sự trở lại tuyên bố năng suất)

Cảm ơn!


Cập nhật. Điều đó thật thú vị. Vì tôi chỉ tạo một chuỗi toán học, sử dụng recurrence có thể là một lựa chọn tốt.

auto fib = recurrence!("a[n-1] + a[n-2]")(1, 1); 

foreach (e; take(fib, 10)) // <- prints first ten numbers from the sequence 
{ 
    writeln(e); 
} 
+0

Lưu ý rằng bạn có thể viết fib.take (10) bây giờ gây ra Cú pháp gọi hàm đồng nhất đã được tăng cường. – Trass3r

+0

Thậm chí tìm thấy bài viết: http://www.drdobbs.com/blogs/cpp/232700394 – Trass3r

Trả lời

20

Không có chính xác tương đương trong D. Dưới đây là một số tương đương thô:

Sử dụng opApply kiểu lặp nội bộ. Tuy nhiên, điều này không cho phép lặp qua hai trình lặp trong ngưỡng khóa:

struct Foo { 
    int opApply(int delegate(ref int) dg) { 
     int a = 1, b = 1; 
     int result; 
     while(true) { 
      result = dg(b); 
      if(result) break; 
      int temp = a + b; 
      a = b; 
      b = temp; 
     } 

     return result; 
    } 
} 

void main() { 
    // Show usage: 
    Foo foo; 
    foreach(elem; foo) { 
     // Do stuff. 
    } 
} 

Phạm vi sử dụng. Đây là một chút khó khăn hơn để viết trong một số trường hợp, nhưng rất hiệu quả và cho phép lặp lại khóa. Đây cũng có thể được lặp lại với một vòng lặp foreach, giống hệt như phiên bản opApply:

struct Foo { 
    int a = 1, b = 1; 

    int front() @property { 
     return b; 
    } 

    void popFront() { 
     int temp = a + b; 
     a = b; 
     b = temp; 
    } 

    // This range is infinite, i.e. never empty. 
    enum bool empty = false; 

    typeof(this) save() @property { return this; } 
} 

Nếu bạn thực sự cần coroutine kiểu thứ bạn có thể kết hợp các dãy và opApply cùng sử dụng core.thread.Fiber, nhưng có thể bạn sẽ tìm thấy hoặc là phạm vi hoặc opApply thực hiện những gì bạn cần gần như mọi lúc.

+0

Trong khi phiên bản D hơi dài hơn một chút, thì ít nhất cũng có thể đọc được nhiều hơn: Tôi không thể vượt qua được Foo đó trả về 1 lần (b được chỉ định 1 ngay từ đầu). Ngoài ra, mọi ngôn ngữ đều khác nhau một chút, ví dụ Ruby về cơ bản là phiên bản opApply mà không có cấu trúc trên đầu. –

+5

@he_the_great: Sự cân bằng khác là cả hai phiên bản D đều hiệu quả hơn nhiều. Trong khi sự lặp lại kiểu coroutine/generator có thể được mô phỏng bằng cách sử dụng các sợi, tôi nghĩ rằng cú pháp khá cho nó đã được cố ý bỏ qua bởi vì nó tốn khoảng một trăm chu kỳ chuyển đổi ngữ cảnh trên mỗi lần lặp. Chi phí phiên bản opApply có thể là 5 hoặc 10 chu kỳ cho cuộc gọi đại biểu và phiên bản phạm vi có thể không có chi phí so với phiên bản được mã hóa bằng tay vì tất cả các phạm vi nguyên thủy đều đủ điều kiện cho nội tuyến. Một trong hai phong cách sẽ làm những gì bạn cần w/o nhiều rắc rối về 99,9% thời gian. – dsimcha

+0

Cảm ơn, dsimcha.Phạm vi sử dụng trông rất hứa hẹn, tôi sẽ tra cứu nó. – Lurkeroid

19

Xem here; ví dụ trích dẫn dưới đây:

module main; 

import std.stdio; 
import generators; 

void genSquares(out int result, int from, int to) 
{ 
    foreach (x; from .. to + 1) 
     yield!result(x * x); 
} 

void main(string[] argv) 
{ 
    foreach (sqr; generator(&genSquares, 10, 20)) 
     writeln(sqr); 
} 
15

Module std.concurrency bây giờ có một lớp Generator mà làm cho điều này dễ dàng hơn (và bạn không cần một thư viện của bên thứ ba).

Lớp này là phạm vi đầu vào, vì vậy lớp này có thể được sử dụng cho các vòng lặp và tất cả các chức năng chuẩn std.range/std.algorithm.

import std.stdio; 
import std.range; 
import std.algorithm; 
import std.concurrency : Generator, yield; 

void main(string[] args) { 
    auto gen = new Generator!int({ 
     foreach(i; 1..10) 
      yield(i); 
    }); 

    gen 
     .map!(x => x*2) 
     .each!writeln 
    ; 
} 
+1

Đây phải là câu trả lời được chấp nhận, tôi nghĩ vậy. –

+1

Tôi khá chắc chắn mẫu 'Generator' không tồn tại khi câu hỏi được hỏi ... – DejanLekic