
This code works fine; however, if I change any/c
or any
to the actual type, I get unexpected runtime behavior, not a contract error due to the return value of is-public?
being changed to #f erroneously. The actual type of the higher order function is (-> webctx? request? response?)
Any ideas re: why this is happening?

If I replace the body of is-public?
with #t
I can change the contract to the actual values, and is-public?
will still return #t

I have to run to lunch - I’ll check back after …

Use equal?
instead of eq?
. When you apply a higher-order contract to a function, then you may get a new function that performs checks when the function is called. In the case of (-> any./c any/c any)
, there are no checks to delay that way, so no wrapper procedure is created. The eq?
function is tricky and weakly specified—especially with procedures, and even more especially with contracts.

Thanks - that’s quite surprising!

@mflatt are you saying that to verify the type of handler
, the contract will create a wrapper for it that will be verified when the wrapper is called? If so, how does equal?
determine equality?

@badkins equal?
can see through chaperones and impersonators. Wrappers created by contracts are usually chaperones, rarely impersonators, and very very rarely neither.

Thanks - I’ll read through section 14.5 in the reference.

Good plan. Also, as a general rule, consider just never using eq?
at all. That’s what I do and it makes things much easier.

Sure. In this case (when not considering contracts), I knew there was only one instance of the handler, so I figured eq?
was appropriate. Also, there’s little value of a contract in this particular case, so I just removed it.

I do want to learn more about the inner workings in this area though.

The general idea is that a contract like (-> number? string?)
can’t be checked right away, because you don’t know what the function will return until its called. So the contract creates a wrapper that checks the functions inputs and outputs. In this case it’s a chaperone, which is a special kind of wrapper that is not allowed to cause the function to behave in a way that would break equality. So the chaperone wrapper can check the input before giving it to the underlying function, but it can’t give the underlying function a different input. Likewise the output of the wrapper must be equal to the output of the underlying function. The only thing a chaperone is really allowed to do is cause side effects or abort by raising an exception. Because of these restrictions, equal?
considers chaperones “safe” and will treat a chaperone of a function as equal to the original function.

You can see this behavior in action with this code:
#lang racket
(define bad-add1-chaperone-that-doubles-input
(chaperone-procedure add1 (λ (input) (* 2 input))))
(bad-add1-chaperone-that-doubles-input 5)
When run, it raises this error:
procedure chaperone: non-chaperone result;
received a argument that is not a chaperone of the original argument
original: 5
received: 10
The error message is complaining that the wrapper around add1
’s input 5 did not return something equal to the original input.

I made a library for representing ranges of data: https://docs.racket-lang.org/rebellion/Ranges.html\|https://docs.racket-lang.org/rebellion/Ranges.html

I like this. I prefer range
to return a struct representing the range rather than the existing behaviour (returning a list).

Wrt naming: How about replacing (range (inclusive-bound 3) (exclusive-bound 7))
with (range (inclusive 3) (exclusive 7))
?

And perhaps lettting 3
be short for (inclusive 3)
?

If you want shorter construction, I recommend using the smart constructors like (closed-open-range 3 7)
.

I should probably move the smart constructors section up higher in the docs.


FWIW I needed union
for intervals and wrote this: https://github.com/soegaard/metapict/blob/master/metapict/domain.rkt

Btw is it possible to reword “continous set”? That phrase has a meaning in math. https://www.encyclopediaofmath.org/index.php/Continuous_set

Perhaps “set with consecutive values” ?

I originally used the phrase “contiguous set”, does that sound better?

Ranges aren’t discrete so “consecutive” doesn’t seem right

When you say “union”, what is the union of two disconnected ranges? Like [3, 5)
and [8, 10)
.

I also think “contiguous” is better.

The union is the set [3,5) U [8,10) (so it is no longer a range).

Ahh

I would like to add a range set API to rebellion, so that would be a good place for that type of union operation

The docs for ranges are here: https://github.com/jackfirth/rebellion/blob/master/private/range.scrbl#L19 Would happily accept a pull request to change “continuous” to “contiguous”

:+1:

@john.champaign has joined the channel

I’m working through the problem sets for htdp and in set 7 (https://htdp.org/2003-09-26/Problems/7.html) problem 3 (solution here: https://htdp.org/2003-09-26/Problems/Solutions/sol7.html#PROBLEM3) it feels like there’s got to be a better way to handle the capacity function. Three structs each have the same attribute, the cond seems inelegant. I THINK generics are what I want, but I’m having trouble getting them to work. Any pointers to an appropriate tutorial? Should I not be thinking about generics at this point?

@john.champaign I think generics aren’t what you want. There’s easier ways to simplify that, such as pattern matching. But it seems plenty readable as-is.

The redundancy is really bugging me =)

There’s no way to say “these three things are all of type BLURG, which has a cars and a ppc attribute”?

Then just use the BLURG union without the capacity function?

They’re not all the same type though, they only have some overlap. It doesn’t seem worth abstracting over to me.

@notjack gotcha, thanks for your thoughts!

@john.champaign if you use the actual Racket language, there will be a struct
form which allows you to specify super-struct. Like this:
; A Train is one of
(struct train (cars ppc) #:transparent)
; (commuter Number Number Boolean)
(struct commuter train (allstops?) #:transparent)
; (amtrak Number Number Symbol)
(struct amtrak train (type) #:transparent)
; (subway Number Number Symbol)
(struct subway train (color) #:transparent)
;;capacity : Train -> Number
; - return passenger capacity of train
(define (capacity a-train)
(* (train-cars a-train) (train-ppc a-train)))
but for student languages, I don’t think this feature is supported, as it could make things confusing.

What’s the best way to do a while loop in racket? I tried https://docs.racket-lang.org/dyoo-while-loop/index.html but it gives many problems with typechecking. The number of iterations aren’t fixed so I can’t use a for loop.