Понимание теоремы продолжения в Scala

from picamera import PiCamera
import time

camera = PiCamera()
camera.start_preview()

while(1):
    try:
        camera.capture("/home/pi/test.png")
    except KeyboardInterrupt:
        break
camera.stop_preview()

остановить его с помощью CTRL + C

0
задан vesii 19 January 2019 в 22:07
поделиться

1 ответ

  1. Для полного примера вам нужно подготовить компилятор Scala для использования продолжений, а также использовать специальный плагин компилятора и библиотеку. Самый простой способ - создать новый объект sbt.project в IntellijIDEA со следующими файлами: build.sbt - в корне проекта, CTest.scala - внутри main / src. Вот содержимое обоих файлов:

build.sbt:

name := "ContinuationSandwich"

version := "0.1"

scalaVersion := "2.11.6"

autoCompilerPlugins := true

addCompilerPlugin(
  "org.scala-lang.plugins" % "scala-continuations-plugin_2.11.6" % "1.0.2")

libraryDependencies +=
  "org.scala-lang.plugins" %% "scala-continuations-library" % "1.0.2"

scalacOptions += "-P:continuations:enable"

CTest.scala:

import scala.util.continuations._

object CTest extends App {
  case class Sandwich()
  def makeSandwich = {
    println("Making sandwich")
    new Sandwich
  }
  var k1 : (Unit => Sandwich) = null
  reset {
    shift { k : (Unit => Sandwich) => k1 = k }
    makeSandwich
  }
  val x = k1()
}

То, что по сути делает код выше, вызывает Функция makeSandwich (в запутанном виде). Таким образом, результатом выполнения будет просто печать «Создание бутерброда» в консоли. Тот же результат будет достигнут без продолжений:

object CTest extends App {
  case class Sandwich()
  def makeSandwich = {
    println("Making sandwich")
    new Sandwich
  }
  val x = makeSandwich
}
  1. Так в чем же смысл? Насколько я понимаю, мы хотим «приготовить бутерброд», игнорируя тот факт, что мы, возможно, не готовы к этому. Мы отмечаем момент времени, когда мы хотим вернуться после того, как все необходимые условия выполнены (т.е. у нас есть все необходимые ингредиенты готовы). После того, как мы собрали все ингредиенты, мы можем вернуться к цели и «приготовить бутерброд», «забыв, что мы не могли сделать это в прошлом». Продолжения позволяют нам «пометить момент времени в прошлом» и вернуться к этому моменту.

Теперь пошагово. k1 - переменная для хранения указателя на функцию, которая должна позволять «создавать сэндвич». Мы знаем это, потому что k1 объявлено так: (Unit => Sandwich). Однако изначально переменная не инициализирована (k1 = null, «пока нет ингредиентов для приготовления бутерброда»). Поэтому мы пока не можем вызвать функцию, готовящую бутерброд с использованием этой переменной.

Таким образом, мы отмечаем точку выполнения, в которую мы хотим вернуться (или точку в прошлом, в которую мы хотим вернуться), используя инструкцию «reset». makeSandwich - это еще один указатель на функцию, которая позволяет создавать сэндвич. Это последнее утверждение «сброса блока», и, следовательно, оно передается «shift» (функции) в качестве аргумента (shift { k : (Unit => Sandwich).... Внутри shift мы присваиваем этот аргумент переменной k1 k1 = k, таким образом, делая k1 готовым для вызова в качестве функции) После этого мы возвращаемся к точке выполнения, отмеченной сбросом. Следующим оператором является выполнение функции, на которую указывает переменная k1, которая теперь должным образом инициализирована, поэтому в конце мы вызываем makeSandwich, который выводит на экран консоль «Making sandwich». класс сэндвича, который присваивается переменной x.

  1. Не уверен, возможно, это означает, что makeSandwich вызывается не внутри блока сброса, а сразу после этого, когда мы называем его k1 ().
0
ответ дан igorpcholkin 19 January 2019 в 22:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: