首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在for/list中使用in-query (DB调用)中的球拍类型注释

在for/list中使用in-query (DB调用)中的球拍类型注释
EN

Stack Overflow用户
提问于 2017-03-30 16:45:18
回答 2查看 154关注 0票数 0

我正在尝试从类型化的Racket中读取数据库中的数据,并将其转换为一个结构列表。下面的代码是正常工作的非类型化版本。这是我所能做的证明问题的最小的一点。

代码语言:javascript
复制
#lang racket

(require db)

(define dbc (sqlite3-connect #:database "dmdb.sqlite3" #:mode 'read/write))

(struct player (name size str dex con base-hp current-hp base-ac attack) #:mutable)

(define get-players
  (lambda (c)
    (for/list
        ([(n s str dex con bhp chp bac attack)
            (in-query c "select * from players")])
      (player n s str dex con bhp chp bac attack))))

该过程的打印版本如下所示:

代码语言:javascript
复制
#lang type/racket
(require typed/db)

(: get-players (-> Connection (Listof player)))
(define get-players
  (lambda (c)
    (for/list
        ([(n s str dex con bhp chp bac attack)
            (in-query c "select * from players")])
      (player n s str dex con bhp chp bac attack))))

当我试图在类型化的Racket中编译它时,我会收到一些奇怪的错误消息:

代码语言:javascript
复制
Type Checker: Expression should produce 9 values, but produces 1 values of
types SQL-Datum in: (for/list (((n s str dex con bhp chp bac attack
(in-query c "select * from players"))) (player n s str dex con bhp chp bac
attack))

同样,只要没有输入代码,代码就能很好地工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-30 20:15:03

看起来,尽管类型化racket中的for语法支持多个值,但实际上不能在typed/racket中键入多个值序列。但是,您可以将一个值序列转换为带有in-values-sequence的列表。在这里,您可以使用define-values将列表拆分回值,或者只使用列表内联。对于您提供的函数,如下所示:

代码语言:javascript
复制
(: get-players (-> Connection (Listof player)))
(define (get-players c)
  (for/list ([a (in-values-sequence (in-query c "select * from players"))])
    (player (list-ref a 0)
            (list-ref a 1)
            (list-ref a 2)
            (list-ref a 3)
            (list-ref a 4)
            (list-ref a 5)
            (list-ref a 6)
            (list-ref a 7)
            (list-ref a 8))))

我怀疑这可能会影响你的程序的性能,但我不能确定是什么。如果您想要创建一个多值序列,您可以向敲诈勒索邮件列表上的人员寻求帮助,因为他们可能知道一些我不知道的事情。

票数 0
EN

Stack Overflow用户

发布于 2017-03-31 18:52:11

在莱夫·安德森的帮助下,我找到了一个答案。下面是我可以创建的最小代码,它允许我测试我的解决方案。它涉及使用query-rows而不是in-query来提取数据,然后操作产生的向量列表。

代码语言:javascript
复制
#lang typed/racket
(require typed/db/base typed/db/sqlite3)


; for testing - cut and paste into interactions window
(define dbc (sqlite3-connect #:database "dmdb.sqlite3" #:mode 'read/write))

(struct player ([name : String] [size : String]
                [str : Integer] [dex : Integer] [con : Integer] [base-hp : Integer]
                [current-hp : Integer]
                [base-ac : Integer] [attack : Integer]) #:mutable )

(define lv (query-rows dbc "select * from players"))

(define ll : (Listof (Listof SQL-Datum))
    (for/list ((v lv))
      (vector->list v)))

(: lv->ll (-> (Listof (Vectorof SQL-Datum)) (Listof (Listof SQL-Datum))))
(define lv->ll
  (lambda (llv)
    (for/list ((v llv))
      (vector->list v))))

(: list->player (-> (Listof SQL-Datum) player))
(define list->player
  (lambda (a)
    (player (cast (list-ref a 0) String)
            (cast (list-ref a 1) String)
            (cast (list-ref a 2) Integer)
            (cast (list-ref a 3) Integer)
            (cast (list-ref a 4) Integer)
            (cast (list-ref a 5) Integer)
            (cast (list-ref a 6) Integer)
            (cast (list-ref a 7) Integer)
            (cast (list-ref a 8) Integer))))

(: list->playerlist (-> (Listof (Listof SQL-Datum)) (Listof player)))
(define list->playerlist
  (lambda (l)
    (for/list ((p l))
      (list->player p))))

(: listvectors->playerlist (-> (Listof (Vectorof SQL-Datum)) (Listof player)))
(define listvectors->playerlist
  (lambda (l)
    (list->playerlist (lv->ll l))))

(disconnect dbc)

我知道在某些圈子里,数据转换被认为是丑陋的,但是我需要强制数据类型,我相信一旦程序出现,没有人会把数据库搞砸。我想,如果他们把数据库搞砸了,那是他们自己的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43123800

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档