Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crystal How to check if the block argument is given inside the function

Tags:

crystal-lang

Suppose a function defined like this:

def composition(text : String, k : Int32) : Array(String)
  kmers = Array(String).new
  (0 .. text.size - k).each do |i|
    kmers << text[i, k]
    yield text[i, k]
  end
  return kmers
end

How do I check if the block argument is given inside the function? If the block argument is given, kmers will be yielded. If not given, kmers will be returned as an array of strings.

like image 508
Wen-Bin Luo Avatar asked Oct 26 '25 14:10

Wen-Bin Luo


3 Answers

Such a check is impossible, because a method accepting a block (using yield anywhere) already has a signature requiring it. But that also means that you don't need the check. If you want to make it optional, just make 2 methods like this:

# if you want to be explicit (makes no difference, this method requires a block):
# def composition(text : String, k : Int32, &block)
def composition(text : String, k : Int32)
  (0 .. text.size - k).each do |i|
    yield text[i, k]
  end
end

# and the non block option
def composition(text : String, k : Int32) : Array(String)
  kmers = [] of String
  composition(text, k) do |s|
    kmers << s
  end
  return kmers
end
like image 193
Oleh Prypin Avatar answered Oct 29 '25 14:10

Oleh Prypin


In your specific situation, I would recommend Oleh's answer. However, here's a more general solution that lets you determine whether a block has been passed:

def composition(text, k, &block : String ->)
  composition(text, k, block)
end

def composition(text, k, block : (String ->)? = nil)
  kmers = [] of String
  (0 .. text.size - k).each do |i|
    s = text[i, k]
    if block
      block.call s
    else
      kmers << s
    end
  end
  kmers
end

(For more information on Proc syntax, see https://crystal-lang.org/reference/syntax_and_semantics/type_grammar.html#proc)

like image 32
fn control option Avatar answered Oct 29 '25 15:10

fn control option


Such a check is impossible, because a method accepting a block (using yield anywhere) already has a signature requiring it. But that also means that you don't need the check. If you want to make it optional, just make 2 methods like this:

# if you want to be explicit (makes no difference, this method requires a block):
# def composition(text : String, k : Int32, &block)
def composition(text : String, k : Int32)
  (0 .. text.size - k).each do |i|
    yield text[i, k]
  end
end

# and the non block option
def composition(text : String, k : Int32) : Array(String)
  kmers = [] of String
  composition(text, k) do |s|
    kmers << s
  end
  return kmers
end
like image 42
Oleh Prypin Avatar answered Oct 29 '25 15:10

Oleh Prypin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!