Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[and/c | or/c]: ignore any/c | none/c. #4437

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

NoahStoryM
Copy link
Contributor

Before:

Welcome to Racket v8.6 [cs].
> (or/c #t #f (or/c))
(or/c #t #f (or/c))
> (or/c #t #f (or/c) 'x)
(or/c #t #f (or/c) 'x)
> (first-or/c #t #f (first-or/c) 'x)
(first-or/c #t #f (first-or/c) 'x)
> (and/c any/c)
(and/c any/c)
> (and/c any/c any/c)
(and/c any/c any/c)
> (and/c number? (and/c) integer?)
(and/c number? any/c integer?)

After:

Welcome to Racket v8.6 [cs].
> (or/c #t #f (or/c))
boolean?
> (or/c #t #f (or/c) 'x)
(or/c #t #f 'x)
> (first-or/c #t #f (first-or/c) 'x)
(first-or/c #t #f 'x)
> (and/c any/c)
any/c
> (and/c any/c any/c)
any/c
> (and/c number? (and/c) integer?)
(and/c number? integer?)

And the path error in contract/private/types.rkt seems to have no effect on TR, does the current version of TR still need this file to set up information?

By the way, I didn't find define/subexpression-pos-prop/name in the document.

@rfindler
Copy link
Member

Should (or/c) come out as none/c? (Then maybe some of these changes will amount to just looking for none/c?)

@NoahStoryM
Copy link
Contributor Author

Should (or/c) come out as none/c? (Then maybe some of these changes will amount to just looking for none/c?)

Treating (or/c) and (first-or/c) as none/c has no effect since nones (none/c, (or/c), (first-or/c)) are ignored by remq*. And I'm not sure if this change will work, maybe (or/c) and (first-or/c) are used somewhere.

@rfindler
Copy link
Member

I'm not following the comment about remq. And if (or/c) is used somewhere, then that seems fine; it accepts the same values as none/c, right?

@NoahStoryM
Copy link
Contributor Author

I mean maybe some places already use '(or/c) as contract-name. And on the other hand racket provides make-none/c to make new none, so I guess making (or/c) evaluate to none/c may affect some code.

@rfindler
Copy link
Member

That's definitely true. We could do something similar to the way that any/c works (c.f. named-any/c), where there are many "names" for none/c but all of answer true to none/c? (or some other predicate) and then use that predicate when removing them from arguments?

@NoahStoryM
Copy link
Contributor Author

For first-or/c this change I think is feasible.

But if or/c does the same thing, I don't know how to make (opt/c (or/c ...)) return the same name as (or/c ...):

Welcome to Racket v8.6 [cs].
> (or/c 1 2 (make-none/c 'any/c))
(or/c 1 2)
> (opt/c (or/c 1 2 (make-none/c 'any/c)))
#<opt-chaperone-contract: (or/c 1 2 any/c)>

@@ -666,34 +665,21 @@
(define env (contract-random-generate-get-current-environment))
(λ () (random-any/c env fuel)))

(define-struct any/c ()
(define-struct any/c (name)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

Welcome to Racket v8.6 [cs].
> (object-name (or/c any/c any/c any/c))
'named-any/c

After:

Welcome to Racket v8.6 [cs].
> (object-name (or/c any/c any/c any/c))
'any/c

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really sure what's going on here (I can't tell from what I'm reading on github), but I see a diff where a name field was added to any/c and I don't think we want that. We should stick with using named-any/c if we want a name.

@NoahStoryM
Copy link
Contributor Author

NoahStoryM commented Sep 23, 2022

I wonder if racket/contract is willing to provide make-any/c (as the dual of make-none/c) ?
Thus premissive/c can be described as:

If (permissive-xexprs) is #t, then equivalent to (make-any/c 'permissive) any/c, otherwise equivalent to (make-none/c 'permissive).

And also any/c? and none/c? ?

@rfindler
Copy link
Member

I wonder if racket/contract is willing to provide make-any/c (as the dual of make-none/c) ?

I don't think that's necessary.

My thinking is that (or/c) would actually return none/c but the name of that none/c would be still be (or/c). So we'd have (contract-name (or/c)) returning '(or/c) even though, internally, it is a none/c.

This is the setup for the way any/c works for exactly the reasons that you're talking about above.

@NoahStoryM
Copy link
Contributor Author

It makes sense to me. And what about none/c?? Should we provide it?

@rfindler
Copy link
Member

I think none/c? is an internal detail for now. But if there is some contract outside the contract library can benefit from it the way or/c is, then we could provide it. There is always a worry about adding extra names to widely-used libraries, tho.

@@ -620,7 +620,7 @@
(make-struct-type-property 'prop:any/c))

;; this property's value isn't looked at; it is just a signal
;; that the contract accepts any value
;; that the contract accepts none value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "no" instead of "none"?

[() any/c]
[raw-arg*
(define raw-args (remove-duplicates (filter-not prop:any/c? raw-arg*) eq?))
(case (length raw-args)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not do this. Instead do (null? (cdr contracts)) as a new second case.

@@ -666,34 +672,18 @@
(define env (contract-random-generate-get-current-environment))
(λ () (random-any/c env fuel)))

(define-struct any/c ()
(struct any/c ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is removing define- here necessary for the rest of the things that are happening in this PR? If not, let's leave it as is. (I would like to keep the history very clean here as I have used it in the past and it's been helpful.)

@@ -706,19 +696,20 @@
(none/c-name ctc)
val))

(define-struct none/c (name)
(struct none/c (name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto for this change.

#:property prop:flat-contract
(build-flat-contract-property
#:trusted trust-me
#:late-neg-projection none-curried-late-neg-proj
#:stronger (λ (this that) #t)
#:equivalent (λ (this that) (none/c? that))
#:stronger (λ (this that) (prop:none/c? that))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change is incorrect. If there aren't test cases that this change breaks, let's add some.

(cond
[(ormap prop:any/c? args) (named-any/c (contract-name the-or/c))]
[else the-or/c])]))
(let ([none? (make-none/c '(or/c))])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think adding this let is a good idea. We are already using none? as somethign elsewhere here and it is a different thing than this. Also, the let change the indentation, making the diff more painful to work through; in this case we can do this without an indentation change by using define.

[(andmap chaperone-contract? args)
(make-chaperone-first-or/c args)]
[else (make-impersonator-first-or/c args)])]))
(let ([none? (make-none/c '(first-or/c))])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here with the let.

(case-lambda
[() or/c:none/c]
[raw-arg*
(define raw-args (remq* (list none/c or/c:none/c (first-or/c)) raw-arg*))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use a none/c? predicate here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because (or/c ...) and (opt/c (or/c ...)) should have the same name.
#4437 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not following the answer. Definitely it should be the case that opt/c is less important than the regular use, so we should improve opt/c. Can you say more about what's going on here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The contract-name of (opt/c (or/c ...)) is checked in the test file name.rkt.

So if we use none/c?, this test will fail:

> (contract-name (or/c (make-none/c 'none) #t #f))
'boolean?
> (contract-name (opt/c (or/c (make-none/c 'none) #t #f)))
'(or/c none #t #f)
> (test-name 'boolean? (or/c (make-none/c 'none) #t #f))
FAILED (#<procedure:contract-name> #<opt-chaperone-contract: (or/c none #t #f)>)
       got (or/c none #t #f)
  expected boolean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the definition of the name of (opt/c (or/c ...)) .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two options are to adjust the test case to avoid checking opt/c or to improve opt/c to recognize this case and drop the call to make-none/c. I'm happy either way. I think the code that was there, dynamically doing the removal, isn't the best choice, so probably better not to make that more complicated. (If it has to get more complicated, it should be moved into a helper function and a call to the helper function should be generated.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't figured out how to improve opt/c, so I just avoid checking it.

@samth
Copy link
Sponsor Member

samth commented Jan 8, 2024

What's the current status of this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants