[racket] struct contract violation problem

23 views
Skip to first unread message

Erik Pearson

unread,
Oct 23, 2013, 6:25:00 PM10/23/13
to Racket Users
Excuse my poor experience with contracts, this is probably an easy one.

I'm using a copy of net/url and have a strange problem. The copied library is working fine in general, but this problem cropped up today:

struct:exn:fail:contract:blame url-port: contract violation
expected: url?
given: #<url>
in: the 1st argument of
(-> url? (or/c #f number?))
contract from: 
/home/epearson/work/racket/github/adaptnet/url-structs.rkt
blaming: /home/epearson/work/racket/github/racqueb/httpc.rkt
at: /home/epearson/work/racket/github/adaptnet/url-structs.rkt:4.28

The error is thrown in my usage of url-port which is being passed a perfectly good url struct object. The file is requiring the copied url-structs. If I play with the function that is being blamed in httpc.rkt via the repl in dr racket, this specific error is not thrown. The call to (url-port url) succeeds without throwing this contract exception.

From my primitive understanding, I'm flummoxed: Why is a #<url> not a url?

I suspected that there may have been a leftover require of net/url confusing things, but I can't find any in my code.

Using racket head from github 5.90.0.9--2013-10-20(d6610289/d)

Help!

Thanks,
Erik.


Matthias Felleisen

unread,
Oct 23, 2013, 6:29:21 PM10/23/13
to Erik Pearson, Racket Users
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users



Here is an interaction in a Racket built today:

> (url-port (string->url "http://www.ccs.neu.edu/"))
#f

Can you confirm this much? Can you add more context.


____________________
Racket Users list:
http://lists.racket-lang.org/users

Jay McCarthy

unread,
Oct 23, 2013, 6:31:21 PM10/23/13
to Erik Pearson, Racket Users
Here are two ideas.

1) You simply have an old use of the original net/url. When #<url> is
printed, it uses the symbolic name and you can't really figure out
what the underlying code came from. I would do a grep to make sure
this is not the case.

2) You are using namespaces somewhere and actually have two instances
of the same module somewhere where a value produced by copy 1 is going
to copy 2. This is possible with the Web server if you don't set up
the servlet namespace properly:

http://docs.racket-lang.org/web-server-internal/dispatch-servlets.html#(part._namespace)
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users
>



--
Jay McCarthy <j...@cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93

Matthias Felleisen

unread,
Oct 23, 2013, 6:33:40 PM10/23/13
to Jay McCarthy, Racket Users

Or you defined

(struct url ...)

somewhere :-)

Erik Pearson

unread,
Oct 23, 2013, 6:38:51 PM10/23/13
to Jay McCarthy, Racket Users
On Wed, Oct 23, 2013 at 3:31 PM, Jay McCarthy <jay.mc...@gmail.com> wrote:
Here are two ideas.

1) You simply have an old use of the original net/url. When #<url> is
printed, it uses the symbolic name and you can't really figure out
what the underlying code came from. I would do a grep to make sure
this is not the case.

Would the operative places to look be the point at which the url object is created and then where it is used? In other words, if it is created in the context of net/url (i.e. a module where net/url is required) and used in a module with adaptnet/url required, it will look like a #<url> (when printed) but not be a url? according to adaptnet/url's url-structs, and where the object travels in between doesn't make a difference?



--
Erik Pearson
Adaptations
;; web form and function

Jay McCarthy

unread,
Oct 23, 2013, 6:40:03 PM10/23/13
to Erik Pearson, Racket Users
Correct

Robby Findler

unread,
Oct 23, 2013, 7:58:44 PM10/23/13
to Erik Pearson, Jay McCarthy, Racket Users
Since there's little background here, I thought I'd just add that this feature you're coming across is one of the critical things that underpins Racket and differentiates it from languages like python and ruby. That is, what you're seeing is that Racket has a way to make unforgeable values. This ability is (in addition to lots of stuff, notably macros) is what makes it possible for Racket's class system to be a library and lots of other things that you'd expect to be built into a language to also be libraries. 

As a little example, if you have these files:

;; a.rkt
#lang racket
(struct url (stuff more-stuff))

;; b.rkt
#lang racket
(struct url (stuff more-stuff))

;; c.rkt
#lang racket
(require (prefix-in a: "a.rkt") (prefix-in b: "b.rkt"))
(b:url-stuff (a:url 1 2))


you'll see an error message very similar to the one you reported.

It is the struct declaration's location (technically when it is evaluated -- you can even stick them inside functions and each time you call the function you get a different notion of "url") that determines which is which.

This is why, for example, you cannot see the hidden stuff inside the class and object structs. Or, for that matter functions! The "lambda" that #lang racket exports is a lot fancier than the low-level built-in lambda, and that is all implemented with structs. Indeed, you cannot tell what is primitive and what is implemented with a struct in some private file (unless you read the source code). Or, to put it another way: everything is implemented with struct and the runtime system is just good at optimizing a small subset of the structs where performance matters.

Robby

Erik Pearson

unread,
Oct 23, 2013, 8:55:03 PM10/23/13
to Robby Findler, Jay McCarthy, Racket Users
Thanks Robby, a nice teaching gift.

I think the problem has "gone away". Realizing my ad-hoc test was run from the file in which url triggers the error, I set about to embed the test in the file / dr racket window that generates url.

I ran a test function, starting very simple and step by step getting closer to the one which fails, but was unable to trigger the error. Finally I returned to the original function, and now I can't trigger the error with it either, even with all the test code removed.

Could it have been a stuck compiled file? Overwritten finally when I was running the tests? I see that my Dr Racket's "Populate 'compiled' directories" is enabled. From my CL days, if I ran into something like this I might blow away all the compiled files and recompile everything from scratch.. Anyway it works now and I'm back to working on the real problems ...

Thanks again for all the lightening fast help!

Erik.

Robby Findler

unread,
Oct 23, 2013, 10:15:36 PM10/23/13
to Erik Pearson, Jay McCarthy, Racket Users
It is extremely unlikely that out of date .zo files could cause this, altho it is, in theory, possible. 

Robby
Reply all
Reply to author
Forward
0 new messages