2011-07-27 30 views
11

Tôi đang cố gắng sử dụng Scala (2.9.0) liên tục để xây dựng một API dường như chặn, nhưng điều đó thực sự là không đồng bộ. Giả sử rằng bạn muốn viết một cái gì đó như:Sử dụng tiếp tục Scala cho các API không chặn

if(ask("Continue?")) //Prompts Yes/No 
    name = input("Enter your name") 

đâu ask trả về một boolean nếu người dùng nhấn yes, và input yêu cầu một giá trị. Hình ảnh này được gọi từ máy chủ web, trong đó askinput không chặn bất kỳ chủ đề nào, chúng chỉ lưu trữ liên tục trong Bản đồ (hoặc phiên, không quan trọng nhiều) trước khi hiển thị trang với lời nhắc (phát hành hầu hết tài nguyên) . Và khi một phản hồi lấy lại, nó tìm kiếm sự tiếp tục trong Bản đồ và tiếp tục mã.

Vấn đề cho đến nay là tôi không thể tìm ra cách phù hợp để xác định askinput để sử dụng tính năng tiếp tục mà không chuyển kiểu trả về của bối cảnh gọi là tham số.

Gần nhất tôi có đang làm một cái gì đó như:

#!/bin/sh 
exec scala -P:continuations:enable -deprecation "$0" "[email protected]" 
!# 
import util.continuations._ 

//Api code 
def display[T](prompt: String) = shift { 
    cont: (Unit => T) => { 
     println(prompt) 
     cont() 
    } 
} 

//Client code 
def foo() : Int = reset { 
    display[Int]("foo!") // <-- how do I get rid of the type annotation? 
    5 
} 

def bar() : Unit = reset { 
    display[Unit]("bar!") 
} 

println(foo()) 
bar() 

Tôi thực sự muốn thoát khỏi kiểu chú thích trên các cuộc gọi đến display. Có ai biết một cách để đạt được điều này? Tôi không quan tâm nếu định nghĩa API trở nên xấu hơn, miễn là mã khách hàng trở nên đơn giản hơn. Cảm ơn!

+2

Đăng câu trả lời của bạn dưới dạng câu trả lời. –

+0

Không biết tôi có thể! – juancn

Trả lời

6

Cuối cùng tôi figured it out:

#!/bin/sh 
exec scala -P:continuations:enable -deprecation "$0" "[email protected]" 
!# 
import util.continuations._ 

class Display(val resume: (Unit => Any)) extends Throwable 

//Api code 
def display(prompt: String) = shift { 
    cont: (Unit => Any) => { 
     println(prompt) 
     throw new Display(cont) 
    } 
} 

//Client code 
def foo() : Int = reset { 
    display("foo!") 
    5 
} 

def bar() : Unit = reset { 
    display("bar!") 
} 

//Framework 
try { 
    foo() 
} catch { 
    case d: Display => println(d.resume()) 
} 

try { 
    bar() 
} catch { 
    case d: Display => d.resume() 
} 

Bí quyết là chấp nhận phương pháp mà trở Any (Homeresque: D'oh) và trở về Nothing.

Nếu bạn muốn thực hiện một cái gì đó trả về một giá trị, chẳng hạn như ask, bạn có thể làm:

class Ask(val resume: (Boolean => Any)) extends Throwable 

//Api code 
def ask(prompt: String) = shift { 
    cont: (Boolean => Any) => { 
     println(prompt) 
     throw new Ask(cont) 
    } 
} 

Trong đoạn mã trên, yêu cầu trả về một Boolean.

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