2011-05-27 21 views
10

.Fisafir, bir istisna yakalamak istiyorum, istisna neden sorun düzeltmek ve devam etmek için meydana geldiğini aynı yürütme noktasına dönmek.Scala devamı ve istisna yönetimi

Scala'daki devamlılıklarla bunu nasıl uygularım? Bir anlam ifade ediyor mu?

cevap

11

devam ettirilebilir hata işleme uygulanması muhtemel yollarından biridir gibi sana piton benzeri istisna tedavisini sağlar:

start 
Handling error 
c:\ttttest true 
end Operation finished 
:

import java.io.File 
import java.lang.IllegalStateException 
import scala.util.continuations._ 

// how it works 

ctry { 
    println("start") 

    val operationResult = someOperation(new File("c:\\ttttest")) 

    println("end " + operationResult) 
} ccatch { 
    case (DirNotExists(dir), resume) => 
    println("Handling error") 
    dir.mkdirs() 
    resume() 
} 

def someOperation(dir: File) = { 
    cthrow(DirNotExists(dir)) 
    println(dir.getAbsolutePath + " " + dir.exists) 
    "Operation finished" 
} 

// exceptions 

trait CException 
case class DirNotExists(file: File) extends CException 

// ctry/ccatch classes and methods 

sealed trait CTryResult[T] { 
    def get: T 
    def ccatch(fn: PartialFunction[(CException,() => T), T]): T 
} 
case class COk[T](value: T) extends CTryResult[T] { 
    def ccatch(fn: PartialFunction[(CException,() => T), T]) = value 
    def get = value 
} 
case class CProblem[T](e: CException, k: Any => Any) extends CTryResult[T] { 
    def ccatch(fn: PartialFunction[(CException,() => T), T]) = 
      fn((e,() => k(Unit).asInstanceOf[T])) 
    def get = throw new IllegalStateException("Exception was not processed: " + e) 
} 

def ctry[T](body: => T @cps[Any]) = reset (body) match { 
    case (e: CException, k: (Any => Any)) => CProblem[T](e, k) 
    case value => COk(value) 
} 

def cthrow(e: CException): Any @cps[Any] = shift((k: Any => Any) => (e, k)) 

Bu kod çıkışı aşağıdaki üretir

2

Bir zamanlar yakutta böyle bir şey yaptım. Ruby'nin ortak lisp'inin “devam edilebilir istisnalarını” uygulayıp uygulayamayacağımı görmek sadece bir testti. Aynı şeyi Scala'da yapabilmeliydin, ama denemedim. Genel konsept veya uygulama detayları hakkında sorunuz mu var? Bunları kullanmak

def F[T](foo: => T, dealWithError: Exception => T): T = 
    try foo 
    catch{ 
    case ex: Exception => dealWithError(ex)} 

:)

#!/usr/bin/env ruby 

require 'continuation' 

#Module for adding elements of an array. Leaves error handling to the caller by using exceptions and continuations. 
module Adder 

#Exception class that offers continuations to the receiver. 
    class CcExc < Exception 
     def initialize(again, skip, index, sum) 
      @again = again 
      @skip = skip 
      @index = index 
      @sum = sum 
     end 
     def again 
      @again.call 
     end 
     def skip 
      @skip.call 
     end 
     attr_reader :index #where the problem occured 
     attr_reader :sum #current sum 
    end 

    #Method to get the current continuation 
    def Adder.getcc 
     cc = nil 
     callcc {|c| cc = c} 
     cc 
    end 

    #add all numbers in the array, raise an exception with continuations if an 
    #item doesn't have the right type 
    def Adder.addAll(array) 
     sum = 0; 
     array.each_with_index {|dummy,i| 
      again = getcC#save continuation before processing the item 
      if array[i].is_a? Numeric 
       sum += array[i] #process item normally 
      else 
       #raise exception with previously save continuation (again) 
       #and current continuation (skip) 
       callcc {|skip| raise CcExc.new again, skip, i, sum} 
      end 
     } 
     sum 
    end 
end 

data = [1,"2",3,"hello",Object,"4",5,"END",6] 
begin 
    puts "The sum is #{Adder.addAll data}." 
rescue Adder::CcExc => e 
    puts "Exception raised." 
    i = e.index 
    case data[i] 
     when /^\s*\d/ 
      data[i] = data[i].to_i 
      puts 'Problem fixed. Continue adding.' 
      e.again 
     when "END" 
      puts "'END' found. Stop processing." 
      puts "The sum is #{e.sum}" 
     else 
      puts "'#{data[i]}' of type #{data[i].class} can't be converted " + 
       "to interger. Item skipped." 
      e.skip 
    end 
end 
2
Bu fonksiyon yapmalı

(foo arg de istisnalar atar kodu yerleştirebilirsiniz);

Neyse

, burada (garanti olmaksızın) kodudur sınıf + örtülü dönüşüm:

class ORfoo[R](foo:() => R){ 
    def or(r: R): R = 
     try foo() 
     catch{ 
     case ex: Exception => r 
     } 
    } 

implicit def ORfooWrapper[R](f: => R) = new ORfoo(() => f)

O Burada "1a".toInt or 5