Nano Hash - криптовалюты, майнинг, программирование

Использование переменных let в лямбде на схеме

Этот вопрос по своему охвату аналогичен: В схеме R6RS есть способ получить текущую среду для использования с eval? но я хотел бы пойти дальше и спросить, как бы вы исправили что-то вроде это.

Моя проблема еще больше осложняется тем, что в моем случае '(+ x y) является произвольным неоцененным лямбда-выражением. Без оценки, потому что он может содержать вызовы переменных, которые являются частью let (и поскольку Scheme не верит в то, что процедура будет вызываться в среде, содержащей эти переменные, когда текущая нет, она вызывает ошибку неопределенного идентификатора) . Таким образом, возникает вопрос: как я могу реструктурировать свой код, чтобы этот кошмар определения области видимости больше не был проблемой? Я хотел бы по-прежнему иметь возможность использовать переменные среды из let всякий раз, когда вызывается лямбда.

Я использую Pretty Big

Намерение состоит в том, чтобы создать классы в Scheme. Мой подход пока довольно обширен (без каламбура), но выглядит так:

    (define (dispatch msg methods args)
      (if (null? methods) (display "Method signature not found.")
          (let (
                (m-name (caar methods))
                (m-args (cadar methods))
                (m-body (caddar methods)))
            (if (and (eq? msg (caar methods)) (eq? (length args) (length (cadar methods))))
                `(lambda ,m-args ,m-body)
                (dispatch msg (cdr methods) args)))))

    (define (build-lets c-def)
      (let (
            (i-vars (cadr c-def))
            (meths (caddr c-def)))
        (eval `(append ',i-vars (list (list 'methods '',meths))))))

    (define (new c-def . args)
      (apply (eval `(lambda ,(map cadr (cadr c-def))
               (let* ,(build-lets c-def)
                 (lambda (msg . args)
                   (letrec ((meth (dispatch msg methods args)))
                     (apply meth args))))))
             args))

Где c-def - это класс def формы (скажем, для точки)

    '(();Name of parent
      ((yvalue y) (xvalue x)) ;Instance variables: (i-var constructor-arg)
      ((getx () xvalue) ;Methods, ((name args body) ...)
       (setx (x) (set! xvalue x)))))
17.04.2013

  • Я не уверен, что вы пытаетесь сделать, у вас есть пример кода? 17.04.2013
  • @ ChrisJester-Young Я думаю, он хочет придумать способ, чтобы что-то вроде (let ((x 1)) (eval '(* x 2))) вернуло 2. 17.04.2013
  • @ Максвелл, это точно 17.04.2013
  • @Maxwell Этот конкретный случай можно решить с помощью local-eval от Guile, но это не то, что поддерживает Racket. Поэтому я посмотрю на обновленный вопрос OP и посмотрю, есть ли другой способ сделать это. 17.04.2013
  • @KPatnode Для вашего конкретного случая использования, я думаю, вам придется использовать макросы (а не eval). Конечно, все встроенные классы Racket выполняются с использованием макросов. 17.04.2013

Ответы:


1

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

(define-syntax make-object
  (syntax-rules ()
    [(__ ([ivar ival] ...) ([method-name args body ...] ...))
      (let ([ivar ival] ...)
        (λ (msg . oargs)
          (cond
            [(eq? 'method-name msg)
              (apply (λ args body ...) oargs)] ...
            [else
              (error 'object-system "unknown message" msg)])))]))

(define o (make-object ([xvalue 'x])
                       ([getx () xvalue]
                        [setx (x) (set! xvalue x)])))

(o 'getx) => x
(o 'setx 'blah)
(o 'getx) => blah

Уловка состоит в том, чтобы написать макрос, выполняющий закрытие. Переменные экземпляра входят в лексическую область видимости (let), которая содержит замыкание. Замыкание - диспетчер. Методы - это лямбды, определенные в диспетчере, поэтому переменные экземпляра находятся в той же области, что и методы.

17.04.2013
  • Это именно то, что мне нужно, чтобы двигаться в правильном направлении. Спасибо! 17.04.2013

  • 2

    Если вы можете сделать let частью eval, тогда он будет работать. Ниже приведен пример:

    Что-то похожее (но более простое) на ваш код, который не работает:

    (define (hello m)
      (let ((msg m))
        (eval '(print msg))))
    

    Делаем let частью eval, чтобы он работал:

    (define (hello m)
      (eval `(let ((msg ,m))
               (print msg))))
    
    17.04.2013
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..