class HFan
{
Void xecho(Int i)
{
echo(i)
}
Void main()
{
g(xecho)
}
Void g(Func m)
{
l := [1,2,3,4,5,6]
x := l.findAll |Int i->Bool| { i % 2 == 0 }
x.each |Int i| { m.call(i) }
}
}
How do I send the xecho method as a callback? I'm getting x.fan(10,11): Unknown slot sys::Void.func ERROR: cannot compile script . I'm not really sure if declaring m as Func is the right way to go here. Not sure how to get the script to compile. Halp! :)
katoxThu 14 Jan 2010
Hey!
You have to write your code like this
class HFan
{
Void xecho(Int i)
{
echo(i)
}
static Void main()
{
hfan := HFan()
hfan.g(#xecho.func)
}
Void g(|HFan implied, Int i -> Void| m)
{
l := [1,2,3,4,5,6]
x := l.findAll |Int i->Bool| { i % 2 == 0 }
x.each |Int i| { m(this, i) }
}
}
Explanation:
you probably wanted main method static, i.e. a starting method for the class,
g is an instance method so it must be called on an existing object (added hfan instance),
xecho is also an instance method, so this parameter is implied even though it is not present it the signature explicitly (like in Python) - see methods as functions,
#xecho gives you xecho slot of the current class and .func provides it as a Func,
in g method call you need a proper signature - the first parameter is a function so all its parameters must be explicit (including this),
in g in call of m you need an extra parameter which is the object on which g is called, i.e. this.
furyThu 14 Jan 2010
Thank you very much for your reply! What if both g and xecho were declared as static? How would main have changed then?
katoxThu 14 Jan 2010
Then you can drop implied this object (which is ignored anyway).
class HFan
{
static Void xecho(Int i)
{
echo(i)
}
static Void main()
{
g(#xecho.func)
}
static Void g(|Int i -> Void| m)
{
l := [1,2,3,4,5,6]
x := l.findAll |Int i->Bool| { i % 2 == 0 }
x.each |Int i| { m(i) }
}
}
with the same result
$ fan hfan.fan
2
4
6
furyThu 14 Jan 2010
This is amazing! Thank you very much! I think I just found my statically-typed Ruby :)
tompalmerThu 14 Jan 2010
I would write it more like this:
class HFan {
Void xecho(Int i) {
echo(i)
}
Void main() {
g {xecho(it)}
}
Void g(|Int i -> Void| m) {
l := [1,2,3,4,5,6]
x := l.findAll {it % 2 == 0}
x.each {m(it)}
}
}
Or something like that. I just got rid of statics, used it where possible, and avoided explicit method references for syntactic convenience.
brianThu 14 Jan 2010
I've found the best technique for simple callbacks is to have a function that takes one parameter, then you can use it-blocks for the simple cases. For example:
Passing methods is IMO still a week point of Fantom.
C#:
class Program
{
static void xecho(int i)
{
Console.WriteLine(i);
}
static void Main(string[] args)
{
g(xecho);
}
static void g(Action<int> m)
{
var l = new List<int> { 1, 2, 3, 4, 5, 6 };
var x = l.FindAll(i => i % 2 == 0);
foreach (var i in x) { m(i); }
}
}
You can just call g(xecho) in C# (or this.xecho if it's an instance method).
brianThu 14 Jan 2010
Passing methods is IMO still a week point of Fantom.
I agree. The fundamental problem is that we don't require the () to call a method. If didn't have that then method would be unambiguous as pass method as function.
But I think b/w the two I'd rather have () be optional.
Something I agree we still need to make easier.
furyThu 14 Jan 2010
I'm still new to Fantom, but I think that () would be nice to be necessary for function calls. If you just do object.method in Python, you'll get the method object. In my opinion, it looks more readable.
fury Thu 14 Jan 2010
Hi guys!
If I have this code:
How do I send the xecho method as a callback? I'm getting x.fan(10,11): Unknown slot
sys::Void.func
ERROR: cannot compile script . I'm not really sure if declaring m as Func is the right way to go here. Not sure how to get the script to compile. Halp! :)katox Thu 14 Jan 2010
Hey!
You have to write your code like this
Explanation:
main
methodstatic
, i.e. a starting method for the class,g
is an instance method so it must be called on an existing object (addedhfan
instance),xecho
is also an instance method, sothis
parameter is implied even though it is not present it the signature explicitly (like in Python) - see methods as functions,#xecho
gives youxecho
slot of the current class and.func
provides it as aFunc
,g
method call you need a proper signature - the first parameter is a function so all its parameters must be explicit (includingthis
),g
in call ofm
you need an extra parameter which is the object on whichg
is called, i.e.this
.fury Thu 14 Jan 2010
Thank you very much for your reply! What if both g and xecho were declared as static? How would main have changed then?
katox Thu 14 Jan 2010
Then you can drop implied
this
object (which is ignored anyway).with the same result
fury Thu 14 Jan 2010
This is amazing! Thank you very much! I think I just found my statically-typed Ruby :)
tompalmer Thu 14 Jan 2010
I would write it more like this:
Or something like that. I just got rid of statics, used
it
where possible, and avoided explicit method references for syntactic convenience.brian Thu 14 Jan 2010
I've found the best technique for simple callbacks is to have a function that takes one parameter, then you can use it-blocks for the simple cases. For example:
helium Thu 14 Jan 2010
Passing methods is IMO still a week point of Fantom.
C#:
You can just call
g(xecho)
in C# (orthis.xecho
if it's an instance method).brian Thu 14 Jan 2010
I agree. The fundamental problem is that we don't require the
()
to call a method. If didn't have that thenmethod
would be unambiguous as pass method as function.But I think b/w the two I'd rather have
()
be optional.Something I agree we still need to make easier.
fury Thu 14 Jan 2010
I'm still new to Fantom, but I think that () would be nice to be necessary for function calls. If you just do object.method in Python, you'll get the method object. In my opinion, it looks more readable.