@@ -371,13 +371,10 @@ the typed racket language.
371
371
stx
372
372
(begin (define-syntax name (define-for-variant #'untyped-name )) ... ))]))
373
373
374
- ;; for/first: and for/and:'s expansions
375
- ;; can't currently be handled by the typechecker.
376
374
(define-for-variants
377
375
(for/list: for/list )
378
376
(for/and: for/and )
379
- (for/or: for/or )
380
- (for/first: for/first ))
377
+ (for/or: for/or ))
381
378
382
379
;; Unlike with the above, the inferencer can handle any number of #:when
383
380
;; clauses with these 3.
@@ -461,8 +458,7 @@ the typed racket language.
461
458
... ))]))
462
459
(define-for*-variants
463
460
(for*/and: for*/and )
464
- (for*/or: for*/or )
465
- (for*/first: for*/first ))
461
+ (for*/or: for*/or ))
466
462
467
463
;; Like for/lists:, for/fold: and for/foldr:, the inferencer can handle these correctly.
468
464
(define-syntaxes (for*/lists:)
@@ -555,6 +551,43 @@ the typed racket language.
555
551
(for/product: for/fold: for/product #f * 1 #%expression )
556
552
(for*/product: for*/fold: for*/product #t * 1 #%expression ))
557
553
554
+ (define-for-syntax (define-for/acc:-break-variant for*? for/folder: for/folder op break-op initial final)
555
+ (lambda (stx)
556
+ (syntax-parse stx #:literals (:)
557
+ [(_ a1:optional-standalone-annotation*
558
+ clause:for-clauses
559
+ a2:optional-standalone-annotation*
560
+ c ... ) ; c is not always an expression, can be a break-clause
561
+ (define a.ty (or (attribute a2.ty)
562
+ (attribute a1.ty)))
563
+ (cond
564
+ [a.ty
565
+ ;; ty has to include exact 0, exact 1, null (sum/product/list respectively),
566
+ ;; the initial value of the accumulator
567
+ ;; (to be consistent with Racket semantics).
568
+ ;; We can't just change the initial value to be 0.0 if we expect a
569
+ ;; Float result. This is problematic in some cases e.g:
570
+ ;; (for/sum: : Float ([i : Float '(1.1)] #:when (zero? (random 1))) i)
571
+ (quasisyntax/loc stx
572
+ (#,final
573
+ (#,for/folder: : #,a.ty ([acc : #,a.ty #,initial])
574
+ (clause.expand ... ... )
575
+ #:break (#,break-op acc #,initial)
576
+ (let ([new (let () c ... )])
577
+ (#,op acc new )))))]
578
+ ;; With no annotation, try our luck with the core form.
579
+ ;; Exact base cases cause problems, thus the additional
580
+ ;; annotation on the accumulator above.
581
+ [for*? ((define-for*-variant for/folder) stx)]
582
+ [else ((define-for-variant for/folder) stx)])])))
583
+
584
+ (define-syntax for/first:
585
+ (define-for/acc:-break-variant
586
+ #f 'for/fold: 'for/first 'begin (λ (x y) (not (equal? x y))) #f '#%expression ))
587
+ (define-syntax for*/first:
588
+ (define-for/acc:-break-variant
589
+ #t 'for*/fold: 'for*/first 'begin (λ (x y) (not (equal? x y))) #f '#%expression ))
590
+
558
591
;; originally, we made the mistake of providing these by default in typed/racket/base
559
592
;; so now we have this trickery here
560
593
;; This trickery is only used for `typed/racket/base`; `typed/racket` just provides the
0 commit comments