2012-07-19 15 views
11

Chcę funkcji, która pobiera typ wartości w czasie wykonywania. Przykładowe zastosowanie:Jak uzyskać typ wartości w Scheme?

(get-type a) 

gdzie a jest define d być nieco arbitralne wartości pośredniej.

Jak to zrobić? Czy też muszę to zaimplementować, używając stosu cond z boolean?, number? itd.?

Odpowiedz

11

W zastosowaniach Scheme z systemem obiektowym typu Tiny-CLOS, można po prostu użyć class-of. Oto próbka sesja w Racket, wykorzystując oszustwo:

$ racket -I swindle 
Welcome to Racket v5.2.1. 
-> (class-of 42) 
#<primitive-class:exact-integer> 
-> (class-of #t) 
#<primitive-class:boolean> 
-> (class-of 'foo) 
#<primitive-class:symbol> 
-> (class-of "bar") 
#<primitive-class:immutable-string> 

I podobnie podstępnie używając GOOPS:

[email protected](guile-user)> ,use (oop goops) 
[email protected](guile-user)> (class-of 42) 
$1 = #<<class> <integer> 14d6a50> 
[email protected](guile-user)> (class-of #t) 
$2 = #<<class> <boolean> 14c0000> 
[email protected](guile-user)> (class-of 'foo) 
$3 = #<<class> <symbol> 14d3a50> 
[email protected](guile-user)> (class-of "bar") 
$4 = #<<class> <string> 14d3b40> 
4

Aby sprawdzić typ czegoś po prostu dodać znak zapytania po rodzaju, na przykład w celu sprawdzenia, czy x jest liczbą:

(define get-Type 
    (lambda (x) 
    (cond ((number? x) "Number") 
      ((pair? x) "Pair") 
      ((string? x) "String") 
      ((list? x) "List")))) 

Just dalej z tym.

+6

PO szczegółowo zapytał, czy istnieje alternatywa dla tego podejścia. Po co używać zagnieżdżonych 'jeśli's, skoro możesz użyć' cond'? \ * boggles \ * –

+0

@ewein @Chris Jester-Young brakuje tego? Dla '(get-Type (samochód (ciąg-> lista (numer-> ciąg 5)))), to nic nie zwraca. – ArtB

+1

Okazuje się, że w moim przypadku brakujący bit był "znak?". Dla kompletności mamy też "wektor?". – ArtB

9

W rakieta, można użyć pakietu describe Doug Williams od planety. Działa to tak:

> (require (planet williams/describe/describe)) 
> (variant (λ (x) x)) 
'procedure 
> (describe #\a) 
#\a is the character whose code-point number is 97(#x61) and 
general category is ’ll (letter, lowercase) 
+0

Ten pakiet jest rzeczywiście pomocny. Szkoda, że ​​to nie była część Racket. – Salil

3

Wszystkie odpowiedzi tutaj są pomocne, ale myślę, że ludzie zaniedbali wyjaśnienie, dlaczego to może być trudne; Standard Scheme nie zawiera statycznego typu systemu, więc nie można powiedzieć, że wartości mają tylko jeden "typ". Sprawy stają się interesujące w obrębie i wokół podtypów (na przykład liczba vs liczba zmiennoprzecinkowa) i typów związków (jaki typ nadajesz funkcji zwracającej liczbę lub ciąg znaków?).

Jeśli opisać pożądane użycie nieco więcej, może się okazać, że istnieją bardziej szczegółowe odpowiedzi, które pomogą ci więcej.

+5

Mówi "w czasie wykonywania", więc nie ma to nic wspólnego z typami statycznymi. Są to dynamiczne (uruchomione) typy wartości, które stosuje po – newacct

+0

. Tęsknisz za punktem Johna, w tym sensie, że typy dynamicznego środowiska wykonawczego nie zawsze mają wystarczającą ilość informacji do ujednoznacznienia. Konkretny przykład: załóżmy, że mam program, który zajmuje się kolorami i nazwami. Mogę wybrać reprezentowanie wartości tych typów jedynie za pomocą łańcuchów. Następnie, jeśli widzę słowo "Szary", nie mam wystarczających informacji, aby odróżnić typ, ponieważ używam tej samej reprezentacji. – dyoo

+0

Ditto; możesz usunąć słowo "static" z mojego posta i nadal ma to sens. Przykład Danny'ego jest dobry. W rzeczywistości język C ma ten sam problem: nie ma operatora "jaki jest typ tej wartości", ponieważ wiele wartości ma taką samą reprezentację. –