<div dir="ltr">OC could suggest moving heavily called functions across boundaries, that&#39;d be cool.<div><br></div><div style>One other place that we realized pretty quickly where we were wrong about the boundaries and inefficiencies is struct declarations. It isn&#39;t uncommon to put contracts on structs and put them in their own module (scribble does this). Currently the contract system can&#39;t tell that a struct contract is actually on a struct and thus avoid checking when doing a selection, but maybe that&#39;s somewhere that could help.</div>
<div style><br></div><div style>Robby</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Dec 27, 2012 at 5:32 PM, Matthias Felleisen <span dir="ltr">&lt;<a href="mailto:matthias@ccs.neu.edu" target="_blank">matthias@ccs.neu.edu</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
1. Robby responded to your first item some time back. He and I had discussed contract-stronger and eq? check several times in the past. But even that doesn&#39;t assure improved checking w/o some performance-oriented thinking on the programmer&#39;s side.<br>

<br>
2. Sam didn&#39;t respond to the second part, which contained two questions. To answer the first one, I changed your code a bit. As for the second one, I think it is a lack os smarts but I am not sure this smarts can be exploited. See below, with modifications labeled MF.<br>

<br>
3. Because we anticipated performance distortions by contracts, Robby and I decided to make contracts a &#39;module&#39; level tool. The hope was that Racket programmers would (1) trust themselves with their own code within a module (&quot;No panic on the Titanic&quot; was my slogan to remind ourselves of this argument; why choose an untyped language otherwise?) and (2) avoid &#39;tight&#39; loops across module boundaries.<br>

<br>
Note: Since then we have learned that Racket programmers don&#39;t trust themselves; see the introduction of define/contract and friends and the repeated misunderstanding that this would check contracts even for internal recursive calls. We have also learned that in the context of generated contracts -- TR -- tight loops might show up.<br>

<br>
I am beginning to wonder whether the work on Optimization Coach should turn to this area next i.e. whether we should figure out a tool that anticipates potential performance problems in linked programs. As a stand-alone library racket/math clearly doesn&#39;t pose any problems. When linked into an untyped context, things might go wrong however -- as your toy benchmark shows. Or we just sit back and hope that nobody is ever bothered by this performance hit because &#39;realistic&#39; programs won&#39;t suffer from this problem.<br>

<br>
-- Matthias<br>
<div class="im"><br>
<br>
<br>
#lang racket<br>
<br>
;; Provides a predicate and constructor for the opaque type `Foo&#39;<br>
(module foo-defs racket<br>
</div> (provide foo? make-foo set-foos foos)<br>
<div class="im"><br>
 (define (make-foo x) x)<br>
<br>
 (define (foo? x)<br>
   (printf &quot;foo?~n&quot;)<br>
   (exact-integer? x))<br>
<br>
</div>  ;; MF: manipulate foos behind your back<br>
  (define (set-foos v)<br>
    (vector-set! v 5 (exact-&gt;inexact (vector-ref v 5))))<br>
<br>
  ;; MF: make foos here<br>
  (define foos (build-vector 10 make-foo)))<br>
<br>
(module typed-defs typed/racket<br>
 (provide get-foo foo-ap bar-ap)<br>
<div class="im"><br>
 (require/typed<br>
  (submod &quot;..&quot; foo-defs)<br>
  [#:opaque Foo foo?]<br>
  [make-foo (Integer -&gt; Foo)]<br>
</div>  ;; MF: type foos properly<br>
  [foos (Vectorof Foo)]<br>
  ;; MF: promise the world here<br>
  [set-foos ((Vectorof Foo) -&gt; Void)])<br>
<div class="im"><br>
 ;; prints `foo?&#39; 10 times; definitely necessary<br>
<br>
</div><div class="im"> (: get-foo (Integer -&gt; Foo))<br>
 (define (get-foo i)<br>
   (vector-ref foos i))<br>
<br>
 (: foo-ap (All (A) ((Foo -&gt; A) Foo -&gt; A)))<br>
 (define (foo-ap f foo)<br>
   (f foo))<br>
<br>
</div>  (: bar-ap (All (A) ((Foo -&gt; A) Integer -&gt; A)))<br>
 (define (bar-ap f foo)<br>
   (f (get-foo foo))))<br>
<br>
(require &#39;typed-defs &#39;foo-defs)<br>
<br>
; I don&#39;t understand why the contract for `get-foo&#39; has to check the return value, because TR already ensures that `get-foo&#39; always returns a `Foo&#39;:<br>
<div class="im"><br>
(printf &quot;going to get a foo~n&quot;)<br>
</div>(set-foos foos) ;; MF: this does NOT raise an error<br>
(with-handlers ((exn:fail:contract:blame? void))<br>
  (get-foo 5) ; prints `foo?&#39; once; why? MF: because it could have been modified, despite the type<br>
  (displayln &quot;ouch, it didn&#39;t catch the problem&quot;))<br>
<br>
; Could TR generate (exact-integer? . -&gt; . any) for `get-foo&#39;?<br>
<div class="im"><br>
; Relatedly, TR already ensures that the function passed to `foo-ap&#39; is only applied to `Foo&#39; values, but this is also checked by a contract:<br>
<br>
(printf &quot;going to apply a function to a foo~n&quot;)<br>
</div>(with-handlers ((exn:fail:contract:blame? void))<br>
  (foo-ap identity (exact-&gt;inexact (get-foo 1))))  ; prints `foo?&#39; twice; why not once, just for 1?<br>
;; MF: the first time because it might get a bad foo<br>
<br>
<br>
(bar-ap identity 5)  ; prints `foo?&#39; twice; why not once, just for 1?<br>
;; MF: After some playing around, I don&#39;t know either.<br>
;; Conjecture: the translation of the All type does not take into account that no matter what (Foo -&gt; A) is applied to a Foo<br>
;; -- statically typed for sure, and possibly protected with a contract<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
_________________________<br>
  Racket Developers list:<br>
  <a href="http://lists.racket-lang.org/dev" target="_blank">http://lists.racket-lang.org/dev</a><br>
</div></div></blockquote></div><br></div>