Velocity Reviews > function and arguments as aguments

# function and arguments as aguments

Telmo Costa
Guest
Posts: n/a

 02-15-2006
Hi. I have the following code:

--------------------------------------
function Tunnel() {
//arguments[0](???);
}

function Sum() {
var sum = 0;
for (i=0; i<arguments.length; i++) sum += arguments[i];
};

// calling Sum directly
Sum(1,2,3,4);

// calling Sum through Tunnel
Tunnel(Sum, 1,2,3,4);
--------------------------------------

How should the Tunnel function be defined, knowing that the number of
parameters passed are unknown?

telmo

UnaCoder
Guest
Posts: n/a

 02-15-2006
You would be better off designing Sum to take an array as an argument,
then you can just pass the array of arguments to Sum

Telmo Costa
Guest
Posts: n/a

 02-15-2006
UnaCoder wrote:
> You would be better off designing Sum to take an array as an argument,
> then you can just pass the array of arguments to Sum
>

I was looking for a generic solution. But I presume for your replay that
there is no direct solution (at least no direct solution known by you
).

UnaCoder
Guest
Posts: n/a

 02-15-2006
Well I thought there was and I researched java script to see if you can
invoke a string containing java script code. the solution that seemed
intuitive would be to do something like:

function Tunnel() {
function_name= arguments[0];
arguments.shift(); args = arguments.join();
eval function_name + "(" + args + ");";
}

I didn't put any error checking in there, or test that code, but as far
as I know that should work =)

Michael Winter
Guest
Posts: n/a

 02-15-2006
On 15/02/2006 17:42, Telmo Costa wrote:

[snip]

> // calling Sum directly
> Sum(1,2,3,4);
>
> // calling Sum through Tunnel
> Tunnel(Sum, 1,2,3,4);
> --------------------------------------
>
> How should the Tunnel function be defined, knowing that the number of
> parameters passed are unknown?

The previous suggestion - rewrite the Sum function to take an array
argument - is preferable as it's the simplest and most compatible
solution. However, there is an alternative: the Function.prototype.apply
method.

function tunnel(func) {
return func.apply(null,
Array.prototype.slice.call(arguments, 1));
}
function sum() {
var total = 0,
i = arguments.length;

while (i--) {
total += arguments[i];
}
}

alert(tunnel(sum, 1, 2, 3, 4)); /* 10 */

The problem with this approach is that not all browsers, especially IE
with a pre-5.5 JScript library, do not implement either the
Function.prototype.apply or call methods. Though both can be emulated,
it requires quite a significant (though relatively trivial) amount of
work to accommodate a general case.

Mike

--
Michael Winter
Prefix subject with [News] before replying by e-mail.

Telmo Costa
Guest
Posts: n/a

 02-16-2006
UnaCoder wrote:
> Well I thought there was and I researched java script to see if you can
> invoke a string containing java script code. the solution that seemed
> intuitive would be to do something like:
>
> function Tunnel() {
> function_name= arguments[0];
> arguments.shift(); args = arguments.join();
> eval function_name + "(" + args + ");";
> }
>
> I didn't put any error checking in there, or test that code, but as far
> as I know that should work =)
>

I always think of eval function as cheating Michael's solution is
more what i was looking for.

To be honest, the function i'm working with only takes 1 argument, so it
is like using the array solution. I was just wondering.

Nevertheless, thank you both.

RobG
Guest
Posts: n/a

 02-16-2006
UnaCoder wrote:
> Well I thought there was and I researched java script to see if you can
> invoke a string containing java script code. the solution that seemed
> intuitive would be to do something like:
>
> function Tunnel() {
> function_name= arguments[0];
> arguments.shift(); args = arguments.join();
> eval function_name + "(" + args + ");";
> }
>
> I didn't put any error checking in there, or test that code, but as far
> as I know that should work =)

Arguments is not an array, it's just a list with a few other properties
that make it look a bit like an array. Consequently, it doesn't have
split() or join() methods (and I don't think you can add them to its
prototype).

--
Rob

RobG
Guest
Posts: n/a

 02-16-2006
