.. include:: ../global.rst .. _`multiple values`: Multiple Values ^^^^^^^^^^^^^^^ Everything returns a value and that value could be a compound type like a list. In many circumstances, the implicit assignment of multiple values to multiple variables (either named variables or function parameters) is a desirable effect. This is a common trope in many programming languages. :lname:`Idio` does not specifically handle the return or receipt of multiple values but there are a number of helper functions. .. _`values`: .. idio:function:: values [args] return *multiple values* :param args: arguments to be tagged as *multiple values* :type args: list or any :return: list of *multiple values* :rtype: list .. _`call-with-values`: .. idio:function:: call-with-values producer consumer invoke `consumer` with the values returned from invoking `producer` :param producer: function to return *multiple values* :type producer: thunk :param consumer: function to accept as many values as `producer` generates :type consumer: function :return: return value of `consumer` :rtype: any ``call-with-values`` is the fundamental operator in *multiple values*, all other functions are derivations of it. :Example: .. code-block:: idio (call-with-values (function #n (values 1 2 3 4)) (function (a b c d) { printf "a + d = %s\n" (a + d) ; a + d = 5 })) Here, the `consumer` function is called with arguments ``1 2 3 4``, the *multiple values* returned by the `producer` function. .. _`let-values`: .. idio:template:: let-values mv-bindings body invoke `body` in the context of the *multiple values* bindings :param mv-bindings: *multiple values* bindings, see below :type mv-bindings: list :param body: body form :type body: expressions :return: return value of `body` :rtype: any `mv-bindings` takes the form :samp:`(({formals} {init}) ...)` where :samp:`{init}` is an expression returning *multiple values* and :samp:`{formals}` is a list of variable names. :Example: .. code-block:: idio (let-values (((a b) (values 1 2)) ((c d) (values 3 4))) { printf "a + d = %s\n" (a + d) ; a + d = 5 }) Here, the `body` function is called with the variable names ``a``, ``b``, ``c`` and ``d`` bound to values ``1``, ``2``, ``3`` and ``4`` respectively. :samp:`{formals}` can be an improper list: .. code-block:: idio (let-values (((a b & c) (values 1 2 3 4))) { printf "c is %s\n" c ; c is (3 4) printf "a + (pht c) = %s\n" (a + (pht c)) ; a + (pht c) = 5 }) .. _`let*-values`: .. idio:template:: let*-values mv-bindings body invoke `body` in the context of the *multiple values* bindings :param mv-bindings: *multiple values* bindings, see below :type mv-bindings: list :param body: body form :type body: expressions :return: return value of `body` :rtype: any `mv-bindings` takes the form :samp:`(({formals} {init}) ...)` where :samp:`{init}` is an expression returning *multiple values* and :samp:`{formals}` is a list of variable names. ``let*-values`` is similar to :ref:`let-values ` except the inner bindings are evaluated in the context of the outer bindings. :Example: .. code-block:: idio (let*-values (((a b) (values 1 2)) ((c d) (values (a + b) (a - b)))) { printf "c=%s d=%s\n" c d ; c=3 d=-1 }) .. _`define-values`: .. idio:template:: define-values formals expr define multiple new variables from the *multiple values* returned from `expr` :param formals: variable names :type formals: list :param expr: expression returning *multiple values* :type expr: expression :rtype: any :Example: .. code-block:: idio define-values (a b & c) (values 1 2 3 4) printf "a + (pht c) = %s\n" (a + (pht c)) ; a + (pht c) = 5 .. include:: ../commit.rst