Тестване, равно на обещание

Как да тествам дали cdr на поток е равен на обещание? Опитвам се да напиша нещо, което изглежда така:

(equal? (stream-cdr s) #<promise>) 

Казва ми, че синтаксисът # е неправилен, така че какъв е правилният начин да напиша това?


person tlauer    schedule 29.03.2013    source източник
comment
Каква библиотека с потоци използвате? Реализация на потока на Racket? (не изглежда така, поради процедурата stream-cdr) srfi/40? srfi/41? Странни потоци в стил SICP? ad-hoc? (след това го публикувайте като част от въпроса)   -  person Óscar López    schedule 29.03.2013
comment
#<...> е как Racket отпечатва стойности, които са нечетими; не можете да използвате този синтаксис във вашата програма. Трябва да създадете обещание, като използвате delay; вижте отговора на Оскар.   -  person Ryan Culpepper    schedule 29.03.2013


Отговори (2)


Това няма да работи, едно „обещание“ няма стойност - все още. Единственият начин да намерите стойността му е като го принудите или оцените по друг начин. В зависимост от начина, по който е имплементиран, може да е функция без аргументи, чакаща да бъде извикана, или забавен обект, чакащ да бъде принуден. Това е нещо като ситуация на принципа на неопределеността на Хайзенберг - не можете да знаете стойността на произволно обещание, докато не го оцените.

Разбира се, ако оцените обещанието, сравнението е лесно. Тъй като от въпроса не става ясно каква библиотека с потоци се използва, ще приема внедряване на ad-hoc странни потоци, използвайки delay (алтернативно: lazy) и force (както е дефинирано в SICP), като това:

(define-syntax stream-cons
  (syntax-rules ()
    ((stream-cons head tail)
     (cons head (delay tail))))) ; also works using `lazy` in place of `delay`

(define (stream-car stream)
  (car stream))

(define (stream-cdr stream)
  (force (cdr stream)))

Както казах, сравнението ще бъде лесно, ако първо се оцени обещанието:

(define promise (delay 42)) ; also works using `lazy` in place of `delay`
(define stream  (stream-cons 16 42))

promise
=> #<promise:promise>
(equal? (stream-cdr stream) promise)
=> #f
(equal? (stream-cdr stream) (force promise))
=> #t
person Óscar López    schedule 29.03.2013

promise е върнатата стойност на delay (и, в някои диалекти на Scheme, make-promise). Можете да тествате равенството на тази стойност с всичко, което желаете. Например:

> (define my-promise (delay "I'll always be good"))
> (equal? "I'll always be good" my-promise)
#f      # a string is not a promise

Във вашия конкретен случай #<promise> е нечетливо печатно представяне на стойност на схема за обещание. Отпечатаното представяне не е стойност и по този начин внедряването на вашата схема ще се оплаква („не може да се чете“). Ако вместо това бяхте обвързали #<promise> с нещо, като some-promise, можеше да опитате:

(equal? (stream-cdr s) some-promise)

Имайте предвид, че обещанието не е неговата стойност; обещанието, когато е принудено, връща стойност. Това е:

(equal? some-promise (force some-promise))

рядко (никога?) е вярно.

person GoZoner    schedule 29.03.2013
comment
R6RS няма make-promise, а R7RS make-promise не прави това, което мислите, че прави (съответства на eager на SRFI 45). R6RS изглежда няма обещания в основната си библиотека, а обещанията на R7RS са създадени с помощта на delay, delay-force (lazy) и make-promise (eager). - person Chris Jester-Young; 30.03.2013