Telmo Costa wrote:
> Hi. I have the following code:
>
> --------------------------------------
> function Tunnel() {
> //arguments[0](???);
> }
>
> function Sum() {
> var sum = 0;
> for (i=0; i<arguments.length; i++) sum += arguments[i];
> };
>
> // calling Sum directly
> Sum(1,2,3,4);
>
> // calling Sum through Tunnel
> Tunnel(Sum, 1,2,3,4);
> --------------------------------------
>
> How should the Tunnel function be defined, knowing that the number of
> parameters passed are unknown?

function tunnel()
{
this.sum = function(x){
var s=x[0], i=x.length;
while (--i) s += x[i];
return s;
}
this.product = function(x){
var s=x[0], i=x.length;
while (--i) s *= x[i];
return s;
}

var funcName = arguments[0];
var ar = [];
for (var i=1, len=arguments.length; i<len; ++i) {
ar[ar.length] = arguments[i];
}
return this[funcName](ar);
}

alert(tunnel('sum', 1, 2, 3, 4)); /* 10 */
alert(tunnel('product', 1, 2, 3, 4)); /* 24 */

Note that the function (e.g. sum) name needs to be passed as a string.

--
Rob

Telmo Costa
Guest
Posts: n/a

 02-16-2006
>
>
> function tunnel()
> {
> this.sum = function(x){
> var s=x[0], i=x.length;
> while (--i) s += x[i];
> return s;
> }
> this.product = function(x){
> var s=x[0], i=x.length;
> while (--i) s *= x[i];
> return s;
> }
>
> var funcName = arguments[0];
> var ar = [];
> for (var i=1, len=arguments.length; i<len; ++i) {
> ar[ar.length] = arguments[i];
> }
> return this[funcName](ar);
> }
>
> alert(tunnel('sum', 1, 2, 3, 4)); /* 10 */
> alert(tunnel('product', 1, 2, 3, 4)); /* 24 */
>
>
> Note that the function (e.g. sum) name needs to be passed as a string.
>

That won't do.

I'm building a XUL application (but could be HTML) and, at some point, I
need to start a couple of XMLHTTPRequest objects (using your examples,
sum and product will generate a XMLHTTPRequest object). Everything
worked ok, but now I have a restriction from the remote server: one
request at a time. I could make synchronous XMLHTTPRequests, but it will
froze the application.

So, I thought of a "tunnel" function that could work as a
synchronization point, where i build a queue of request and dispatch one
at a time. This way, the impact in the rest of the code is minimal.

Thomas 'PointedEars' Lahn
Guest
Posts: n/a

 02-16-2006
RobG wrote:

> UnaCoder wrote:
>> Well I thought there was and I researched java script to see if you can
>> invoke a string containing java script code. the solution that seemed
>> intuitive would be to do something like:
>>
>> function Tunnel() {
>> function_name= arguments[0];
>> arguments.shift(); args = arguments.join();
>> eval function_name + "(" + args + ");";
>> }
>>
>> I didn't put any error checking in there, or test that code, but as far
>> as I know that should work =)

>
> Arguments is not an array, it's just a list

s/list/(Object) object/

> with a few other properties that make it look a bit like an array.
> Consequently, it doesn't have split() or join() methods (and I don't
> think you can add them to its prototype).

Since `arguments' inherits directly from Object (ECMASCript 3 Final,
10.1., it is possible to add them, e.g.:

Object.prototype.join = function(delim)
{
var a = [];

for (var i = 0, len = this.length; i < len; i++)
{
a.push(this[i]);
}

return a.join(delim);
}

However, it is also an Object object without the ReadOnly attribute, so you
can add the methods to it instead, e.g.

arguments.join = function(delim)
{
/* see above */
}

The second approach would work for only one execution context, though, as
the `arguments' object is (re-)created and initialized every time control
enters an execution context for function code.

I have tested both approaches positive in Mozilla/5.0 (X11; U; Linux i686;
en-US; rv:1. Gecko/20060110 Debian/1.5.dfsg-4 Firefox/1.5.

PointedEars