Re: [racket-users] Why is struct/contract so much faster than a guard?

2020-09-03 Thread Christopher Lemmer Webber
Cool!  Thanks for sharing :)

-- 
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/87imcu8o2i.fsf%40dustycloud.org.


Re: [racket-users] Why is struct/contract so much faster than a guard?

2020-09-03 Thread David Storrs
For the record, a self-plug:

#lang racket

(require struct-plus-plus)

(struct foo-guard (bar baz)
  #:guard (struct-guard/c any/c list?))


(struct/contract foo-contract ([bar any/c]
   [baz list?]))

(struct++ foo-spp  ([bar any/c]
[baz list?]))

(display "#:guard: ")

(time
 (for ([i 100])
   (foo-guard 'yeah '(buddy

(display "struct/contract: ")
(time
 (for ([i 100])
   (foo-contract 'yeah '(buddy

(display "struct++:")
(time
 (for ([i 100])
   (foo-spp++ #:bar 'yeah #:baz '(buddy

#:guard: cpu time: 3335 real time: 3361 gc time: 90
struct/contract: cpu time: 217 real time: 218 gc time: 3
struct++:cpu time: 1255 real time: 1262 gc time: 23

The struct++ version is slower at creation but gives you more security
guarantees later on in the form of functional setters, business rules, and
wrapper functions to normalize data.  For example:


; This accepts a symbol or string and forces it to string.

(struct++ baz-spp ([foo (or/c symbol? string?) ~a]) #:transparent)
(display "Result: ") (println (baz-spp++ #:foo 'bob))
Result: (baz-spp "bob")

; Any struct++ struct will throw an exception if given invalid data

(struct++ bar-spp ([foo integer?]))
(display "Throws: ") (bar-spp++ #:foo 'bob)
Throws:
; bar-spp++: contract violation

;   expected: integer?

;   given: 'bob

;   in: the #:foo argument of

;   (-> #:foo integer? bar-spp?)

;   contract from: (function bar-spp++)

;   blaming: /Users/dstorrs/bmtc_dev/app/test.rkt

;(assuming the contract is correct)

;   at: /Users/dstorrs/bmtc_dev/app/test.rkt

; Context:

;  "/Users/dstorrs/bmtc_dev/app/test.rkt":1:1 [running body]



; Example of more heavily verified struct.  It will accept a string or

; symbol for name and force it to string.  It will round the age down

; so it shows only years. It will default the 'gender' field to the

; symbol 'unknown.  It will make a database connection and verify that

; the department ID is valid.  (In practice you would want to check

; this against an in-RAM table instead of going to disk.)
;
(define (dbh) "mock function that should return a database handle")

(struct++ person ([name (or/c symbol? string?) ~a]
  [age  positive? (compose inexact->exact floor)]
  [(gender 'unknown) (or/c 'male 'female 'other 'unknown)]
  [user-id exact-positive-integer?])
  (#:rule ("department-id exists in the database"
   #:check (user-id)
   [(not (null? (query-rows (dbh) ; get database handle

"SELECT id FROM users WHERE
id=$1"
user-id)))]))
  #:transparent)
(display "Result: ")(println (person++ #:name 'bob #:age 18.5 #:user-id 2))

Result: (person "bob" 18 'unknown 2)

It also provides reflection, functional setters (dotted and dashed
versions), transformation rules, and other things.
https://docs.racket-lang.org/struct-plus-plus/index.html





On Wed, Sep 2, 2020 at 10:43 PM Christopher Lemmer Webber <
cweb...@dustycloud.org> wrote:

> Philip McGrath writes:
>
> > On Wed, Sep 2, 2020 at 3:41 PM Christopher Lemmer Webber <
> > cweb...@dustycloud.org> wrote:
> >
> >> Unfortunately I can't use #:methods with struct/contract so I'm stuck
> >> with the slow one if I want a contract on the struct?
> >>
> >
> > For another option (though you may already know this), I'd advocate for
> > using the `struct` sub-form of `contract-out` and drawing the module
> > boundary as tightly as needed to make it a sensible boundary for trust,
> > potentially by using submodules.
>
> Yes... probably what I should do in the future.
>
> > Since you mention `#:methods` in particular, you should be aware of some
> > subtle corners that make it tricky (and potentially expensive at runtime)
> > to protect  `racket/generic` methods comprehensively with contracts.
> (Here's
> > a pointer to some discussions.
> > ) I think just working
> with
> > struct-type properties can make sense when you don't really need most of
> > the features `racket/generic` gives you.
>
> :O
>
> --
> 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/87wo1ba8c1.fsf%40dustycloud.org
> .
>

-- 
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/CAE8gKodHDOVU3y7V1ZZbEn_hSEP%2BYbbtAqTShRdgMeNX2bWLyA%40mail.gmail.com.


Re: [racket-users] Why is struct/contract so much faster than a guard?

2020-09-02 Thread Christopher Lemmer Webber
Philip McGrath writes:

> On Wed, Sep 2, 2020 at 3:41 PM Christopher Lemmer Webber <
> cweb...@dustycloud.org> wrote:
>
>> Unfortunately I can't use #:methods with struct/contract so I'm stuck
>> with the slow one if I want a contract on the struct?
>>
>
> For another option (though you may already know this), I'd advocate for
> using the `struct` sub-form of `contract-out` and drawing the module
> boundary as tightly as needed to make it a sensible boundary for trust,
> potentially by using submodules.

Yes... probably what I should do in the future.

> Since you mention `#:methods` in particular, you should be aware of some
> subtle corners that make it tricky (and potentially expensive at runtime)
> to protect  `racket/generic` methods comprehensively with contracts. (Here's
> a pointer to some discussions.
> ) I think just working with
> struct-type properties can make sense when you don't really need most of
> the features `racket/generic` gives you.

:O

-- 
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/87wo1ba8c1.fsf%40dustycloud.org.


Re: [racket-users] Why is struct/contract so much faster than a guard?

2020-09-02 Thread Christopher Lemmer Webber
Ah, I didn't know one could just write a function for the guard... but
that makes a lot of sense!

Sam Tobin-Hochstadt writes:

> The issue is that `struct-guard/c` is slow. If you just write a
> function as a guard it's faster than `struct/contract`.
>
> Sam
>
> On Wed, Sep 2, 2020 at 3:41 PM Christopher Lemmer Webber
>  wrote:
>>
>> I tested the following:
>>
>>   (struct foo (bar baz)
>> #:guard (struct-guard/c any/c list?))
>>
>> and:
>>
>>   (struct/contract foo ([bar any/c]
>> [baz list?]))
>>
>> With the first:
>>
>>   test> (time
>>  (for ([i 100])
>>(foo 'yeah '(buddy
>>   cpu time: 2601 real time: 2599 gc time: 7
>>
>> With the second:
>>
>>   test> (time
>>  (for ([i 100])
>>(foo 'yeah '(buddy
>>   cpu time: 184 real time: 184 gc time: 13
>>
>> Wow, what the heck?  That's about a 10x difference.  What?!?!?
>> Why would #:guard be so damn slow in comparison?  You'd think they'd be
>> doing the same thing.
>>
>> Unfortunately I can't use #:methods with struct/contract so I'm stuck
>> with the slow one if I want a contract on the struct?
>>
>> --
>> 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/873640arw7.fsf%40dustycloud.org.

-- 
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/87zh67a8cy.fsf%40dustycloud.org.


Re: [racket-users] Why is struct/contract so much faster than a guard?

2020-09-02 Thread Philip McGrath
On Wed, Sep 2, 2020 at 3:41 PM Christopher Lemmer Webber <
cweb...@dustycloud.org> wrote:

> Unfortunately I can't use #:methods with struct/contract so I'm stuck
> with the slow one if I want a contract on the struct?
>

For another option (though you may already know this), I'd advocate for
using the `struct` sub-form of `contract-out` and drawing the module
boundary as tightly as needed to make it a sensible boundary for trust,
potentially by using submodules.

Since you mention `#:methods` in particular, you should be aware of some
subtle corners that make it tricky (and potentially expensive at runtime)
to protect  `racket/generic` methods comprehensively with contracts. (Here's
a pointer to some discussions.
) I think just working with
struct-type properties can make sense when you don't really need most of
the features `racket/generic` gives you.

-Philip

-- 
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/0100017450ed66ea-e1b5b7a3-11cf-416b-bcab-dc314bc692b2-00%40email.amazonses.com.


Re: [racket-users] Why is struct/contract so much faster than a guard?

2020-09-02 Thread Sam Tobin-Hochstadt
The issue is that `struct-guard/c` is slow. If you just write a
function as a guard it's faster than `struct/contract`.

Sam

On Wed, Sep 2, 2020 at 3:41 PM Christopher Lemmer Webber
 wrote:
>
> I tested the following:
>
>   (struct foo (bar baz)
> #:guard (struct-guard/c any/c list?))
>
> and:
>
>   (struct/contract foo ([bar any/c]
> [baz list?]))
>
> With the first:
>
>   test> (time
>  (for ([i 100])
>(foo 'yeah '(buddy
>   cpu time: 2601 real time: 2599 gc time: 7
>
> With the second:
>
>   test> (time
>  (for ([i 100])
>(foo 'yeah '(buddy
>   cpu time: 184 real time: 184 gc time: 13
>
> Wow, what the heck?  That's about a 10x difference.  What?!?!?
> Why would #:guard be so damn slow in comparison?  You'd think they'd be
> doing the same thing.
>
> Unfortunately I can't use #:methods with struct/contract so I'm stuck
> with the slow one if I want a contract on the struct?
>
> --
> 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/873640arw7.fsf%40dustycloud.org.

-- 
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%2BbX8B9vknFmzqsrnQDkyUmcfnDfio7-LoC1efwAuxSfqA%40mail.gmail.com.


[racket-users] Why is struct/contract so much faster than a guard?

2020-09-02 Thread Christopher Lemmer Webber
I tested the following:

  (struct foo (bar baz)
#:guard (struct-guard/c any/c list?))

and:

  (struct/contract foo ([bar any/c]
[baz list?]))

With the first:

  test> (time
 (for ([i 100])
   (foo 'yeah '(buddy
  cpu time: 2601 real time: 2599 gc time: 7

With the second:

  test> (time
 (for ([i 100])
   (foo 'yeah '(buddy
  cpu time: 184 real time: 184 gc time: 13

Wow, what the heck?  That's about a 10x difference.  What?!?!?
Why would #:guard be so damn slow in comparison?  You'd think they'd be
doing the same thing.

Unfortunately I can't use #:methods with struct/contract so I'm stuck
with the slow one if I want a contract on the struct?

-- 
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/873640arw7.fsf%40dustycloud.org.