How to compare `hash` correctly

I'm trying to generate yaml from Racket, once it has been done, I want to check it has the same value as the original reference yaml.

(require yaml)

(define origin (file->yaml "origin.yml"))
(define new ...)
(equal? new origin)

Currently (equal? new origin) produces #f, but after I trace into its value, they look the same.

3 Likes

If "they look the same" means that they are the same textual - then convert the values to strings and compare the strings. An easy way to convert a string is to display the value to a string port. Depending on context you could even use ~a to do the conversion.

1 Like

They look like same in yaml, but yaml has different formats for one type. So I think this is not an option

Jens Axel Søgaard via Racket Discussions <racket@discoursemail.com>於 2021年12月12日 週日,下午9:09寫道:

Do you have a minimal example that shows the problem?

Emmm...... I start to think my code has some problem now, I tried the following code

(equal? (make-hash (list (cons "a" (make-hash (list)))))
        (make-hash (list (cons "a" (make-hash (list)))))

and it works. So my original question has a problem, and I actually can dump hash into YAML and using diff, but still thanks for help!

Beware, mutable and immutable hashes are not equal even if they have equal contents. For example:

> (equal? (make-hash null) (hash))
#f

That's a likely reason for hashes not being equal even if they print the same.

4 Likes

If you only need to generate YAML, not parse it, I've taken advantage of the fact that YAML is defined as a superset of JSON and just used Racket's json library to write it. There are some YAML features that can't be expressed as JSON, but I've never needed them in practice, and I think many YAML-using programs don't even support them.

4 Likes

Agreed; I've been convinced that general YAML has some very poor design choices; sticking to a JSON subset seems like a very good idea.