ترکیب برنامه های فانکشنال

scala
functional

#1

به برنامه زیر نگاه کنید این برنامه تعداد لغات یک فایل رو محاسبه و پرینت میکنه

val fr  = newFileReader("thefile.txt")  
val br  =  newBufferedReader(fr)  
var line  = br.readLine()

var count  =  0
while  (line  !=  null)  
{  
  val words  = line.split("\\s")  
  for  (w  <-  words)  { 
    count  +=  1    
  }      
  line  = br.readLine()
}

br.close()

println(count)

مثال oop

class FileReader(path: String) {
  var count  =  0

  def run: Unit = {
    val br  =  openFile
    var line  = br.readLine()

    while  (line  !=  null)
    {
      line = countWords(line, br)
    }

    br.close()

    println(count)
  }
  
  def openFile =
  {
    new BufferedReader(new FileReader(path))
  }
  

  
  def countWords(line: String, br: BufferedReader): Unit = {
    val words  = line.split("\\s")
    for  (w  <-  words)  {
      count  +=  1
    }
    br.readLine()
  }

}

چون این برنامه stateful هست برای درک هر قسمت باید کل برنامه رو درک کنید و قسمت های آن ترکیب پذیر نیستند

حالا همین برنامه‌ را توسط fs2 که کتابخانه streaming هست بصورت فانکشنال مینویسیم

io.linesR("thefile.txt")
.flatMap(s  => emits(s.split("\\s")))
.map(_  =>1)
.fold(0)(_  +  _)
.to(stdout)

هر قسمت کاملا مستقل عمل میکنه و روی داده که نتیجه قبلی کار میکنه طوری که هر قسمت و میشه به عنوان ارزش جدا کرد وبرنامه را از ترکیب این توابع کوچک ساخت

val lines  = io.linesR("thefile.txt")  
val words  =  _.flatMap(s  => emits(s.split("\\s")))  
val ones  =  _.map(_  =>1)  
val sum  =  _.fold(0)(_  +  _)  
val print  =  _.to(stdout)  
val prg  =  print(sum(ones(words(lines))))

چون همه این توابع روی یک سری داده کار می‌کنند میشه ترکیب تابعی استفاده کرد و برنامه ما درواقع ترکیب این توابع هست که اسم فایل برای ورودی میگیره

val f  =  print 
compose  sum    
compose  ones    
compose  words 
val prg  =  f(lines)

این کد بسیار راحت تر درک میشه تست میشه و با هر فانکشن دیگه که این نوع داده رو بگیره به راحتی ترکیب میشه


آموزش کلوژر ۲ - یه مقدار تئوری