function and arguments as aguments

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Telmo Costa

    function and arguments as aguments

    Hi. I have the following code:

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

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

    // 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

    #2
    Re: function and arguments as aguments

    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

    Comment

    • Telmo Costa

      #3
      Re: function and arguments as aguments

      UnaCoder wrote:[color=blue]
      > 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
      >[/color]

      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
      ;) ).

      Comment

      • UnaCoder

        #4
        Re: function and arguments as aguments

        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 =)

        Comment

        • Michael Winter

          #5
          Re: function and arguments as aguments

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

          [snip]
          [color=blue]
          > // 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?[/color]

          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.protot ype.apply
          method.

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

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

          alert(tunnel(su m, 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.protot ype.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.

          Comment

          • Telmo Costa

            #6
            Re: function and arguments as aguments

            UnaCoder wrote:[color=blue]
            > 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 =)
            >[/color]


            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.



            Comment

            • RobG

              #7
              Re: function and arguments as aguments

              UnaCoder wrote:[color=blue]
              > 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 =)[/color]

              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

              Comment

              • RobG

                #8
                Re: function and arguments as aguments

                Telmo Costa wrote:[color=blue]
                > Hi. I have the following code:
                >
                > --------------------------------------
                > function Tunnel() {
                > //arguments[0](???);
                > }
                >
                > function Sum() {
                > var sum = 0;
                > for (i=0; i<arguments.len gth; i++) sum += arguments[i];
                > alert(sum);
                > };
                >
                > // 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?[/color]

                How about:

                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.l ength; i<len; ++i) {
                ar[ar.length] = arguments[i];
                }
                return this[funcName](ar);
                }

                alert(tunnel('s um', 1, 2, 3, 4)); /* 10 */
                alert(tunnel('p roduct', 1, 2, 3, 4)); /* 24 */


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


                --
                Rob

                Comment

                • Telmo Costa

                  #9
                  Re: function and arguments as aguments

                  >[color=blue]
                  > How about:
                  >
                  > 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.l ength; i<len; ++i) {
                  > ar[ar.length] = arguments[i];
                  > }
                  > return this[funcName](ar);
                  > }
                  >
                  > alert(tunnel('s um', 1, 2, 3, 4)); /* 10 */
                  > alert(tunnel('p roduct', 1, 2, 3, 4)); /* 24 */
                  >
                  >
                  > Note that the function (e.g. sum) name needs to be passed as a string.
                  >[/color]


                  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.



                  Comment

                  • Thomas 'PointedEars' Lahn

                    #10
                    Re: function and arguments as aguments

                    RobG wrote:
                    [color=blue]
                    > UnaCoder wrote:[color=green]
                    >> 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 =)[/color]
                    >
                    > Arguments is not an array, it's just a list[/color]

                    s/list/(Object) object/
                    [color=blue]
                    > 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).[/color]

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

                    Object.prototyp e.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.8) Gecko/20060110 Debian/1.5.dfsg-4 Firefox/1.5.


                    PointedEars

                    Comment

                    • ron.h.hall@gmail.com

                      #11
                      Re: function and arguments as aguments

                      Thomas 'PointedEars' Lahn wrote:
                      [...][color=blue]
                      > Since `arguments' inherits directly from Object (ECMASCript 3 Final,
                      > 10.1.8), it is possible to add them, e.g.:
                      >
                      > Object.prototyp e.join = function(delim)
                      > {
                      > var a = [];
                      >
                      > for (var i = 0, len = this.length; i < len; i++)
                      > {
                      > a.push(this[i]);
                      > }
                      >
                      > return a.join(delim);
                      > }
                      >[/color]
                      [...]

                      But since Array.prototype .join is generic (under ECMASCript 3), it
                      seems you should be able to use the built-in here, given that
                      'arguments': has a length and "numeric" properties:

                      Object.prototyp e.join = Array.prototype .join;

                      ../rh

                      Comment

                      • Thomas 'PointedEars' Lahn

                        #12
                        Re: function and arguments as aguments

                        ron.h.hall@gmai l.com wrote:
                        [color=blue]
                        > Thomas 'PointedEars' Lahn wrote:[color=green]
                        >> Since `arguments' inherits directly from Object (ECMASCript 3 Final,
                        >> 10.1.8), it is possible to add them, e.g.:
                        >>
                        >> Object.prototyp e.join = function(delim)
                        >> {
                        >> var a = [];
                        >>
                        >> for (var i = 0, len = this.length; i < len; i++)
                        >> {
                        >> a.push(this[i]);
                        >> }
                        >>
                        >> return a.join(delim);
                        >> }
                        >>[/color]
                        >
                        > But since Array.prototype .join is generic (under ECMASCript 3), it
                        > seems you should be able to use the built-in here, given that
                        > 'arguments': has a length and "numeric" properties:
                        >
                        > Object.prototyp e.join = Array.prototype .join;[/color]

                        Indeed. Thank you for pointing this out. When reading only

                        ,-[ECMAScript Edition 3 Final]
                        |
                        | 15.4.4.5 Array.prototype .join (separator)
                        |
                        | The elements of the array are converted to strings, [...]
                        ^^^^^^^^^^^^^^^ ^^^^^^^^^^

                        it is easy to overlook the following at the top of the next page
                        (PDF version):

                        | NOTE The join function is intentionally generic; it does not require that
                        | its `this' value be an Array object. Therefore, it can be transferred to
                        | other kinds of objects for use as a method. Whether the join function
                        | can be applied successfully to a host object is implementation-dependent.

                        (It should be noted *g* that there is such a NOTE for other methods of
                        Array.prototype too.)

                        The test case

                        Object.prototyp e.join = Array.prototype .join;
                        (function() { alert(arguments .join("x")); })(1, 2, 3); // "1x2x3"
                        alert({1: 2, 2: 3, length: 3}.join("x")); // "x2x3"

                        works in the following user agents:

                        - Mozilla Firefox 1.5.0.1
                        Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.1) Gecko/20060209
                        Debian/1.5.dfsg+1.5.0. 1-2 Firefox/1.5.0.1

                        - Mozilla (Suite) 1.7.12
                        [Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20060205
                        Debian/1.7.12-1.1]

                        - Netscape Navigator 4.8
                        [Mozilla/4.8 [en] (X11; U; Linux 2.6.15.1-20060130.184242 +0100 i686)]

                        - Opera 8.51
                        [Opera/8.51 (X11; Linux i686; U; en)]

                        - Konqueror 3.5.1
                        [Mozilla/5.0 (compatible; Konqueror/3.5;
                        Linux 2.6.15.1-20060130.184242 +0100; X11; i686; de, en_US)
                        KHTML/3.5.1 (like Gecko) (Debian package 4:3.5.1-2)]

                        IE, Windows, and Mac testers, it's your turn :)


                        PointedEars

                        Comment

                        • RobG

                          #13
                          Re: function and arguments as aguments

                          Thomas 'PointedEars' Lahn wrote:[color=blue]
                          > RobG wrote:
                          >
                          >[color=green]
                          >>UnaCoder wrote:
                          >>[color=darkred]
                          >>>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 =)[/color]
                          >>
                          >>Arguments is not an array, it's just a list[/color]
                          >
                          > s/list/(Object) object/[/color]

                          Yes, a list Object.

                          [color=blue][color=green]
                          >>with a few other properties that make it look a bit like an array.
                          >>Consequentl y, it doesn't have split() or join() methods (and I don't
                          >>think you can add them to its prototype).[/color]
                          >
                          > Since `arguments' inherits directly from Object (ECMASCript 3 Final,
                          > 10.1.8), it is possible to add them, e.g.:[/color]

                          The way I read the spec was that arguments shares the Object prototype,
                          which is null. I concluded that you couldn't add to it - clearly an
                          incorrect conclusion. :-x

                          I'll run the test in your other post later on a few Mac OS browsers.


                          --
                          Rob

                          Comment

                          • VK

                            #14
                            Re: function and arguments as aguments


                            Thomas 'PointedEars' Lahn wrote:[color=blue]
                            > ron.h.hall@gmai l.com wrote:
                            >[color=green]
                            > > Thomas 'PointedEars' Lahn wrote:[color=darkred]
                            > >> Since `arguments' inherits directly from Object (ECMASCript 3 Final,
                            > >> 10.1.8), it is possible to add them, e.g.:
                            > >>
                            > >> Object.prototyp e.join = function(delim)
                            > >> {
                            > >> var a = [];
                            > >>
                            > >> for (var i = 0, len = this.length; i < len; i++)
                            > >> {
                            > >> a.push(this[i]);
                            > >> }
                            > >>
                            > >> return a.join(delim);
                            > >> }
                            > >>[/color]
                            > >
                            > > But since Array.prototype .join is generic (under ECMASCript 3), it
                            > > seems you should be able to use the built-in here, given that
                            > > 'arguments': has a length and "numeric" properties:
                            > >
                            > > Object.prototyp e.join = Array.prototype .join;[/color]
                            >
                            > Indeed. Thank you for pointing this out. When reading only
                            >
                            > ,-[ECMAScript Edition 3 Final]
                            > |
                            > | 15.4.4.5 Array.prototype .join (separator)
                            > |
                            > | The elements of the array are converted to strings, [...]
                            > ^^^^^^^^^^^^^^^ ^^^^^^^^^^
                            >
                            > it is easy to overlook the following at the top of the next page
                            > (PDF version):
                            >
                            > | NOTE The join function is intentionally generic; it does not require that
                            > | its `this' value be an Array object. Therefore, it can be transferred to
                            > | other kinds of objects for use as a method. Whether the join function
                            > | can be applied successfully to a host object is implementation-dependent.
                            >
                            > (It should be noted *g* that there is such a NOTE for other methods of
                            > Array.prototype too.)
                            >
                            > The test case
                            >
                            > Object.prototyp e.join = Array.prototype .join;
                            > (function() { alert(arguments .join("x")); })(1, 2, 3); // "1x2x3"
                            > alert({1: 2, 2: 3, length: 3}.join("x")); // "x2x3"
                            >
                            > works in the following user agents:
                            >
                            > - Mozilla Firefox 1.5.0.1
                            > Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.1) Gecko/20060209
                            > Debian/1.5.dfsg+1.5.0. 1-2 Firefox/1.5.0.1
                            >
                            > - Mozilla (Suite) 1.7.12
                            > [Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20060205
                            > Debian/1.7.12-1.1]
                            >
                            > - Netscape Navigator 4.8
                            > [Mozilla/4.8 [en] (X11; U; Linux 2.6.15.1-20060130.184242 +0100 i686)]
                            >
                            > - Opera 8.51
                            > [Opera/8.51 (X11; Linux i686; U; en)]
                            >
                            > - Konqueror 3.5.1
                            > [Mozilla/5.0 (compatible; Konqueror/3.5;
                            > Linux 2.6.15.1-20060130.184242 +0100; X11; i686; de, en_US)
                            > KHTML/3.5.1 (like Gecko) (Debian package 4:3.5.1-2)]
                            >
                            > IE, Windows, and Mac testers, it's your turn :)[/color]

                            It works in JScript 5.6 (IE 6.0)

                            For the purity of picture :-) one should say that in JScript
                            "arguments" is an objects with non-enumerable properties "length",
                            "callee", "caller" and "00"..."0X"
                            Besides that "00"..."0N of arguments" properties are *protected* so you
                            can access them only by numeric index, so say arguments[1] is really an
                            access to the property arguments['01'] which is not accessible
                            otherwise. Overall it looks like HTMLCollection where scring property
                            access is locked. That is the reason why it is stated in docs that
                            "arguments is not an array despite it looks like one" (because it's
                            indeed not).

                            Comment

                            • Duncan Booth

                              #15
                              Re: function and arguments as aguments

                              Thomas 'PointedEars' Lahn wrote:
                              [color=blue]
                              > The test case
                              >
                              > Object.prototyp e.join = Array.prototype .join;
                              > (function() { alert(arguments .join("x")); })(1, 2, 3); // "1x2x3"
                              > alert({1: 2, 2: 3, length: 3}.join("x")); // "x2x3"
                              >
                              > works in the following user agents:
                              >
                              > - Mozilla Firefox 1.5.0.1
                              > Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.1) Gecko/20060209
                              > Debian/1.5.dfsg+1.5.0. 1-2 Firefox/1.5.0.1
                              >
                              > - Mozilla (Suite) 1.7.12
                              > [Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20060205
                              > Debian/1.7.12-1.1]
                              >
                              > - Netscape Navigator 4.8
                              > [Mozilla/4.8 [en] (X11; U; Linux 2.6.15.1-20060130.184242 +0100 i686)]
                              >
                              > - Opera 8.51
                              > [Opera/8.51 (X11; Linux i686; U; en)]
                              >
                              > - Konqueror 3.5.1
                              > [Mozilla/5.0 (compatible; Konqueror/3.5;
                              > Linux 2.6.15.1-20060130.184242 +0100; X11; i686; de, en_US)
                              > KHTML/3.5.1 (like Gecko) (Debian package 4:3.5.1-2)]
                              >
                              > IE, Windows, and Mac testers, it's your turn :)[/color]

                              It appears to also work on IE 5.5 and IE 6.

                              Comment

                              Working...