Skip to content

Preserve minimum possible arity in case-lambda-generated procedure - #1167

Open
aartaka wants to merge 2 commits into
ashinn:masterfrom
aartaka:case-lambda-better-arity
Open

Preserve minimum possible arity in case-lambda-generated procedure#1167
aartaka wants to merge 2 commits into
ashinn:masterfrom
aartaka:case-lambda-better-arity

Conversation

@aartaka

@aartaka aartaka commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

It always grated me that case-lambda-created procedures had 0+ arity. Even when having actual clear arglists with fixed / minimum arity. That’s because the current implementation of case-lambda always sets a rest argument and processed it instead of actual arguments. Which is fine! Just that I want more understanding over the structure of the lambda. Thus this pull request: to get the minimum arity of a case-lambda right.

Tested on this expression (try and remove some of the clauses to observe the effect:)

(case-lambda
 (() #f)
 ((x y z . rest) #t)
 ((x y) (+ x y))
 ((x y z) (+ (+ x y) z))
 (args #t))

@aartaka
aartaka force-pushed the case-lambda-better-arity branch from 8103234 to b9fbb90 Compare August 13, 2026 03:16
@aartaka

aartaka commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

CC @ashinn

@ashinn

ashinn commented Aug 13, 2026

Copy link
Copy Markdown
Owner

The code is much larger and harder to follow, expansion is slower, you're pulling SRFI 1 into (scheme base), and the benefit seems minimal (no difference for the 0+ case and the arity alone without a proper name is not very useful).

That said, the depths to which I despise case-lambda cannot be expressed in words, and I'd rather not spend time on this. Remove the SRFI 1 dependency:

(length* (cons* shortest ... . rest))

is just

(length `(shortest ...))

and I can merge this, but if it breaks I'll revert and never accept patches for case-lambda again 😛

@aartaka

aartaka commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

and the arity alone without a proper name is not very useful

Given that most case-lambda-s are bound to something, this should not be a problem. Signaling the right arity in addition to the name is quite helpful, though!

Remove the SRFI 1 dependency:
(length* (cons* shortest ... . rest))
is just
(length `(shortest ...))

Notice that it’s not ... . rest, it’s ... rest (no dot.) So the rest argument is inlined (by cons*) into the total arglist which is then measured by length*. So something like cons* is needed to “flatten“ the rest into the args. Nevermind, I seem to have found it:

`((unquote shortest) ... . (unquote rest))

I pushed a fixed version that no longer depends on SRFI 1. Use your judgement, I’m not particularly attached to this code and it’s fine by me if you don’t merge—it is quite repulsing indeed.

Is there maybe a better macro magic way to get the shorter of two arglists? Mine seems overly complex. Is that the way to go even?

Comment thread lib/srfi/16.sld
;; Generate the actual lambda with the right minimum arity
((%collect-args (shortest ...) (clauses ...))
(lambda (shortest ... . rest)
(let ((len (length `((unquote shortest) ... . (unquote rest)))))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(let ((len (length `((unquote shortest) ... . (unquote rest)))))
(let ((len (+ (length '(shortest ...)) (length rest))))

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.

2 participants