Replies: 2 comments
-
Summary of Proposed SyntaxHere's a summary of the syntax proposed in PR #38 and #39. PR #38: Proc and Lambda Type SyntaxProposed Syntax1. Proc Type # Syntax: Proc(ParameterTypes) -> ReturnType
def each(&block: Proc(Integer) -> void): void
yield 1
yield 2
end
def map_values(&block: Proc(Integer, Integer) -> String): Array<String>
[]
end2. Lambda Type (stricter argument checking than Proc) def strict_call(&block: Lambda(Integer) -> void): void
yield 1
end3. Optional Block Parameter ( def maybe_yield(&block?: Proc(Integer) -> void): void
if block_given?
yield 1
end
endRBS Conversion
PR #39: Yield Statement and Expression SupportProposed Syntax1. Yield Statement yield # no arguments
yield x # single argument
yield x, y, z # multiple arguments
yield(x) # parenthesized form
yield x if cond # conditional modifier2. Yield Expression result = yield(value) # capture block return value3. Type Validation def process(&block: Proc(Integer) -> String): void
yield 42 # OK: Integer type
yield "text" # Compile error: expected Integer, got String
yield 1, 2 # Compile error: expected 1 argument, got 2
end |
Beta Was this translation helpful? Give feedback.
-
TL;DRHow about this?
Thoughts on Syntax Style@dfl, these are my personal thoughts. My opinions don't need to be unconditionally accepted. I want to emphasize that I'm always open to discussion and improvement if there are better ideas. IntroductionWhile static type transpiling is the core of T-Ruby, we aim to avoid novel or experimental syntax styles and instead pursue type syntax as close to TypeScript as possible.
We believe this approach brings lower learning costs and higher productivity for more developers and AI. 1. On Function Object TypesIn Ruby, both Lambda and Proc are objects. This is a core philosophy of Ruby.
The proposed Alternative Proposal: # Proposed syntax
def each(&block: Proc(Integer) -> void): void
# Alternative proposal
def each(&block: Proc<(x: Integer) => void>): voidRationale:
2. On Block ParametersType Constraints
Type Inference
# When type is not specified
def each(&block)
# block is inferred as Proc<(x: untyped) => untyped>
# Expressed with generics
def each<T, R>(&block: T): R
# T implicitly extends Proc<(x: untyped) => untyped>
# Explicit constraint
def each<T extends Proc<(x: untyped) => untyped>, R>(&block: T): R
# Restricting to Lambda
def strict_each<T extends Lambda<(x: untyped) => untyped>, R>(&block: T): R
# Of course, you can define types directly without using generics.
def each(&block: Proc<(x: untyped) => untyped>)
def each(&block?: Proc<(x: untyped) => untyped> | nil) # nillable
def each<X, Y, R>(&block: Proc<(x: X) => Y>): R # generic can be used for inside function of procNote: This discussion does not cover which function type definition is better among For now, we will use |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
In this discussion,
I would like to review the 'Proc and Lambda type syntax for block parameters.'
Addressing this topic is a crucial part of T-Ruby's coverage of Ruby and represents a significant step forward.
I am grateful that @dfl has taken the lead by submitting this implementation as a PR (#38 #39).
Special thanks to @dfl for the contribution.
Beta Was this translation helpful? Give feedback.
All reactions