A little more information about these things.

I'd say that there are two obstacles to having the racket/contract library
actually be the source of the contract checks in all functions exported by
the racket language/library:

1) dependency layering. The racket/contract library is really a library. So
if that library needs something to actually implement the contract system
(eg string manipulation libraries, which are handy for constructing error
messages), then it can't have a contract that is implemented by the library

2) performance. The contract system has gobs of special cases to get quite
close in various situations but it still doesn't quite ever achieve the
performance of just writing a simple check at the start of the function
(unfortunately). It can be difficult to predict which cases those are (and
there are plenty of situations when the raw overhead of the contract
checking isn't what matters for the performance) but this is an area I'd
like to improve somehow.

One consequence is that some care has been taken, both in the contract
system and in functions like number->string, to make the error messages
look uniform. A giveaway, however, is the "blaming" line, which the
racket/contract contract checking always has and the simple number->string
function checks do not. Including that line forces us to give up on the
performance benefits of just doing the simple check (since that line
requires a precise accounting of who called whom and we have only an
approximate accounting of that from a stacktrace unless we add what has
been deemed (quite reasonably, IMO) unacceptable overhead).

hth,Robby


On Tue, Jun 29, 2021 at 11:11 AM Sam Tobin-Hochstadt <sa...@cs.indiana.edu>
wrote:

> On Tue, Jun 29, 2021 at 12:04 PM Jonathan Simpson <jjsim...@gmail.com>
> wrote:
> >
> > On Monday, June 28, 2021 at 10:25:36 PM UTC-4 Sam Tobin-Hochstadt wrote:
> >>
> >> On Mon, Jun 28, 2021 at 9:46 PM Jonathan Simpson wrote:
> >> >
> >> > On Sunday, June 27, 2021 at 10:29:55 AM UTC-4 Robby Findler wrote:
> >> >>
> >> >> Replacing ` (~r x #:precision 1)` with `(number->string x)` and
> ditto for `y` eliminates the overhead of contracts and brings about another
> 4x speedup on my machine.
> >> >
> >> >
> >> > This is because the compiler is able to remove the contract checks,
> not because number->string doesn't have a contract, correct? If it is the
> compiler, is there any rule of thumb to determine when the compiler will
> likely remove the contract checks? Using typed 'for' iterators seems to be
> one case that the compiler optimizes, but can we rely on others?
> >>
> >> There are two possible meanings for "contract checks" here. One is
> >> "does it check that it gets the right kind of arguments, and raise an
> >> error if not". In that sense, every function that is not "unsafe" has
> >> contracts, certainly including `number->string`. The other meaning is
> >> "uses the `racket/contract` library". The `~r` function has a contract
> >> in that sense, while `number->string` does not, and that's a
> >> significant source of overhead. On my laptop, just removing the
> >> contract on `~r` in the source of the `racket/format` library speeds
> >> up Bogdan's revised program from 600ms to 200ms.
> >>
> >> Most of the time, the compiler does not remove either kind of contract
> >> check. Sometimes the first kind of contract check can be removed in
> >> the simplest of cases; the second kind is basically never removed by
> >> the compiler. There are other cases where macros can generate code
> >> that omits contract checks, as with the `for` forms when used with
> >> sequence generators like `in-list`, but that is again for simple
> >> checks.
> >>
> >> Sam
> >
> >
> > Thanks for the reply. I was under the impression that all of the racket
> provided functions had full racket/contract contracts implemented at the
> module boundary, which is what I thought was generating errors of the form:
> > ---
> > (number->string "aa")
> > ; number->string: contract violation
> > ;   expected: number?
> > ;   given: "aa"
> > ---
>
> That error message is generated here:
>
> https://github.com/racket/racket/blob/master/racket/src/cs/rumble/number.ss#L364
>
> It uses the term "contract", and the exception is an instance of
> `exn:fail:contract`, but it is not generated by the `racket/contract`
> library.
>
> > I take it that the contract error above was generated by a lower-level
> contract then. I've only glanced at contracts, so I assume this is
> documented somewhere. Is this section of the Reference referring to the
> simple contracts that you mention? From
> https://docs.racket-lang.org/reference/contracts.html:
> > ---
> > Contracts come in two forms: those constructed by the various operations
> listed in this section of the manual, and various ordinary Racket values
> that double as contracts, including...
> > ---
>
> That whole section of the reference is about the `racket/contract`
> library, and thus the second kind of contracts that I mentioned.
>
> Sam
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/CAK%3DHD%2BYVJbsqvBzT-52meaoj8vV9XkdXXPFC%3DgL1JTCVxNTizA%40mail.gmail.com
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAL3TdOMCZPf6x2s6E_CuJ89wW6NwNuVwhLFnnBuhp89WeOAR0g%40mail.gmail.com.

Reply via email to