#2460 Func.bind() and Func.retype() in Javascript

SlimerDude Fri 11 Sep 2015

Just to mention that currently there's no bind() or retype() methods for Func in Javascript.

bind() I can often get away with by creating a new closure that call the original func with the new arguments. But I don't know a way around retype().

andy Mon 21 Sep 2015

Ticket promoted to #2460 and assigned to andy

SlimerDude Tue 22 Sep 2015

An accumulated patch for Func.retype(), adding methods to Func.js and MethodFunc.js:

diff -r 56d95b6fa8ad src/sys/js/fan/Func.js
--- a/src/sys/js/fan/Func.js	Tue Sep 22 09:31:42 2015 -0400
+++ b/src/sys/js/fan/Func.js	Wed Sep 23 01:39:57 2015 +0100
@@ -76,6 +76,22 @@
 fan.sys.Func.prototype.exitCtor = function() {}
 fan.sys.Func.prototype.checkInCtor = function(obj) {}
 
+fan.sys.Func.prototype.toStr = function() { return "sys::Func"; }
+
+fan.sys.Func.prototype.retype = function(t)
+{
+  if (t instanceof fan.sys.FuncType)
+  {
+    var params = [];
+    for (var i=0; i < t.pars.length; ++i)
+      params.push(new fan.sys.Param(String.fromCharCode(i+65), t.pars[i], 0));
+    var paramList = fan.sys.List.make(fan.sys.Param.$type, params);
+    return fan.sys.Func.make(paramList, t.ret, this.m_func);
+  }
+  else
+    throw fan.sys.ArgErr.make(fan.sys.Str.plus("Not a Func type: ", t));
+}
+
 /*************************************************************************
  * ClosureFuncSpec
  ************************************************************************/
diff -r 56d95b6fa8ad src/sys/js/fan/MethodFunc.js
--- a/src/sys/js/fan/MethodFunc.js	Tue Sep 22 09:31:42 2015 -0400
+++ b/src/sys/js/fan/MethodFunc.js	Wed Sep 23 01:39:57 2015 +0100
@@ -14,6 +14,7 @@
 {
   this.m_method = method;
   this.m_returns = returns;
+  this.m_type = null;
 }
 fan.sys.MethodFunc.prototype.returns = function() { return this.m_returns; }
 fan.sys.MethodFunc.prototype.arity = function() { return this.params().size(); }
@@ -27,8 +28,8 @@
     if ((this.m_method.m_flags & (fan.sys.FConst.Static|fan.sys.FConst.Ctor)) == 0)
     {
       var temp = [];
-      temp[0] = new fan.sys.Param("this", this.m_parent, 0);
-      fparams = fan.sys.List.make(fan.sys.Param.$typeof, temp.concat(mparams));
+      temp[0] = new fan.sys.Param("this", this.m_method.m_parent, 0);
+      fparams = fan.sys.List.make(fan.sys.Param.$type, temp.concat(mparams.m_values));
     }
     this.m_fparams = fparams.ro();
   }
@@ -37,6 +38,20 @@
 fan.sys.MethodFunc.prototype.method = function() { return this.m_method; }
 fan.sys.MethodFunc.prototype.isImmutable = function() { return true; }
 
