#racket
#racket
Вопрос:
Я читаю файл .csv и с помощью
(define-struct my-struct (id name))
(apply my-struct '("5" "Tomas"))
(string? (my-struct-id (apply my-struct '("5" "Tomas"))))
преобразование его в struct. Однако все поля являются строковыми, есть ли какой-нибудь элегантный способ принудительного string->number
преобразования, например, для id
поля?
Большое спасибо.
Комментарии:
1.
(apply my-struct (map string->number '("5" "Tomas"))
?2. это нарушает drracket … кроме того, я хочу, чтобы только «5» было преобразовано в number, а не «tomast» в # f
3. Я надеялся на какой-то более автоматический способ, что-то вроде:
define-struct my-struct (id #:number name))
Ответ №1:
На мой взгляд, существует два варианта. Первый из них самый простой, используйте пользовательский конструктор:
; Option 1: Make a dedicated constructor that
; handles the conversion.
(struct my-struct (id name) #:transparent)
(define (create-struct id name)
(my-struct (string->number id) name))
Второй вариант — (ab) использовать защиту:
; Option 2: Use a guard
(define (converter id name the-struct-name)
(values (string->number id) name))
(struct my-second-struct (id name) #:guard converter #:transparent)
(apply my-second-struct '("5" "Tomas"))
Комментарии:
1. Связано с вариантом 1: когда кто-то хочет предоставить структуру с измененным конструктором, можно сделать это следующим образом:
(provide (except-out (struct-out person) person) (rename-out [make-person person]))
Ответ №2:
Чтобы завершить ответ soegaard, если вы предоставляете свою структуру и используете ее в других модулях, вы также можете добавить контракт для предотвращения неправильного использования:
#lang racket/base
(require racket/contract)
(provide (contract-out
[struct person ((id number?) (name string?))]))
(struct person (id name))
> (require my-module/person)
> (person 42 "Margaret")
#<person>
> (person "haxxor" 1337)
; person: contract violation
; expected: number?
; given: "haxxor"
; in: the 1st argument of
; (-> number? string? person?)
Смотрите полную документацию здесь: https://docs.racket-lang.org/guide/contracts-struct.html #(part._contracts-define-struct)
Комментарии:
1. Спасибо, я также буду использовать contract, если бы я только мог принять оба ответа.