badkins
2019-12-30 16:55:46

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?


badkins
2019-12-30 16:57:11

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


badkins
2019-12-30 16:59:55

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


mflatt
2019-12-30 17:25:54

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.


badkins
2019-12-30 17:49:43

Thanks - that’s quite surprising!


badkins
2019-12-30 18:17:55

@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?


notjack
2019-12-30 19:17:16

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


badkins
2019-12-30 19:19:17

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


notjack
2019-12-30 19:20:10

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.


badkins
2019-12-30 19:22:48

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.


badkins
2019-12-30 19:23:08

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


notjack
2019-12-30 19:27:07

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.


notjack
2019-12-30 19:31:51

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.


notjack
2019-12-30 19:50:34

soegaard2
2019-12-30 20:02:43

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


soegaard2
2019-12-30 20:03:44

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


soegaard2
2019-12-30 20:04:29

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


notjack
2019-12-30 20:05:19

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


notjack
2019-12-30 20:05:32

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



soegaard2
2019-12-30 20:09:59

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


soegaard2
2019-12-30 20:29:55

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


soegaard2
2019-12-30 20:30:49

Perhaps “set with consecutive values” ?


notjack
2019-12-30 20:41:29

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


notjack
2019-12-30 20:41:59

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


notjack
2019-12-30 20:43:44

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


soegaard2
2019-12-30 20:43:47

I also think “contiguous” is better.


soegaard2
2019-12-30 20:44:44

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


notjack
2019-12-30 20:44:54

Ahh


notjack
2019-12-30 20:45:47

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


notjack
2019-12-30 20:49:58

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”


badkins
2019-12-30 22:31:32

:+1:


john.champaign
2019-12-31 02:01:09

@john.champaign has joined the channel


john.champaign
2019-12-31 02:04:55

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?


notjack
2019-12-31 02:09:38

@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.


john.champaign
2019-12-31 02:13:16

The redundancy is really bugging me =)


john.champaign
2019-12-31 02:14:27

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


john.champaign
2019-12-31 02:15:39

Then just use the BLURG union without the capacity function?


notjack
2019-12-31 02:22:01

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


john.champaign
2019-12-31 03:01:22

@notjack gotcha, thanks for your thoughts!


sorawee
2019-12-31 07:33:56

@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.


p.kushwaha97
2019-12-31 07:43:00

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.