racket / macro-debugger

Other
8 stars 16 forks source link

check-requires does not report redundant (require racket) #2

Closed wolverian closed 9 years ago

wolverian commented 9 years ago

Given this file (foo.rkt):

#lang racket

(require racket)

Checking the requires:

~/src $ raco check-requires foo.rkt 
(file "foo.rkt"):

~/src $

Nothing is reported, even though the (require racket) is redundant.

This was originally reported against the Emacs racket-mode repo at https://github.com/greghendershott/racket-mode/issues/117.

rmculpepper commented 9 years ago

check-requires doesn't report information about specific require forms. It deals with sets of imports (an import is a pair of module and phase offset).

You could combine check-requires with code that matches the import set to the require forms seen in the program, but you'd also have to deal with issues like macros expanding into require. Or come up with some simpler conservative approximation.

greghendershott commented 9 years ago

Thanks for replying!

I think this is confusing for me because:

I'm not saying this is a huge, urgent problem. Just that it's confusing.

For purposes of the racket-mode feature: I suppose I could check the module form and remove any phase 0 require, regardless of what macro-debugger/check-requires reports. I'm fine doing that. I'm just curious why it doesn't already happen.

samth commented 9 years ago

I think this isn't an issue with the #lang line at all. This module:

#lang racket/base
(require racket/list)
(require racket/list)
first

doesn't produce any suggestions from raco check-requires either.

greghendershott commented 9 years ago

@samth OK I see. In other words "useless" here means "you don't need to require this module". It doesn't mean "you do need to require this but you're requiring it multiple times".

Independent of what macro-debugger advises, I do already de-dupe the list of required modules, so I would transform your example to (require racket/list). But currently I only consider things inside require forms -- not the module lang. To close https://github.com/greghendershott/racket-mode/issues/117, it looks like I would need to do what I described above -- remove from that list any module that is also the module language. But only if it's not qualified by something like a rename-in and so on.

Anyway I think this issue against macro-debugger can be closed.

samth commented 9 years ago

@greghendershott note that having the (require racket) isn't exactly the same. For example, this is a syntax error:

#lang racket
(require racket)
(define + 5)

But this works:

#lang racket
(define + 5)

That's not necessarily saying that racket-mode should behave either way, though.

greghendershott commented 9 years ago

And this works:

#lang racket
(require (except-in racket +))
(define + 5)

So. I realize I don't have a crisp understanding. My practical intuition has been that the x in #lang x or (module m x ....) is "like requiring x". But reading the Guide carefully, it is referred to as the initial-module-path. Not only is it not a require, it is how the require form itself is obtained. It is an import. The precise terminology Ryan used. The Guide says: "In other words, the initial-module-path import bootstraps the syntax that is available in the body."

Hmm. I feel like I should have a more-solid understanding of this, by now. Off to search for things to read....

OK, the Reference is pretty clear about the mechanism you illustrated. There's it's called the module-path, and

The module-path form must be as for require, and it supplies the initial bindings for the body forms. That is, it is treated like a (require module-path) prefix before the forms, except that the bindings introduced by module-path can be shadowed by definitions and requires in the module body forms.

So. It is like a require (but is not the require form itself; it is how the require form is imported), but the bindings it imports may be shadowed. And now the examples make sense.