+fan.sys.MethodFunc.prototype.$typeof = function()
+{
+  // lazy load type and params
+  if (this.m_type == null)
+  {
+    var params = this.params();
+    var types = [];
+    for (var i=0; i<params.size(); i++)
+      types.push(params.get(i).m_type);
+    this.m_type = new fan.sys.FuncType(types, this.m_returns);
+  }
+  return this.m_type;
+}
+
 fan.sys.MethodFunc.prototype.call = function()
 {
   return this.m_method.call.apply(this.m_method, arguments);
@@ -44,13 +59,28 @@
 
 fan.sys.MethodFunc.prototype.callList = function(args)
 {
-  println("### MethodFunc.callList");
-  return this.m_func.apply(null, args.m_values);
+  return this.m_method.callList.apply(this.m_method, arguments);
 }
 
 fan.sys.MethodFunc.prototype.callOn = function(obj, args)
 {
-  println("### MethodFunc.callOn");
-  return this.m_func.apply(obj, args.m_values);
+  return this.m_method.callOn.apply(this.m_method, arguments);
 }
 
+fan.sys.MethodFunc.prototype.retype = function(t)
+{
+  if (t instanceof fan.sys.FuncType)
+  {
+    var params = [];
+    for (var i=0; i < t.pars.length; ++i)
+      params.push(new fan.sys.Param(String.fromCharCode(i+65), t.pars[i], 0));
+    var paramList = fan.sys.List.make(fan.sys.Param.$type, params);
+
+    var func = new fan.sys.MethodFunc(this.m_method, t.ret);
+    func.m_type = t;
+    func.m_fparams = paramList;
+    return func;
+  }
+  else
+    throw fan.sys.ArgErr.make(fan.sys.Str.plus("Not a Func type: ", t));
+}

Testing with testSys::FuncTest.testRetype() the only verifies that now fail are verifyEq(z.isImmutable, true) which relates to js: Func.toImmutable not implemented and this one:

verifyEq(z.callOn("a", ["b", "c", "d", "e", "f", "g", "h"]), "abcdefgh")
...
sys::Err: Test failed: bcdefghnull != abcdefgh

which I'm not too sure about, as it looks to me as if it shouldn't pass anyway!

andy Wed 23 Sep 2015

I missed you a merged one here - can you sync up and test/update this patch so I can merge it correctly?

SlimerDude Wed 23 Sep 2015

Sure, try this:

diff -r 108d631d7a58 src/sys/js/fan/Func.js
--- a/src/sys/js/fan/Func.js	Wed Sep 23 08:05:53 2015 -0400
+++ b/src/sys/js/fan/Func.js	Wed Sep 23 13:40:23 2015 +0100
@@ -79,6 +79,20 @@
 
 fan.sys.Func.prototype.toStr = function() { return "sys::Func"; }
 
+fan.sys.Func.prototype.retype = function(t)
+{
+  if (t instanceof fan.sys.FuncType)
+  {
+    var params = [];
+    for (var i=0; i < t.pars.length; ++i)
+      params.push(new fan.sys.Param(String.fromCharCode(i+65), t.pars[i], 0));
+    var paramList = fan.sys.List.make(fan.sys.Param.$type, params);
+    return fan.sys.Func.make(paramList, t.ret, this.m_func);
+  }
+  else
+    throw fan.sys.ArgErr.make(fan.sys.Str.plus("Not a Func type: ", t));
+}
+
 /*************************************************************************
  * ClosureFuncSpec
  ************************************************************************/
diff -r 108d631d7a58 src/sys/js/fan/MethodFunc.js
--- a/src/sys/js/fan/MethodFunc.js	Wed Sep 23 08:05:53 2015 -0400
+++ b/src/sys/js/fan/MethodFunc.js	Wed Sep 23 13:40:23 2015 +0100
@@ -66,3 +66,21 @@
 {
   return this.m_method.callOn.apply(this.m_method, arguments);
 }
+
+fan.sys.MethodFunc.prototype.retype = function(t)
+{
+  if (t instanceof fan.sys.FuncType)
+  {
+    var params = [];
+    for (var i=0; i < t.pars.length; ++i)
+      params.push(new fan.sys.Param(String.fromCharCode(i+65), t.pars[i], 0));
+    var paramList = fan.sys.List.make(fan.sys.Param.$type, params);
+
+    var func = new fan.sys.MethodFunc(this.m_method, t.ret);
+    func.m_type = t;
+    func.m_fparams = paramList;
+    return func;
+  }
+  else
+    throw fan.sys.ArgErr.make(fan.sys.Str.plus("Not a Func type: ", t));
+}

andy Wed 23 Sep 2015

Got it thanks - Func.retype fixed

Login or Signup to reply.