Page 1 of 2

Ruby like blocks in Cobra?

PostPosted: Mon Jul 13, 2009 11:14 am
by Csaba
Hi,
Recently Yehuda Katz: pointed out that one of the two main advantages Ruby has over Python is that Ruby can take blocks of code and that is heavily used in Rails. As far as I know, Cobra don’t have Ruby like blocks. So the suggestion is to introduce some Ruby like blocks, for instance, as shown below.

Code: Select all
class TimingUsingClosureAndBlock

   sig ParameterlessSubOrBlock

   def timeIt(aProc  as ParameterlessSubOrBlock) is shared
      startTime= DateTime.now
      print 'Start    [ startTime]'
      aProc.invoke
      print 'Cobra elapsed time is [DateTime.now.subtract(startTime)] seconds'
      print

   def main
   
      timeThis as ParameterlessSubOrBlock = do
         # could be many statements here
         for i in 0:1_000_000
            x = Math.sin(Math.pi*i/2_000_000)
   
      # This is legal Cobra code but requires that the code is in a closure
      .timeIt( timeThis )
      
      # v1 Suggested Ruby like block to achieve the same result
      .timeIt.do
         # could be many statements here
         for i in 0:1_000_000
            x = Math.sin(Math.pi*i/2_000_000)

      # v2  Alternative Ruby like block
      .timeIt(do
         # could be many statements here
         for i in 0:1_000_000
            x = Math.sin(Math.pi*i/2_000_000)

In v1 suggested example, ‘do’ appears in a different context (as in Ruby) but for the same purpose as when used in a closure or lambda. In v2 suggested example do is a “normal” "multi-line statement lamdbda".
It seems like VB 10 will get "multi-line statement lambdas" similar to Ruby blocks but slightly clumsier:

Code: Select all
animal.DoTrick(Sub()
      animal.LegsOnGround = 0
      Console.WriteLine("I'm Jumping now!")
      animal.LegsOnGround = 4
   End Sub)

I hope it is possible to implement some version of blocks in Cobra. (The other main Ruby advantage over Python is simpler meta programming.)
Regards
Csaba

Re: Ruby like blocks in Cobra?

PostPosted: Mon Jul 13, 2009 12:42 pm
by Charles
This is a good question and I have a great answer. Cobra already has blocks of code, also called "closures". They are kicked off with the "do" keyword and the code is indented on the next line. See the test cases.

If you know of some shortcoming that should be addressed let me know. Currently, the types of the arguments are not inferred by the compiler, which takes some of the fun out. But they do work.

This points out, of course, that we need a How To.

If you have any questions, let me know.

Re: Ruby like blocks in Cobra?

PostPosted: Mon Jul 13, 2009 1:58 pm
by Csaba
Hi,
Fine! So this code actually works:
Code: Select all
      .timeIt(do)
         for i in 0:1_000_000
            x = Math.sin(Math.pi*i/2_000_000)

The only problem is with comments:
Code: Select all
      .timeIt(do)
         # This commnet will give compilation error::  Expecting INDENT, but got "\n" (EOL) instead.´
         for i in 0:1_000_000
            x = Math.sin(Math.pi*i/2_000_000)

Thank you!
Regards
Csaba

Re: Ruby like blocks in Cobra?

PostPosted: Mon Jul 13, 2009 11:57 pm
by Charles
Thanks for the report. Will fix.

Re: Ruby like blocks in Cobra?

PostPosted: Thu Jul 16, 2009 12:49 am
by Charles
Fixed.

Re: Ruby like blocks in Cobra?

PostPosted: Fri Jul 17, 2009 1:51 am
by Csaba
Than you! Regards Csaba

Re: Ruby like blocks in Cobra?

PostPosted: Fri Aug 07, 2009 3:30 pm
by todd.a
I vote for changing the syntax used, i.e. use vertical bars :) (I know how much chuck hates those) but at the same time the parentheses don't seem syntactically pleasing to the eye for this use.

Re: Ruby like blocks in Cobra?

PostPosted: Fri Aug 07, 2009 9:05 pm
by Charles
"do" blocks that don't have arguments take no parens at all. "do" blocks with arguments take them as: do(arg1, arg2)

This is identical to declaring arguments for methods as well as declaring sigs:
sig ComputeResult(a as number, b as number) as number  # 1

class Foo

def bar(s as String) # 2
pass

def baz
# ...
t.sort(do(a as Platform, b as Platform) as int) # 3
return a.name.compareTo(b.name)

I don't plan on changing any of the three.

Re: Ruby like blocks in Cobra?

PostPosted: Thu Jul 01, 2010 3:43 pm
by _Gold_Fish
I know this is an old topic, however:
I've been trying to find a way to do something very common in Ruby:
Code: Select all
myArray.delete_if { |value| value == 7 }

This may not be a good example of a portable method, however it does have something I would love to be able to do (or find out how to do), and that is to be be able to pass a whole section of code to a function, and have the function run its own code, be able to execute the passed code when it is told to (like Ruby's "yield" keyword), and be able to supply values to the code block (like "|value|" in the above example.

Re: Ruby like blocks in Cobra?

PostPosted: Thu Jul 01, 2010 6:37 pm
by Charles
This should help:
extend IList<of T>

def printAll(pred as Predicate<of T>)
for item in this
if pred(item)
print 'found:', item


class Program

def main
t = [1, 2, 3, 4, 5, 6]
t.printAll(do(i as int)=i%2==0)

# outputs:
# found: 2
# found: 4
# found: 6

The Predicate type is already available in the .NET standard library. It's for any method that takes an argument and returns a boolean. But if you need something else, you have to declare your own type through "sig".

To call the predicate, or any method reference (called a "delegate" in .NET parlance), you call it with parens: foo(args)

That's pretty similar to invoking other methods except there's nothing to dot (.) because you have the reference already.

And I don't normally structure my code around "print" statements like that, but you can rename .printAll and rewrite it to your purposes.

HTH