[racket-dev] promise vs polym contracts

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Sat Jul 7 10:14:51 EDT 2012

As Carl pointed out, I should explain more background. 

Stephen and I are exploring how to get laziness in Racket w/o going 
to Lazy Racket (in a sense). As I wrote the idea is to introduce laziness
in a somewhat transparent manner, the way Sam introduces types in a mostly
transparent manner (minus polymorphic exports and bugs). 

What this particularly means is that I do not want programs to change
behavior silently. So yes you get promise? and you get force so that 
you can retrieve computations as needed. BUT it becomes your responsibility 
to force things for all strict functions/points in your language (e.g., 
add1, function application, if). If you forget to force there or insert 
a promise?, the language traps the value. 

;; --- 

The more general idea is that there is an alternative design space 
out there where you want 'boxes' that signal errors when touched by 
strict functions. You need these every time you want transparent 
transitions from one point in the computational spectrum to another. 

;; ---

And one more level up, I am thinking of selling Racket as a wide-spectrum
programming language, the first one that introduces "safe" or "transparent"
transitions properly. 

-- Matthias, CPS 

p.s. Sam's version forces too early because strict functions should 
force not variable lookups. This is a common misconception among programmers. 
I suspect it goes back to Abelson and Sussman getting it wrong (see what 
happens if you don't understand the foundations). 

Then again, Racket is PITCO so in a sense the force is executed at the right 
place in this particular example, even though it was inserted in the wrong place. 

On Jul 6, 2012, at 8:19 PM, Robby Findler wrote:

> Lets say I have a function that gets a list of promises or lists. It
> is going to print out the state of some ongoing computation (that is
> producing these lists). It will print the list, if there's a list, and
> it will print "pending" if it is a promise; it doesn't want to force
> it, since it is just a view.
> Somewhere else, something is building new lists-- when it decides to
> force something, it replaces the promise in the list with the forced
> value and then hands a new list off to the view.
> (But in general, it just seems useful to be able to ask if something
> is a promise without forcing it.)
> Robby
> On Fri, Jul 6, 2012 at 4:53 PM, Matthias Felleisen <matthias at ccs.neu.edu> wrote:
>> I can't think of such a primitive other than force, for which it is okay. Can you be concrete?
>> On Jul 6, 2012, at 5:16 PM, Robby Findler wrote:
>>> What do you do if you have a function that accepts either promises or
>>> lists? Then, you might want total predicates.
>>> Robby
>>> On Fri, Jul 6, 2012 at 2:22 PM, Matthias Felleisen <matthias at ccs.neu.edu> wrote:
>>>> I just realized that Racket already suffers from the problem that polymorphic contracts introduce.
>>>> As Stephen is working out right now, Racketeers want to introduce laziness to speed up programs on occasion. We have been told for decades that delay and force are our friends. In a sense, this performance-refactoring problem is exactly the same problem as incremental type refactoring aka gradual typing. You want to add laziness in a transparent manner -- or if you make a mistake, it should blow up on you.
>>>> But it doesn't:
>>>>> Welcome to DrRacket, version [3m].
>>>>> Language: racket.
>>>>>> (null? (delay (/ 1 0)))
>>>>> #f
>>>>>> (zero? (delay (/ 1 0)))
>>>>> . . zero?: contract violation
>>>>> expected: number?
>>>>> given: #<promise:unsaved-editor12957:6:9>
>>>> For some reasons I don't understand, our ancestors (let's not use their name anymore) decided to make some primitives resistant to promises and some aren't. Now imagine you accidentally package a null in a delay, which may happen when you use lazy combinators:
>>>>>> (null? (delay null))
>>>>> #f
>>>> Your program changes meaning and off it goes and signals an error. You don't get a faster program, you get a program that raises the wrong kind of error.
>>>> What they should have done is signal an exception when strict primitives receive a promise.
>>>> I take it is too late to correct such a {\HUGE HUGE} historical blunder. -- Matthias
>>>> _________________________
>>>> Racket Developers list:
>>>> http://lists.racket-lang.org/dev

Posted on the dev mailing list.