Какие проблемы C-интеграции возникают с реализациями VM без стека?

С реактивным значением:

library(dplyr)
library(DT)
library(shiny)

ui <- fluidPage(
  fluidRow(
    numericInput("num1", "Limiter", value = 0)
  ),
  fluidRow(
    actionButton("button1", "Apply filters")
  ),
  fluidRow(
    dataTableOutput("testtable")
  )
)

server <- function(input, output, session) {

  filteredData <- reactiveVal(iris)
  observeEvent(input$button1, {
    filteredData(iris %>% filter(Petal.Length >= input$num1))
  })

  output$testtable <- renderDataTable(datatable(filteredData()))
}

shinyApp(ui, server)
7
задан Seki 11 June 2015 в 12:39
поделиться

2 ответа

После переписки по электронной почте со Стивом Декорте (автором языка программирования Io) и Константином Оленин, я нашел проблему и (частичное) решение. Представьте себе вызов от виртуальной машины к функции C, которая вызывает метод виртуальной машины. В течение периода времени, когда виртуальная машина выполняет обратный вызов, часть состояния виртуальной машины находится вне виртуальной машины: в стеке C и регистрах. Если вы сохраните состояние виртуальной машины в этот момент, то вы гарантированно не сможете правильно восстановить состояние при следующей загрузке виртуальной машины.

Решение состоит в моделировании виртуальной машины как субъекта, принимающего сообщения: виртуальная машина может отправлять асинхронные уведомления на собственный код и собственный код могут отправлять асинхронные уведомления на виртуальную машину. То есть в однопоточной среде, когда виртуальная машина получает управление, за ее пределами не сохраняется никакого дополнительного состояния (кроме данных, не относящихся к времени выполнения виртуальной машины).

Это не означает, что вы можете правильно восстановить состояние виртуальной машины при любых обстоятельствах, но, по крайней мере, вы можете построить на его основе свою собственную надежную систему.

1
ответ дан 7 December 2019 в 10:07
поделиться

Похоже, вы уже знакомы с некоторыми недостатками и преимуществами.

Некоторые другие: a) Делает возможным поддерживать правильную оптимизацию хвостового вызова, даже если базовая реализация не поддерживает ее б) Легче создавать такие вещи, как "трассировка стека" на уровне языка. c) Легче добавлять правильные продолжения, как вы отметили

. Недавно я написал простой интерпретатор "Scheme" на C #, который изначально использовал стек .NET. Затем я переписал его, чтобы использовать явный стек - так что, возможно, вам поможет следующее:

Первая версия использовала неявный стек времени выполнения .NET ...

Первоначально это была просто иерархия классов с другими формы (Lambda, Let и т. д.) являются реализациями следующего интерфейса:

// A "form" is an expression that can be evaluted with
// respect to an environment
// e.g.
// "(* x 3)"
// "x"
// "3"
public interface IForm
{
    object Evaluate(IEnvironment environment);
}

IEnvironment выглядела так, как и следовало ожидать:

/// <summary>
/// Fundamental interface for resolving "symbols" subject to scoping.
/// </summary>
public interface IEnvironment
{
    object Lookup(string name);
    IEnvironment Extend(string name, object value);
}

Для добавления «встроенных функций» к моему интерпретатору схемы у меня изначально был следующий интерфейс:

/// <summary>
/// A function is either a builtin function (i.e. implemented directly in CSharp)
/// or something that's been created by the Lambda form.
/// </summary>
public interface IFunction
{
    object Invoke(object[] args);
}

Это было тогда, когда он использовал неявный стек времени выполнения .NET. Кода определенно было меньше, но было невозможно добавить такие вещи, как правильная хвостовая рекурсия, и, что наиболее важно, моему интерпретатору было неудобно обеспечивать «языковой уровень» новый ThreadState вместо того, чтобы изменять его так, чтобы у меня была задача «продолжение вызова») ... и т. д. и т. д.

По сути, вы просто меньше зависите от реализации основного языка.

О единственном недостатком, который я могу найти, является производительность ... Но в моем случае это всего лишь интерпретатор, так что меня все равно не особо заботит производительность.

Я также рекомендую вам прочитать эту очень хорошую статью о преимуществах повторного использования. написание рекурсивного кода в виде итеративного кода со стеком одним из авторов компилятора KAI C ++: Учитывая рекурсию

5
ответ дан 7 December 2019 в 10:07
поделиться
Другие вопросы по тегам:

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