[racket] Case with strings: normal behavior?

24 views
Skip to first unread message

Laurent

unread,
Nov 19, 2012, 8:07:16 AM11/19/12
to Racket Mailing List
Hi,

Is this a bug or a not quite intuitive normal behavior?
> (define (foo s)
    (case s
      [("a") 'a]
      [else 'none]))
> (foo "a")
'a
> (foo (string-append "a" ""))
'none

in 5.3.1.5--2012-11-08(5589bcb/a) [3m].

Laurent

Sam Tobin-Hochstadt

unread,
Nov 19, 2012, 8:12:50 AM11/19/12
to Laurent, Racket Mailing List
`case` compares values with `eqv?`, which distinguishes
distinctly-allocated strings with the same contents. Using `match`
instead of `case` will fix the problem.
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users
>



--
sam th
sa...@ccs.neu.edu
____________________
Racket Users list:
http://lists.racket-lang.org/users

Matthew Flatt

unread,
Nov 19, 2012, 8:13:09 AM11/19/12
to Laurent, Racket Mailing List
This is not-quite-intuitive behavior. The `case' form is based on
`eqv?' instead of `equal?', and the first example works because string
literals are interned, while the result of `string-append' is not.

Should we change `case' to use `equal?' instead of `eqv?'? I can't
think of a good reason to stick with `eqv?'.

Jay McCarthy

unread,
Nov 19, 2012, 8:15:26 AM11/19/12
to Laurent, Racket Mailing List
case compares with eqv?

strings are only ever eqv? if they are eq?

It turns out that Racket guarantees that all literal strings in your
program are eq if they have the same letters, so in your program, the
three "a"s are all the same object.

When you append the empty string to the end, you get a new object, so
it isn't eqv with the other three.
> ____________________
> 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

Robby Findler

unread,
Nov 19, 2012, 8:19:13 AM11/19/12
to Matthew Flatt, Racket Mailing List
I can't think of a good reason either.

We could do a trial period where it uses eqv? and equal? and complains
if it finds a difference and then ask people to run programs. That
seems like an easy enough experiment.

Robby

Laurent

unread,
Nov 19, 2012, 8:20:20 AM11/19/12
to Jay McCarthy, Racket Mailing List
Oh, thank you all for the (prompt!) reminder, I had forgotten about that.
Match works as expected indeed.


Laurent

David T. Pierson

unread,
Nov 20, 2012, 1:14:18 AM11/20/12
to us...@racket-lang.org
On Mon, Nov 19, 2012 at 06:13:09AM -0700, Matthew Flatt wrote:
> Should we change `case' to use `equal?' instead of `eqv?'? I can't
> think of a good reason to stick with `eqv?'.

My first reaction to this was that such a change would eliminate one of
the motivations for using `case': getting the (perhaps insignificant?)
performance improvement of using `eqv?' in a conditional when you know
the key type is suitable for it.

However it occurs to me that since the datums in a `case' clause are
always literals, couldn't the expansion of `case' be "smart" enough to
use the appropriate comparison function (eq?/eqv?/equal?) given the type
of the datum?

David

Robby Findler

unread,
Nov 20, 2012, 8:42:46 AM11/20/12
to David T. Pierson, Racket Users
On Tue, Nov 20, 2012 at 12:14 AM, David T. Pierson <d...@mindstory.com> wrote:
> On Mon, Nov 19, 2012 at 06:13:09AM -0700, Matthew Flatt wrote:
>> Should we change `case' to use `equal?' instead of `eqv?'? I can't
>> think of a good reason to stick with `eqv?'.
>
> My first reaction to this was that such a change would eliminate one of
> the motivations for using `case': getting the (perhaps insignificant?)
> performance improvement of using `eqv?' in a conditional when you know
> the key type is suitable for it.
>
> However it occurs to me that since the datums in a `case' clause are
> always literals, couldn't the expansion of `case' be "smart" enough to
> use the appropriate comparison function (eq?/eqv?/equal?) given the type
> of the datum?

I think that equal? will always terminate quickly when its input is a
symbol/number/boolean so the macro doesn't need to do anything special
in that case.

Robby

Hendrik Boom

unread,
Nov 20, 2012, 9:15:04 AM11/20/12
to us...@racket-lang.org
It could do a binary tree search on the data and use some kind of
ordering comnparison.

By the way, it's a long time since I saw 'datums' as plural of 'datum'.
I wonder if it will become correct one of these years, since 'data' is
often misused as singular, as a substance noun instead of an object
noun.

-- hendrik

Jon Zeppieri

unread,
Nov 20, 2012, 11:54:34 AM11/20/12
to Hendrik Boom, Racket Users
The obvious way to handle strings is to turn the constants into
symbols at expansion time, and dispatch on (string->symbol <input>),
just like we handle chars by turning them into fixnums and using
fixnum dispatch. After that, it's a question of whether you want case
to work for lists, vectors, syntactic hash tables, whatever else. For
my own part, those are better handled by `match.' (Well, maybe not
hash tables.)

Jon Zeppieri

unread,
Nov 20, 2012, 11:57:05 AM11/20/12
to Hendrik Boom, Racket Users
On Tue, Nov 20, 2012 at 11:54 AM, Jon Zeppieri <zepp...@gmail.com> wrote:
> (Well, maybe not hash tables.)
>

I take that back.
Reply all
Reply to author
Forward
0 new messages