3
votes

Identifiant unique pour les objets Racket?

Existe-t-il un moyen d'obtenir un identifiant unique pour un objet dans Racket? Par exemple, lorsque nous utilisons l'opérateur eq? de Racket pour vérifier si deux variables font référence au même objet, quel identifiant utilise-t-il pour réaliser cette comparaison?

Je recherche quelque chose comme id function ou la méthode object_id de Ruby, dans d'autres mots, une fonction id telle que (= (id obj) (id obj2)) signifie que (eq? obj obj2) est vrai.

Quelques documents pertinents:

Identité des objets et comparaisons

Variables et emplacements


2 commentaires

Pourquoi avez-vous besoin d'un tel numéro?


Malheureusement, je ne me souviens pas exactement maintenant, mais cela avait quelque chose à voir avec la compréhension du fonctionnement de l'interpréteur Racket dans un certain contexte, ou peut-être était-il lié aux types de structure "préfabriqués". En tout cas, je crois que c'était lié à l'apprentissage. Si je me souviens de ce que c'était ou si je pense à un autre cas d'utilisation valable, je prévois de faire un suivi ici.


4 Réponses :


2
votes

Vous ne trouverez probablement pas d'identité, mais l'objet lui-même n'est que eq? avec lui-même et rien d'autre. eq? compare essentiellement l'emplacement d'adresse des valeurs. Donc, si vous voulez un identifiant, vous pouvez simplement stocker l'objet entier à cet endroit et il sera unique.

Un emplacement est une liaison. Considérez-le comme une adresse que vous ne pouvez pas obtenir et une adresse qui a une adresse à un objet. Par exemple. une liaison ((lambda (a) a) 10) stockerait l'emplacement de l'adresse de l'objet 10 dans la première adresse de pile et le code dans le corps la renvoie simplement adresse. Un emplacement peut changer par set! mais vous n'obtiendrez jamais l'emplacement mémoire de celui-ci.

Il est courant pour les systèmes lisp de stocker des valeurs dans des pointeurs. Cela signifie que certains types et valeurs n'ont pas vraiment d'objet à l'adresse, mais que l'adresse contient une valeur et un type codés que le système connaît. En général, les petits entiers, caractères, symboles et booléens peuvent être égaux au pointeur même s'ils sont construits à des moments différents. par exemple. '(1 2 3) n'utiliserait que 3 paires et aucun espace pour les valeurs 1-3 et () .


0 commentaires

3
votes

Il existe un moyen d'obtenir un pointeur C d'un objet via ffi / unsafe , avec la mise en garde évidente que c'est UNSAFE.

(define a (list 1 2))
(define b (list 1 2))

(printf "a and b have different address: ~a ~a\n"
        (equal? (madness a) (madness b))
        (eq? a b))

(printf "a and a have the same address: ~a ~a\n"
        (equal? (madness a) (madness a))
        (eq? a a))

(printf "1 and 1 have the same address: ~a ~a\n"
        (equal? (madness 1) (madness 1))
        (eq? 1 1))

Pour l'utiliser:

;; from https://rosettacode.org/wiki/Address_of_a_variable#Racket

(require ffi/unsafe)

(define (madness v) ; i'm so sorry
   (cast v _racket _gcpointer))

Bien que le pointeur ne soit pas un nombre ou un identifiant. C'est un objet opaque ... Donc dans un sens, c'est un peu inutile. Vous auriez pu utiliser les objets réels avec eq? à la place.

Je ne connais pas non plus de garantie de cette méthode. En particulier, je ne sais pas si le pointeur sera mis à jour à sa dernière valeur lorsque la copie GC copie des objets.


0 commentaires

3
votes

Voici une implémentation d'une telle fonction en utilisant une table de hachage faible. L'utilisation d'une table de hachage faible garantit que les objets sont correctement récupérés même si nous lui avons donné un identifiant.

#lang racket

(define ht (make-weak-hasheq))
(define next 0)

(define (get-id x)
  (define id (hash-ref ht x #f))
  (or id
      (begin0
        next
        (hash-set! ht x next)
        (set! next (+ next 1)))))

(get-id 'a)
(get-id 'b)
(get-id 'a)

Notez que les conseils de Sylwester sont judicieux. La norme est de stocker la valeur directement.


0 commentaires

6
votes

Est eq-hash-code ce que vous voulez?

> (define l1 '(1))
> (define l2 '(1))
> (eq? l1 l2)
#f
> (eq-hash-code l1)
9408
> (eq-hash-code l2)
9412


0 commentaires