Forum: Ruby Seeking C# references about Ruby Code block functionality

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
dkmd_nielsen (Guest)
on 2007-05-17 19:20
(Received via mailing list)
I have two rather simple class methods coded in Ruby...my own each
iterator:

   # Loop through each instruction in the block, yielding the result
from
   # the specified code block.
   def each(&logic)
      @instructions.each {|instr| yield instr}
   end

   # Find the specified instruction parm (string) in the block.
Returns
   # nil if parm not found.
   def find(p)
      self.each {|i| return i if i.parm.index(p) }
      nil
   end

I'm trying to recode this exact functionality in C#, and am just not
getting the Delegate stuff.  Can you direct me to some online examples
or references that show how to pass a delegate into method that
implements an iterator?  I'm just not getting all the new C#
terminology and syntax complexities, and I need to learn it.  MSDN
isn't helping me at all.  The following is quasi psuedo mock up of
what I'm trying to accomplish.

        public void each(Delegate block)
        {
            foreach (FL_Instruction i in this.Instructions)
            {
                block;
            }
        }

        public static FL_Instruction find(string parm)
        {
            FindParm fp = delegate(FL_Instruction i) { if
(i.Parm.IndexOf(parm) > 0) { return i; } };
            this.each(fp);
            return null;
        }

Thanks for your time and consideration,
dvn
Justin B. (Guest)
on 2007-05-17 20:15
(Received via mailing list)
On 5/17/07, dkmd_nielsen <removed_email_address@domain.invalid> wrote:
>             }
>         }

C# gives you the yield keyword now, so I think you can code this
directly, without a delegate:

public void each()
{
  foreach(FL_instruction in in this.Instructions)
    yield i;
}

Haven't used yield myself yet so YMMV. However, as you might see
below, you don't really need this function unless you want to provide
an external iterator because it doesn't do what you want in C#.

>
>         public static FL_Instruction find(string parm)
>         {
>             FindParm fp = delegate(FL_Instruction i) { if
> (i.Parm.IndexOf(parm) > 0) { return i; } };
>             this.each(fp);
>             return null;
>         }

 In C#, delegates represent function signatures. You are wanting to
pass functions with different signatures (including return type) to
each. That works in Ruby but not C#.  Instead, define a function
exists which takes a Predicate delegate (defined in the System
namespace):

// finds an individual instruction
public static FL_instruction find(string parm)
{
  // "anonymous" delegate, which defines a function that takes an
FL_instruction
 // and tests it against the passed in "parm" parameter.
  Predicate<FL_Instruction> findParm = delegate(FL_Instruction i) {
return i.Parm.IndexOf(parm) > 0 };

  FL_instruction [] found = this.findAll(findParm);
  if(found.Length > 0)
    return found[0];
  else
    return null;
}

// Function which takes a test and applies it to all the instructions
// in this class. An array of instructions which passed the test are
returned,
// or a zero-length array.
public static FL_instruction findAll(Predicate<FL_instruction> test)
{
   ArrayList found = new ArrayList();
   foreach(FL_instruction i in this.INstructions)
    if(test(i))
     found.Add(i)

  return found.ToArray(); // have to convert to array of FL_instructions
}

Array.Exists (and other similar functions) will do all of this and
more, so take a look at them.

Hope that helps!

Justin
Ryan D. (Guest)
on 2007-05-17 21:38
(Received via mailing list)
On May 17, 2007, at 08:20 , dkmd_nielsen wrote:

>    # Find the specified instruction parm (string) in the block.
> Returns
>    # nil if parm not found.
>    def find(p)
>       self.each {|i| return i if i.parm.index(p) }
>       nil
>    end

I know it isn't what you're asking but FWIW, if you code #each and
include Enumerable, you get this exact find for free.
dkmd_nielsen (Guest)
on 2007-05-18 17:06
(Received via mailing list)
>
> Haven't used yield myself yet so YMMV. However, as you might see
> below, you don't really need this function unless you want to provide
> an external iterator because it doesn't do what you want in C#.
>

Thanks for all the info, Justin. I'll try to digest it.  I want to
provide an external iterator as many classes will be using this from a
DLL.  The internals of this calls are to be hidden.  The purpose of
"each" is to provide the looping functionality while hiding the
details.  The example I had given (in Ruby) demonstrated that I was
using the "each" internally, as well as using it externally.

I would think the delegate would work because the signature should not
change.  The framework is always the same, "instruction
= ??.each(parm)", returning the instruction that matches the parm or
nil.

Again, thanks for the info.  And if others have suggestions, I would
appreciate it.  Once I have that feeling of, "Ah Haa...now I got it",
then I will be good to go in the future.

dvn
This topic is locked and can not be replied to.