我正在通过编译器遍历,并且想要删除多余的movq
指令。例如,此列表:
((movq a b)
(movq b c)
(movq c d)
(movq d e))
应成为((movq a e))
。
同样,列表
((movq a b)
(movq b c)
(addq 20 c)
(movq a b)
(movq c d)
(movq d e))
应简化为:
((movq a c)
(addq 20 c)
(movq a b)
(movq c e))
如果当前的目标与下一个movq
的源匹配,则我的当前(工作)方法将当前和下一个(define (fuse-movq lst) ;; ((movq x y) (movq y z)) => ((movq x z))
(match lst
[`(,x) `(,x)]
[else
(define-values (x z) (values (car lst) (cddr lst)))
(match* (x (cadr lst))
[(`(movq ,a ,b) `(movq ,b ,c)) (fuse-movq (cons `(movq ,a ,c) z))]
[(_ _) (append (list x) (fuse-movq (cdr lst)))])]))
指令融合在一起。
;; core logic
(define (fuse-movq x y)
(match* (x y)
[(`(movq ,a ,b) `(movq ,b ,c)) `(movq ,a ,c)]
[(_ _) (x y)]))
;; list traversal handled by `foldl`
(foldl fuse-movq '() '((movq a b) (movq b c) (movq c d)))
很好,但是我更希望将逻辑与列表遍历分开,更像这样:
foldl
不幸的是,map
似乎不太正确,f
也不起作用,因为我要处理“此元素和下一个元素”。
我用APL和J对此进行了标记,因为将中缀函数lst
应用于J中的f/\lst
的惯用方式是f/
。其中apply f between the next 2 elements
大致翻译为\
,而prefix scan
是processed = 0
starting_after = None
while True:
results = stripe('get', '/subscriptions', params={
'limit': 100,
'starting_after': starting_after
}).json()
for sub in results.get('data'):
print("Checking {0} for customer {1}".format(sub.get('id'), sub.get('customer')))
starting_after = sub.get('id')
if sub.get('items').get('total_count') != 1:
print('Customer {0} has {1} subscriptions ????'.format(sub.get('customer'), sub.get('items').get('total_count')))
continue
plan = sub.get('items').get('data')[0].get('plan')
if plan.get('id') not in maps:
print('Plan {0} was not found'.format(plan.get('id')))
continue
try:
invoice = stripe('get', '/invoices/upcoming', params={
'customer': sub.get('customer')
}).json()
except requests.exceptions.HTTPError as e:
if e.response.status_code != 404:
print(e.json())
continue
print("Ignoring customer {0} because subscription will end ...".format(sub.get('customer')))
continue
expected_amount = invoice.get('total')
try:
new_invoice = stripe('get', '/invoices/upcoming', params={
'customer': sub.get('customer'),
'subscription': sub.get('id'),
'subscription_items[0][id]': sub.get('items').get('data')[0].get('id'),
'subscription_items[0][deleted]': True,
'subscription_items[1][plan]': maps[plan.get('id')],
'subscription_prorate': False
}).json()
except Exception as e:
print(e.response.json())
continue
assert invoice.get('total') == new_invoice.get('total')
assert invoice.get('amount_due') == new_invoice.get('amount_due')
assert invoice.get('next_payment_attempt') == new_invoice.get('next_payment_attempt')
assert invoice.get('period_start') == new_invoice.get('period_start')
assert invoice.get('period_end') == new_invoice.get('period_end')
stripe('post', '/subscriptions/{0}'.format(sub.get('id')), data={
'items[0][id]': sub.get('items').get('data')[0].get('id'),
'items[0][deleted]': True,
'items[1][plan]': maps[plan.get('id')],
'prorate': False
}).json()
updated_invoice = stripe('get', '/invoices/upcoming', params={
'customer': sub.get('customer')
}).json()
assert invoice.get('total') == updated_invoice.get('total')
assert invoice.get('amount_due') == updated_invoice.get('amount_due')
assert invoice.get('next_payment_attempt') == updated_invoice.get('next_payment_attempt')
assert invoice.get('period_start') == updated_invoice.get('period_start')
assert invoice.get('period_end') == updated_invoice.get('period_end')
processed += 1
if not results.get('has_more'):
break
。这些语言非常普遍,我希望在Racket中找到类似的习惯用法。
在Racket中,有没有办法将这种“中缀”的功能行为与列表遍历脱钩?
答案 0 :(得分:1)
您应该能够针对您的用例进行调整。
#lang racket
(define (transform xs)
(for/fold ([prev (list (first xs))] #:result (reverse prev))
([item (in-list (rest xs))])
(match* (prev item)
[((list (list p q) xs ...) (list q r)) (cons (list p r) xs)]
[(xs item) (cons item xs)])))
(transform '([a b] [c d] [d e] [e f] [s t] [g h] [h k] [x y] [y z]))
;=> '((a b) (c f) (s t) (g k) (x z))