Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 5, 2025

Implements a refactoring rule that fuses map expressions with for loops when the intermediate list is only used once, eliminating unnecessary list construction.

Example transformation:

;; Before
(define ys (map (λ (x) (g x)) xs))
(for* ([y (in-list ys)]
       [z (in-list (h y))])
  (displayln z))

;; After
(for* ([x (in-list xs)]
       [y (in-list (g x))]
       [z (in-list (h y))])
  (displayln z))

Implementation details:

  • Multi-clause fusion: For for* loops with multiple clauses, inlines the map body as a nested clause
  • Single-clause fusion: For simple for loops, converts map body to internal definitions
  • Lambda handling: Supports single-body, multi-body, and let-refactorable lambdas. Multi-body lambdas have their side effects extracted before the final result binding
  • Safety check: Only applies when the intermediate list has usage count of 1

Files:

  • default-recommendations/loops/fuse-map-with-for.rkt - rule implementation with two variants
  • default-recommendations/loops/fuse-map-with-for-test.rkt - test cases covering all lambda forms
  • default-recommendations.rkt - added suite to default recommendations
Original prompt

This section details on the original issue you should resolve

<issue_title>New rule: fuse-map-with-for</issue_title>
<issue_description>### Rule summary

A map expression that produces a list which is immediately iterated over by a for* loop can be fused with the for* loop, if the intermediate list isn't used elsewhere. This avoids constructing the intermediate list and is usually more readable. This should only be applied when the map expression is given a short lambda.

Test case

#lang resyntax/test

test: "original code should be refactorable to new code"
--------------------
#lang racket
(define (f xs g h)
  (define ys (map (λ (x) (g x)) xs))
  (for* ([y (in-list ys)]
         [z (in-list (h y))])
    (displayln z)))
====================
#lang racket
(define (f xs g h)
  (for* ([x (in-list xs)]
         [y (in-list (g x))]
         [z (in-list (h y))])
    (displayln z)))
--------------------

No-change test case

#lang resyntax/test

no-change-test: "code not refactorable"
--------------------
#lang racket
(define (f xs g h)
  (define ys (map (λ (x) (g x)) xs))
  (for* ([y (in-list ys)]
         [z (in-list (h y))])
    (displayln z))
  (displayln ys))
--------------------

Additional context

Spotted this here in racket/drracket#783.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Add new rule to fuse map with for loop Add fuse-map-with-for refactoring rule Dec 5, 2025
Copilot AI requested a review from jackfirth December 5, 2025 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New rule: fuse-map-with-for

2 participants