Skip to content

Allow methods to match on block argument structures. #82

Open
@faultyserver

Description

@faultyserver

In Ruby, blocks are special-cased with how their parameters are matched. Unlike any other method in Ruby, blocks can be given more or fewer arguments than they are defined to accept, and the interpreter will be okay with it:

[1, 2, 3].each{ |a, b, c| puts a }
[1, 2, 3].each{ puts "hi" }

This is really more like javascript, and while I've definitely used/abused this feature before, I don't particularly like its implicit nature from a design perspective.

I would prefer allowing methods to match the structure of the block argument they are given, and define different clauses accordingly. Crystal supports this in a way that's fairly clean, but more verbose and restrictive than I think I would like:

def transform_int(start : Int32, &block : Int32 -> Int32)
  result = yield start
  result * 2
end

transform_int(3) { |x| x + 2 } #=> 10
transform_int(3) { |x| "foo" } # Error: expected block to return Int32, not String

In #57, I've already started describing method signatures using a more terse version of this syntax. Expanded into an actual method definition, it might looks something like this:

def map(&block(e))
  [1, 2, 3].each do |e|
    block(e)
  end
end

def map(&block(e, i))
  [1, 2, 3].each_with_index do |e, i|
    block(e, i)
  end
end

This would define two different clauses that each expect a different block structure, one accepting an index parameter, and the other not. Usage wise, this wouldn't look any different from Ruby:

map{ |e| IO.puts(e) }
map{ |e, i| IO.puts(e, i) }

Maybe this is unnecessary or unhelpful, but I've been thinking about how to more explicitly implement the variadic matching of Ruby blocks, and this is the best I've come up with.

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature-requestAny request for a new feature of the language. Includes both syntax and library features.rfcA request for comments from the communitysyntaxAny issue relating to the syntax of Myst.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions