Does the C# compiler require a function delegate to pass a function as an argument to another function?
In Visual Basic .Net I can pass a function whose return value is of the same type as a method argument to the method itself without anything fancy. This doesn't appear possible in C# unless the method was written to accept a function delegate??
working vb:
Function DoSomething(r As DataRow())
'...
End Function
Function CallSomething()
Dim dt As DataTable
DoSomething(dt.Select(""))
End Function
C# would require the calling code to assign a variable and pass that, or that the referenced function's signature included a delegate (useful to know). Subtle difference but I was expecting that a simple method call made in one language could be just as easily made in the other since they both compile to the same IL.
here's the C# equivalent I was trying to do:
string DoSomething(ref DataRow[] r)
{ ///do something }
void CallSomething()
{
DataTable dt;
DoSomething(ref dt.Select(""));
}
What I meant by "fancy" was the use of delegates, I've used delegates for more complex scenarios, like assigning event handlers to array elements, but I was surprised they would be required for this.
Thanks for the replies. The VB code is functioning as expected, ByRef is implicit in VB, you can't pass an object managed on the heap byval. Nonetheless, here's the simplest form I can provide in VB, if you use a simple forms project w/ a single listbox and drop this code in, should work fine:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim dt As New DataTable("A really great table")
dt.Columns.Add("Column1", GetType(String))
dt.Rows.Add("Row1") : dt.Rows.Add("Row2")
PutRowsInListbox(dt.Select(""))
End Sub
Private Function PutRowsInListbox(ByRef r() As DataRow)
For i As Integer = 0 To r.Length - 1
Me.ListBox1.Items.Add(r(i).Item("Column1"))
Next
End Function
End Class
Your Vb.Net code is not equivalent to your c# code. If you want them to be equivalent, you need to remove the ref keyword on the c# code (or add ByRef on the VB.Net code).
Both visual basic and c# allows this style of programming. Please note, however, that you are not passing a function (or method) to another method here, not in Vb nor in c# - you are simply populating the DataRow array with the results of the data table's Select method.
Since you are not actually passing a method as an argument, a more readable code would be to get the results of the Select method into a variable and pass that variable into the DoSomething method - but that's more a personal preference thing.
The c# code sample you have in the question will not compile.
Here's an equivalent and compilable c# version of the Vb.Net code you have now:
void DoSomething(DataRow[] r)
{
//do something
}
void CallSomething()
{
DataTable dt = null;
DoSomething(dt.Select(""));
}
Of course, that would throw a NullReferenceException unless you actually initialize the dt with a value instead of null.
BTW, ByRef is not implicit. passing reference types does not mean passing them by Reference. That's a common misconception.
When you pass a reference type to a method, what actually is going on is that you are passing the reference itself by value. You can test it easily yourself if you try to reassign the reference inside the method - you'll still see the old value outside the method if you didn't specify ByRef.
Is there an equivalent for the C# 4 'dynamic' keyword when using type safe VB.NET, i.e. with Option Strict On?
The equivalent is Object in VB.NET but with Option Strict Off. With Option Strict On there's no equivalent. Put another way the dynamic keyword brings Option Strict Off equivalent functionality to C#.
VB.NET always had the "dynamic" feature built in, originally called late binding. This syntax was supported forever:
Dim obj = new SomeComClass()
obj.DoSomething()
Worked on code implemented in .NET and COM, the latter being the most common use. The dynamic keyword in C# gave it that same capability. It did get changed in VB.NET version 10 however, it is now using the DLR as well. Which adds support for dynamic binding to language implementations like Python and Ruby.
The syntax is exactly the same, use the Dim keyword without As. You will however have to use Option Strict Off, Option Infer On can soften that blow a bit. It does show that C# using a specific keyword to signal dynamic binding was a pretty good move. Afaik all requests to do so in VB.NET as well have as yet been considered but not planned.
If you prefer Option Strict On, then using the Partial Class keyword so you can move some of the code into another source file is probably the most effective approach.
This will demonstrate what Basic is saying about VB not having the same granularity in this as C#. I have this piece of code in C#, that uses reflection to dynamically invoke a method at runtime:
var listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
The reason I'm doing this is that "GetSomeData" could be any of a number of methods, each getting different data. Which method to invoke here is dependent on a string parameter passed into this object at runtime, so, value of "GetSomeData" varies at runtime.
The signature of "GetSomeData" is:
public List<SomeResultSetClass> GetSomeData()
Each one of the methods invoked returns some sort of List<T> object. Next, I'm sending the listResult object to a generic method called Export, which looks like this:
void Export<T>(List<T> exportList, string filePath, byte fileType) where T: class;
Here's where we run into a problem. Invoke returns an object of type System.Object. Of course, a List<T> is also a System.Object, but the interface exposed is the System.Object interface, not the IList interface. If I try to execute the Export method, thus:
myExportObj.Export(listResult, parms.filePath, parms.fileType);
the code fails to compile. The error is:
The type arguments for method '...Export<T>...' cannot be inferred from the usage. Try specifying the type arguments explicitly.
No thanks!! That's what I'm trying to avoid here. The problem is that the compiler can't find the IList metadata, because it's looking at the System.Object interface. Now, you can create a new List<T>, assign (List<Whatever>) listResult to it, but that defeats the purpose of dynamic invocation in the first place.
The fix is to change var to dynamic:
dynamic listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, null);
Since dynamic bypasses static type checking at compile time, we don't get a compile error. Then, when the dynamic object gets passed to the Export method, the DLR (Dynamic Language Runtime) looks to see if it can implicitly cast the object to meet the requirements of the method signature. Which of course it can.
Ok, so that's how things work in C#. With VB, the line goes like this:
Dim listResult = tgtObj.GetType().GetMethod("GetSomeData").Invoke(tgtObj, Nothing)
With Option Strict On, this line upsets the compiler, as expected. With it off, it works fine. In other words, in VB, I have to turn off the type checker for the entire module that contains the line. There is no finer granularity than that.
You can turn Option Infer On and Option Strict Off and still have something very close.
There are enough ways to handle methods and properties with late binding COM objects and type safe (Option Strict On). This when using the Microsoft.VisualBasic.Interaction.CallByName and System.Type.InvokeMember methods. (Or create a separate "partial" file where Option Strict is Off).
But to handle events with late binding from VB.NET is not as straightforward as with the dynamic type in C#. You can check the "hack" for that in Dynamic Events in VB.NET.
Note that even with Option Strict on you can still use e.g. an ExpandoObject to access properties like:
Dim doc = JsonConvert.DeserializeObject(Of ExpandoObject)("{""name"":""Bob""}")
Dim lookup as IDictionary(Of String, Object) = doc
lookup("name") ' Bob
The equivalent of the c# dynamic keyword in Vb.Net with option strict on exists as a NuGet package: Dynamitey .
After install-package Dynamitey, one can write Vb.Net code as follows:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Dynamic.InvokeMember(o, "Substring", 5)) ' writes 67890
End Sub
End Module
Or the slighly more readable:
Option Strict On : Option Infer On : Option Explicit On
Imports Dynamitey
Module Module1
<Extension()>
Public Function Substring(self As Object, offset As Integer) As String
Return CType(Dynamic.InvokeMember(self, "Substring", offset), String)
End Function
Public Sub Main()
Dim o = Nothing
o = "1234567890"
Console.WriteLine(Substring(o, 5)) ' writes 67890
End Sub
End Module
Tested with VS2017 and .net Framework 4.7.2 .
Yes, ExpandoObject.
Dim DObj = New System.Dynamic.ExpandoObject()
DObj.A = "abc"
DObj.B = 123
This question already has answers here:
Method Signature in C#
(7 answers)
C# overloaded methods
(2 answers)
Generic interface overloading for methods?
(2 answers)
Closed 5 years ago.
--- UPDATE: ---
TL;DR
While it is not possible to have two methods (in the same context; e.g. in the same class) that differ only by their return type, it is possible to solve the problem a different way:
"Return" the value in an out parameter.
(C#) Bad:
// WON'T COMPILE
int myfunc() { ... }
double myfunc() { ... }
(C#) Good:
void myfunc(out int value) { ... }
void myfunc(out double value) { ... }
--- ORIGINAL QUESTION ---
Yes, this has strong similarities to "Generic interface overloading for methods". Thank you for finding that thread. Note however that it is not "an exact duplicate".
Please read the text bar that is inserted once a Q has been marked as a duplicate - it shows that the intent of "duplicate question" is to mark when a question is an exact duplicate of an existing question, and therefore adds nothing to SO. As I explain below, in response to the three proposed duplicates, this is incorrect (IMO). Instead of marking as duplicate, it would be more helpful to add either an answer or a comment linking to the related Q&A, and explaining the connection.
In that case, OP was working with generics, and it is not clear without delving into the details, that there mistake was trying to only differ by return type. Here, OP is focused on OVERLOADING, and thinks maybe the answer is Generics (it is not).
It is a mistake to consider this a duplicate of Q&A about method signature. Someone (including me, before) who didn't grasp that the solution to "overload + differ only by value returned" is solved by using an "out" parameter, is likely to only be confused by reading that Q&A.
Consider the mindset of someone who doesn't yet understand a topic. There is a difference between a related Q&A, which has answers that could be useful to someone if they were given an ANSWER here, which EXPLAINED how that other Q&A helps, and included a link to that Q&A, and a duplicate Q&A, which is a quite similar thread.
I do not see this as a duplicate of How to use generic method with "out" variable.
The reason it is different is because the goal is different.
Yes, the solution is an out parameter, but the goal is to find a way to overload methods differing only by the value returned.
For many years I have believed that doing so is impossible, because "return value is not part of the method signature."
However, I figured that with all the language enhancements, this might be possible now. (What I did not realize until today, was that it was possible to think about the problem in a different way. I figure I'm not the only one to be obtuse about this. Hence this Q&A.)
That other question only helps someone if they already know that the solution is an out parameter. (That question does not mention either "extension" or "return"/"returned value".)
I have a lot of VB read/write code that looks similar to this:
Public Structure MyVertex
Public Position As Vector3
Public Normal As Vector3
Public TextureCoordinates As Vector2
Public Sub Read(br As BinaryReader)
Position = br.ReadVector3()
Normal = br.ReadVector3()
TextureCoordinates = br.ReadVector2()
End Sub
Public Sub Write(bw As BinaryWriter)
bw.WriteVector3(Position)
bw.WriteVector3(Normal)
bw.WriteVector2(TextureCoordinates)
End Sub
End Structure
where the Read/Write methods are extension methods, e.g.
Public Module ReadWriteExtensions
<Extension()>
Public Function ReadVector2(br As BinaryReader) As Vector2
Dim v2 As New Vector2()
v2.X = br.ReadSingle()
v2.Y = br.ReadSingle()
Return v2
End Function
<Extension()>
Public Function ReadVector3(br As BinaryReader) As Vector3
...
End Function
<Extension()>
Public Sub WriteVector2(bw As BinaryWriter, v2 As Vector2)
...
<Extension()>
Public Sub WriteVector3(bw As BinaryWriter, v3 As Vector3)
...
End Module
I know I can use "overloading" of parameter types to simplify the Write methods to have the same name. (I use "WriteT" to distinguish from the built-in BinaryWriter methods, but I could have simply used "Write".):
Public Sub WriteT(bw As BinaryWriter, v2 As Vector2)
...
Public Sub WriteT(bw As BinaryWriter, v3 As Vector3)
...
So usage becomes easier:
Public Sub Write(bw As BinaryWriter)
bw.WriteT(Position)
bw.WriteT(Normal)
bw.WriteT(TextureCoordinates)
End Sub
But I have not done so, because I couldn't see how to do the equivalent to the "Read" methods. The obvious attempt fails because the methods vary only in return type:
<Extension()>
Public Function ReadT(br As BinaryReader) As Vector2
...
<Extension()>
Public Function ReadT(br As BinaryReader) As Vector3
...
Results in compiler error "Member with the same name or signature is already declared ...".
Is there some way to achieve the desired result?
(An answer for C# would also be useful.)
If you could have methods that varied only by return values, then how would you know for sure which method you were calling if the variable to which the result was assigned was implicitly typed or if multiple return types were assignable to the variable?
For example, suppose you had these three methods:
Public Function GetResult() As Object
Return new Object()
End Function
Public Function GetResult() As SomeClass
Return new SomeClass()
End Function
Public Function GetResult() As SomeOtherClass
Return new SomeOtherClass()
End Function
If you do this:
Dim result = whatever.GetResult()
What will result be - Object, SomeClass, or SomeOtherClass?
Even if you could do this:
Dim result as SomeClass = whatever.GetResult()
What if SomeOtherClass inherits from SomeClass? Either one would be valid, so how would you know which one was returned?
But the worst part is that in these scenarios, if you could do this and the compiler attempted to infer which method you meant to call, then you could remove a method, your code would still compile, but removing that method would cause your code to call a different method. That's bad. If we remove the method our code calls, we want a compiler error. We don't want it to transparently guess at the next best method to call.
So one reason (I'm sure there others) is that if signatures could vary only by return type then the selection of methods could be ambiguous, harder to follow, and could change without warning.
On the other side, what is gained by ensuring that two methods have the same name? Giving things different names is a wonderful opportunity to add meaning to our code, and we should do it whenever we can. In fact, in cases where we are allowed to duplicate names, we often shouldn't. For example, we could decide that every method's first parameter should be a, the second should be b, etc. The compiler won't stop us from using a over and over again. But if we did we'd miss out on giving our parameters meaningful names that help others follow the code.
Or we could give all of our classes the same name, but in different namespaces. No compiler errors. But naming things is good, so if the compiler forces us to disambiguate a little with different names, that's also good.
Are these two essentially the same thing? They look very similar to me.
Did lambda expression borrow its idea from Ruby?
Ruby actually has 4 constructs that are all extremely similar
The Block
The idea behind blocks is sort of a way to implement really light weight strategy patterns. A block will define a coroutine on the function, which the function can delegate control to with the yield keyword. We use blocks for just about everything in ruby, including pretty much all the looping constructs or anywhere you would use using in c#. Anything outside the block is in scope for the block, however the inverse is not true, with the exception that return inside the block will return the outer scope. They look like this
def foo
yield 'called foo'
end
#usage
foo {|msg| puts msg} #idiomatic for one liners
foo do |msg| #idiomatic for multiline blocks
puts msg
end
Proc
A proc is basically taking a block and passing it around as a parameter. One extremely interesting use of this is that you can pass a proc in as a replacement for a block in another method. Ruby has a special character for proc coercion which is &, and a special rule that if the last param in a method signature starts with an &, it will be a proc representation of the block for the method call. Finally, there is a builtin method called block_given?, which will return true if the current method has a block defined. It looks like this
def foo(&block)
return block
end
b = foo {puts 'hi'}
b.call # hi
To go a little deeper with this, there is a really neat trick that rails added to Symbol (and got merged into core ruby in 1.9). Basically, that & coercion does its magic by calling to_proc on whatever it is next to. So the rails guys added a Symbol#to_proc that would call itself on whatever is passed in. That lets you write some really terse code for any aggregation style function that is just calling a method on every object in a list
class Foo
def bar
'this is from bar'
end
end
list = [Foo.new, Foo.new, Foo.new]
list.map {|foo| foo.bar} # returns ['this is from bar', 'this is from bar', 'this is from bar']
list.map &:bar # returns _exactly_ the same thing
More advanced stuff, but imo that really illustrates the sort of magic you can do with procs
Lambdas
The purpose of a lambda is pretty much the same in ruby as it is in c#, a way to create an inline function to either pass around, or use internally. Like blocks and procs, lambdas are closures, but unlike the first two it enforces arity, and return from a lambda exits the lambda, not the containing scope. You create one by passing a block to the lambda method, or to -> in ruby 1.9
l = lambda {|msg| puts msg} #ruby 1.8
l = -> {|msg| puts msg} #ruby 1.9
l.call('foo') # => foo
Methods
Only serious ruby geeks really understand this one :) A method is a way to turn an existing function into something you can put in a variable. You get a method by calling the method function, and passing in a symbol as the method name. You can re bind a method, or you can coerce it into a proc if you want to show off. A way to re-write the previous method would be
l = lambda &method(:puts)
l.call('foo')
What is happening here is that you are creating a method for puts, coercing it into a proc, passing that in as a replacement for a block for the lambda method, which in turn returns you the lambda
Feel free to ask about anything that isn't clear (writing this really late on a weeknight without an irb, hopefully it isn't pure gibberish)
EDIT: To address questions in the comments
list.map &:bar Can I use this syntax
with a code block that takes more than
one argument? Say I have hash = { 0 =>
"hello", 1 => "world" }, and I want to
select the elements that has 0 as the
key. Maybe not a good example. – Bryan
Shen
Gonna go kind of deep here, but to really understand how it works you need to understand how ruby method calls work.
Basically, ruby doesn't have a concept of invoking a method, what happens is that objects pass messages to each other. The obj.method arg syntax you use is really just sugar around the more explicit form, which is obj.send :method, arg, and is functionally equivalent to the first syntax. This is a fundamental concept in the language, and is why things like method_missing and respond_to? make sense, in the first case you are just handling an unrecognized message, the second you are checking to see if it is listening for that message.
The other thing to know is the rather esoteric "splat" operator, *. Depending on where its used, it actually does very different things.
def foo(bar, *baz)
In a method call, if it is the last parameter, splat will make that parameter glob up all additional parameters passed in to the function (sort of like params in C#)
obj.foo(bar, *[biz, baz])
When in a method call (or anything else that takes argument lists), it will turn an array into a bare argument list. The snippet below is equivilent to the snippet above.
obj.foo(bar, biz, baz)
Now, with send and * in mind, Symbol#to_proc is basically implemented like this
class Symbol
def to_proc
Proc.new { |obj, *args| obj.send(self, *args) }
end
end
So, &:sym is going to make a new proc, that calls .send :sym on the first argument passed to it. If any additional args are passed, they are globbed up into an array called args, and then splatted into the send method call.
I notice that & is used in three
places: def foo(&block), list.map
&:bar, and l = lambda &method(:puts).
Do they share the same meaning? –
Bryan Shen
Yes, they do. An & will call to_proc on what ever it is beside. In the case of the method definition it has a special meaning when on the last parameter, where you are pulling in the co-routine defined as a block, and turning that into a proc. Method definitions are actually one of the most complex parts of the language, there are a huge amount of tricks and special meanings that can be in the parameters, and the placement of the parameters.
b = {0 => "df", 1 => "kl"} p b.select
{|key, value| key.zero? } I tried to
transform this to p b.select &:zero?,
but it failed. I guess that's because
the number of parameters for the code
block is two, but &:zero? can only
take one param. Is there any way I can
do that? – Bryan Shen
This should be addressed earlier, unfortunately you can't do it with this trick.
"A method is a way to turn an existing
function into something you can put in
a variable." why is l = method(:puts)
not sufficient? What does lambda &
mean in this context? – Bryan Shen
That example was exceptionally contrived, I just wanted to show equivalent code to the example before it, where I was passing a proc to the lambda method. I will take some time later and re-write that bit, but you are correct, method(:puts) is totally sufficient. What I was trying to show is that you can use &method(:puts) anywhere that would take a block. A better example would be this
['hello', 'world'].each &method(:puts) # => hello\nworld
l = -> {|msg| puts msg} #ruby 1.9:
this doesn't work for me. After I
checked Jörg's answer, I think it
should be l = -> (msg) {puts msg}. Or
maybe i'm using an incorrect version
of Ruby? Mine is ruby 1.9.1p738 –
Bryan Shen
Like I said in the post, I didn't have an irb available when I was writing the answer, and you are right, I goofed that (spend the vast majority of my time in 1.8.7, so I am not used to the new syntax yet)
There is no space between the stabby bit and the parens. Try l = ->(msg) {puts msg}. There was actually a lot of resistance to this syntax, since it is so different from everything else in the language.
C# vs. Ruby
Are these two essentially the same thing? They look very similar to me.
They are very different.
First off, lambdas in C# do two very different things, only one of which has an equivalent in Ruby. (And that equivalent is, surprise, lambdas, not blocks.)
In C#, lambda expression literals are overloaded. (Interestingly, they are the only overloaded literals, as far as I know.) And they are overloaded on their result type. (Again, they are the only thing in C# that can be overloaded on its result type, methods can only be overloaded on their argument types.)
C# lambda expression literals can either be an anonymous piece of executable code or an abstract representation of an anonymous piece of executable code, depending on whether their result type is Func / Action or Expression.
Ruby doesn't have any equivalent for the latter functionality (well, there are interpreter-specific non-portable non-standardized extensions). And the equivalent for the former functionality is a lambda, not a block.
The Ruby syntax for a lambda is very similar to C#:
->(x, y) { x + y } # Ruby
(x, y) => { return x + y; } // C#
In C#, you can drop the return, the semicolon and the curly braces if you only have a single expression as the body:
->(x, y) { x + y } # Ruby
(x, y) => x + y // C#
You can leave off the parentheses if you have only one parameter:
-> x { x } # Ruby
x => x // C#
In Ruby, you can leave off the parameter list if it is empty:
-> { 42 } # Ruby
() => 42 // C#
An alternative to using the literal lambda syntax in Ruby is to pass a block argument to the Kernel#lambda method:
->(x, y) { x + y }
lambda {|x, y| x + y } # same thing
The main difference between those two is that you don't know what lambda does, since it could be overridden, overwritten, wrapped or otherwise modified, whereas the behavior of literals cannot be modified in Ruby.
In Ruby 1.8, you can also use Kernel#proc although you should probably avoid that since that method does something different in 1.9.
Another difference between Ruby and C# is the syntax for calling a lambda:
l.() # Ruby
l() // C#
I.e. in C#, you use the same syntax for calling a lambda that you would use for calling anything else, whereas in Ruby, the syntax for calling a method is different from the syntax for calling any other kind of callable object.
Another difference is that in C#, () is built into the language and is only available for certain builtin types like methods, delegates, Actions and Funcs, whereas in Ruby, .() is simply syntactic sugar for .call() and can thus be made to work with any object by just implementing a call method.
procs vs. lambdas
So, what are lambdas exactly? Well, they are instances of the Proc class. Except there's a slight complication: there are actually two different kinds of instances of the Proc class which are subtly different. (IMHO, the Proc class should be split into two classes for the two different kinds of objects.)
In particular, not all Procs are lambdas. You can check whether a Proc is a lambda by calling the Proc#lambda? method. (The usual convention is to call lambda Procs "lambdas" and non-lambda Procs just "procs".)
Non-lambda procs are created by passing a block to Proc.new or to Kernel#proc. However, note that before Ruby 1.9, Kernel#proc creates a lambda, not a proc.
What's the difference? Basically, lambdas behave more like methods, procs behave more like blocks.
If you have followed some of the discussions on the Project Lambda for Java 8 mailinglists, you might have encountered the problem that it is not at all clear how non-local control-flow should behave with lambdas. In particular, there are three possible sensible behaviors for return (well, three possible but only two are really sensible) in a lambda:
return from the lambda
return from the method the lambda was called from
return from the method the lambda was created in
That last one is a bit iffy, since in general the method will have already returned, but the other two both make perfect sense, and neither is more right or more obvious than the other. The current state of Project Lambda for Java 8 is that they use two different keywords (return and yield). Ruby uses the two different kinds of Procs:
procs return from the calling method (just like blocks)
lambdas return from the lambda (just like methods)
They also differ in how they handle argument binding. Again, lambdas behave more like methods and procs behave more like blocks:
you can pass more arguments to a proc than there are parameters, in which case the excess arguments will be ignored
you can pass less arguments to a proc than there are parameters, in which case the excess parameters will be bound to nil
if you pass a single argument which is an Array (or responds to to_ary) and the proc has multiple parameters, the array will be unpacked and the elements bound to the parameters (exactly like they would in the case of destructuring assignment)
Blocks: lightweight procs
A block is essentially a lightweight proc. Every method in Ruby has exactly one block parameter, which does not actually appear in its parameter list (more on that later), i.e. is implicit. This means that on every method call you can pass a block argument, whether the method expects it or not.
Since the block doesn't appear in the parameter list, there is no name you can use to refer to it. So, how do you use it? Well, the only two things you can do (not really, but more on that later) is call it implicitly via the yield keyword and check whether a block was passed via block_given?. (Since there is no name, you cannot use the call or nil? methods. What would you call them on?)
Most Ruby implementations implement blocks in a very lightweight manner. In particular, they don't actually implement them as objects. However, since they have no name, you cannot refer to them, so it's actually impossible to tell whether they are objects or not. You can just think of them as procs, which makes it easier since there is one less different concept to keep in mind. Just treat the fact that they aren't actually implemented as blocks as a compiler optimization.
to_proc and &
There is actually a way to refer to a block: the & sigil / modifier / unary prefix operator. It can only appear in parameter lists and argument lists.
In a parameter list, it means "wrap up the implicit block into a proc and bind it to this name". In an argument list, it means "unwrap this Proc into a block".
def foo(&bar)
end
Inside the method, bar is now bound to a proc object that represents the block. This means for example that you can store it in an instance variable for later use.
baz(&quux)
In this case, baz is actually a method which takes zero arguments. But of course it takes the implicit block argument which all Ruby methods take. We are passing the contents of the variable quux, but unroll it into a block first.
This "unrolling" actually works not just for Procs. & calls to_proc on the object first, to convert it to a proc. That way, any object can be converted into a block.
The most widely used example is Symbol#to_proc, which first appeared sometime during the late 90s, I believe. It became popular when it was added to ActiveSupport from where it spread to Facets and other extension libraries. Finally, it was added to the Ruby 1.9 core library and backported to 1.8.7. It's pretty simple:
class Symbol
def to_proc
->(recv, *args) { recv.send self, *args }
end
end
%w[Hello StackOverflow].map(&:length) # => [5, 13]
Or, if you interpret classes as functions for creating objects, you can do something like this:
class Class
def to_proc
-> *args { new *args }
end
end
[1, 2, 3].map(&Array) # => [[nil], [nil, nil], [nil, nil, nil]]
Methods and UnboundMethods
Another class to represent a piece of executable code, is the Method class. Method objects are reified proxies for methods. You can create a Method object by calling Object#method on any object and passing the name of the method you want to reify:
m = 'Hello'.method(:length)
m.() #=> 5
or using the method reference operator .::
m = 'Hello'.:length
m.() #=> 5
Methods respond to to_proc, so you can pass them anywhere you could pass a block:
[1, 2, 3].each(&method(:puts))
# 1
# 2
# 3
An UnboundMethod is a proxy for a method that hasn't been bound to a receiver yet, i.e. a method for which self hasn't been defined yet. You cannot call an UnboundMethod, but you can bind it to an object (which must be an instance of the module you got the method from), which will convert it to a Method.
UnboundMethod objects are created by calling one of the methods from the Module#instance_method family, passing the name of the method as an argument.
u = String.instance_method(:length)
u.()
# NoMethodError: undefined method `call' for #<UnboundMethod: String#length>
u.bind(42)
# TypeError: bind argument must be an instance of String
u.bind('Hello').() # => 5
Generalized callable objects
Like I already hinted at above: there's not much special about Procs and Methods. Any object that responds to call can be called and any object that responds to to_proc can be converted to a Proc and thus unwrapped into a block and passed to a method which expects a block.
History
Did lambda expression borrow its idea from Ruby?
Probably not. Most modern programming languages have some form of anonymous literal block of code: Lisp (1958), Scheme, Smalltalk (1974), Perl, Python, ECMAScript, Ruby, Scala, Haskell, C++, D, Objective-C, even PHP(!). And of course, the whole idea goes back to Alonzo Church's λ-calculus (1935 and even earlier).
Not exactly. But they're very similar. The most obvious difference is that in C# a lambda expression can go anywhere where you might have a value that happens to be a function; in Ruby you only have one code block per method call.
They both borrowed the idea from Lisp (a programming language dating back to the late 1950s) which in turn borrowed the lambda concept from Church's Lambda Calculus, invented in the 1930s.