четверг, 16 мая 2013 г.

Управляющие конструкции (Control structures)

Привет!

Во многих языках программирования есть конструкции управления выполнением кода - for, while, if etc.

Где-то их больше, где-то -- меньше. Они составляют базис языка.

Scala -- не исключение и тоже содержит некоторое число встроенных управляющих конструкций (напр. if, for) но в ней возможно написать нечто свое очень похожее внешне на "control structure".

Т.е. выглядящее вот так:

  breakable {
    // your code is here
    if (someCondition) {
      break
    }       
  }

С виду очень похожее на "встроенную" возможность языка, но breakable входит в scala-library.jar как простая фунция.
Тем, кому не хватало какой-нибудь экзотической конструкции могут написать ее сами.

 

Пример ниже:

  type Resource = BufferedReader
  type ResourceUsage = (Resource => Any)

  def use(closable: => Resource)(code: => ResourceUsage) {
    /**
     * Function in function. Comfortable isn't it?
     */
    def handleEx(e: IOException) {
      sys.error(e.getStackTraceString)
    }

    try {
      val resourceToClose = closable

      // use opened resource
      code(resourceToClose)

      resourceToClose.close()
    } catch {
      case e: IOException => {
        handleEx(e)
      }
    }
  }
Эта структура, названная use избавляет нас от необходимости писать try-catch при использовании файла. 
К тому же она сама закроет reader в конце работы с ним.                               
                                                        
Так называемый call-by-name приводит к тому, что выражение:

new BufferedReader(new FileReader(new File("c:\\tmp\\1.txt")))

вызывается внутри ф-и, а не до вызова use. В Java для подобного нужно было бы делать некий callback интерфейс, который нужно было бы "дёргать" из функции use() вызывая нужный блок кода "потом".

А поскольку блок val resourceToClose = closable находится в тесном окружении блока try-catch внутри функции, то и беспокоиться за "вылет" исключения при вызове use() не нужно. Все будет обработано внутри def use().

Ф-я use() "каррированная" -- возвращает ф-ю, которая использует параметр переданный в порождающию функцию use(). Это дает возможность передать второй параметр (блок кода, который работает с открытым ридером) не в скобках, а используя "{}". 
Что делает use() ничем не отличающейся с виду от того же "while() {}".

Кстати, def handleEx(e: IOException) находится внутри ф-и use(...) что очень удобно с точки зрения логической группировки кода (к подобному удобству привыкли те, кто достаточно поработал с Javascript).

Итог

Количество "своих" управляющих конструкций ограниченно разве что необходимостью в проекте и желанием автора. 

Возможность несомненно понравится тем, кто мигрирует с других языков и кто имеет набор понравившихся функций которые есть там, но которых не хватает в Scala.

Комментариев нет:

Отправить комментарий