.. include:: ../global.rst Idio Functions -------------- .. _`not/function`: .. idio:function:: not/function x invert the boolean sense of `x` :param x: value to invert :type x: any :result: boolean inverse of `x` :rtype: boolean This is the function equivalent of the :ref:`not special form `. .. _`when`: .. idio:template:: when test body if `test` is `true` run `body` :param test: test condition :type test: expression :param body: expressions :type test: expression :return: value from `body` or ``#`` .. _`unless`: .. idio:template:: unless test body if `test` is `false` run `body` :param test: test condition :type test: expression :param body: expressions :type test: expression :return: value from `body` or ``#`` .. _`case`: .. idio:template:: case key clauses Each clause in `clauses` takes the form :samp:`(({v} ...) {expr} ...)` except the last clause which can take the form :samp:`(else {expr} ...)`. `key` is evaluated and then compared with :ref:`memv ` against the list in the head of each clause in `clauses`. If the comparison is `true` then the result of ``case`` is the result of evaluating the expressions in the body of the clause. No other clauses are considered. If no comparison is `true` and there is an ``else`` clause then it is run otherwise the result is ``#``. .. _`do`: .. idio:template:: do var-clauses test-result body Despite the visual differences, ``do`` performs much the same task as :lname:`C`'s :samp:`for ({init}; {test}; {step}) {body}` statement. `var-clauses` is a list of `var-clause` which is a tuple, :samp:`({var} {init} {step})`. Each :samp:`{var}` is initialised to :samp:`{init}` and adjusted by :samp:`{step}` each time round the loop. `test-result` offers a little more flexibility than :lname:`C` in that `test-result` is the tuple :samp:`({test} {expr})` where :samp:`{test}` is evaluated each time round the loop, the same as :lname:`C`, but ``do`` allows you to run some arbitrary :samp:`{expr}` for the result to be returned from ``do``. `body` is the usual body form. :Example: Increment :samp:`{i}` starting from 1. If :samp:`{i}` is 10 then return :samp:`{i} + 13`. The body, ``i``, is a placeholder in this instance. .. code-block:: idio do ((i 1 (1 + i))) ((eq i 10) i + 13) i ; 23 .. _`C/for`: .. idio:template:: C/for var-clauses test body ``C/for`` is a variation on :ref:`do ` but adds :ref:`continue ` and :ref:`break ` continuations to alter the flow of control. `var-clauses` is a list of `var-clause` which is a tuple, :samp:`({var} {init} {step})`. Each :samp:`{var}` is initialised to :samp:`{init}` and adjusted by :samp:`{step}` each time round the loop. .. note:: Each :samp:`{var}` is local to the `body` loop. `test` is evaluated each time round the loop, the same as :lname:`C`. If the test fails ``(break)`` is implicitly called. `body` is the usual body form. ``C/for`` returns either ``#``, from the implicit ``(break)``, or the value supplied to any explicit call to ``break``. :Example: Loop over :samp:`{i}`, starting from 1 and less than 10. If :samp:`{i}` is 3 then return ``99`` otherwise return :samp:`{i} + 13`. .. code-block:: idio C/for ((i 1 (1 + i))) (i lt 10) { if (i eq 3) { break 99 } i + 13 } .. seealso:: :ref:`while ` the degenerative form of ``C/for`` with no `var-clauses`. .. _`break`: .. idio:template:: break [value] ``break`` returns `value` from the enclosing :ref:`C/for ` or :ref:`while ` loop or ``#`` if no `value` is supplied. .. warning:: ``break`` ignores any protection blocks set up by :ref:`unwind-protect ` or :ref:`dynamic-wind `. .. _`continue`: .. idio:template:: continue [value] ``continue`` stops processing the current :ref:`C/for ` or :ref:`while ` `body` and starts the next iteration of the loop. `value` is ignored and set to ``#`` if not supplied. .. warning:: ``continue`` ignores any protection blocks set up by :ref:`unwind-protect ` or :ref:`dynamic-wind `. .. _`while`: .. idio:template:: while test body ``while`` is the degenerative form of :ref:`C/for ` with no `var-clauses`. .. _`map`: .. idio:function:: map f lists apply `f` to the collected n\ :sup:`th` elements of each list in `lists`. `f` should accept as many arguments as there are lists and each list in `lists` should be the same length. :param f: function to be applied :type f: function :param lists: lists, arrays or strings :type lists: list :return: list of the results from applying `f` :rtype: list :Example: Multiply a list of numbers by 10: .. code-block:: idio map (function (n) n * 10) '(1 2 3) ; '(10 20 30) Add two lists of numbers: .. code-block:: idio map (function (n1 n2) n1 + n2) '(1 2 3) '(4 5 6) ; '(5 7 9) Combine the elements of arrays (:ref:`list `, of course, takes any number of arguments): .. code-block:: idio map list #[1 2 3] #[4 5 6] #[7 8 9] ; '((1 4 7) (2 5 8) (3 6 9)) .. seealso:: :ref:`for-each ` which does the same but doesn't return a list .. _`map*`: .. idio:function:: map* f lists apply `f` to the collected n\ :sup:`th` elements of each list in `lists`. `f` should accept as many arguments as there are lists and each list in `lists` should be the same length. :param f: function to be applied :type f: function :param lists: lists, arrays or strings :type lists: list :return: list of the results from applying `f` :rtype: list ``map*`` is a variant of :ref:`map ` that handles improper lists. .. _`for-each`: .. idio:function:: for-each f lists apply `f` to the collected n\ :sup:`th` elements of each list in `lists`. `f` should accept as many arguments as there are lists and each list in `lists` should be the same length. :param f: function to be applied :type f: function :param lists: lists, arrays or strings :type lists: list :return: ``#`` .. seealso:: :ref:`map ` which does the same but returns a list of the results of `f` .. _`for-each*`: .. idio:function:: for-each* f lists apply `f` to the collected n\ :sup:`th` elements of each list in `lists`. `f` should accept as many arguments as there are lists and each list in `lists` should be the same length. :param f: function to be applied :type f: function :param lists: lists, arrays or strings :type lists: list :return: ``#`` ``for-each*`` is a variant of :ref:`for-each ` that handles improper lists. .. _`for`: .. idio:template:: for vars in values body `for` takes two forms: :samp:`for {v} in value {body}` :samp:`for ({v1} {v2} ...) in values {body}` where `body` is a body form that uses the variable(s) :samp:`{v}` or :samp:`{v1}`, :samp:`{v2}`, etc., In the first, singular, form, :samp:`{value}` can be a list, array or string. A string will be split into Unicode code points. In the second, multiple, form, :samp:`{values}` must be a list of lists, arrays or strings and should be of the same type. Strings will be split into Unicode code points. :Example: Printing the elements of a string, one per line: .. code-block:: idio-console Idio> for x in "hello" { printf "%s\n" x } h e l l o # Printing the paired elements of two lists, a pair per line: .. code-block:: idio-console Idio> for (x y) in '((1 2 3) (#\a #\b #\c)) { printf "%s - %s\n" x y } 1 - a 2 - b 3 - c # .. _`fold-left`: .. idio:function:: fold-left f init lists call `func` for each element in list `l` with arguments: `element` and `val` `val` is updated to the value returned by `func`. The final value of `val` is returned. :param func: func to be called with each val, element tuple :type func: 2-ary function :param val: initial value for `val` :type val: value :param l: list :type l: list :return: final value of `val` apply `f` to the collected n\ :sup:`th` elements of each list in `lists` together with a cumulative result value which is initialised to `init`. `f` should accept one more argument than there are lists and each list in `lists` should be the same length. The first time `f` is called the first argument is `init`. The subsequent times `f` is called the first argument is the return value from the previous call to `f`. :param f: function to be applied :type f: function :param init: initial value of the cumulative result :type init: any :param lists: list of lists :type lists: list :return: cumulative result :rtype: any .. seealso:: :ref:`fold-right ` which does the same but processes `lists` right to left .. warning:: There is a :lname:`Scheme` function, ``foldl`` which accepts the cumulative result as the last argument. .. _`fold-right`: .. idio:function:: fold-right f init lists apply `f` to the collected n\ :sup:`th` elements of each list in the reversed `lists` together with a cumulative result value which is initialised to `init`. `f` should accept one more argument than there are lists and each list in `lists` should be the same length. The first time `f` is called the first argument is `init`. The subsequent times `f` is called the first argument is the return value from the previous call to `f`. :param f: function to be applied :type f: function :param init: initial value of the cumulative result :type init: any :param lists: list of lists :type lists: list :return: cumulative result :rtype: any .. seealso:: :ref:`fold-left ` which does the same but processes `lists` left to right .. warning:: There is a :lname:`Scheme` function, ``foldr`` which accepts the cumulative result as the last argument. .. _`unwind-protect`: .. idio:template:: unwind-protect body finally evaluate `body` and then evaluate `finally` irrespective of how `body` completed :param body: expressions :type body: expressions :param finally: expressions :type finally: expressions :return: the result of evaluating `body` :rtype: any .. seealso:: :ref:`dynamic-wind ` .. _`dynamic-wind`: .. idio:function:: dynamic-wind pre-thunk value-thunk post-thunk evaluate `pre-thunk` and then evaluate `value-thunk` then evaluate `post-thunk` irrespective of how `value-thunk` completed :param pre-thunk: thunk :type pre-thunk: function :param value-thunk: thunk :type value-thunk: function :param post-thunk: thunk :type post-thunk: function :return: the result of evaluating `value-thunk` :rtype: any This is derived from ports of :ref-author:`Oleg Kiselyov`'s `delim-control-n.scm `_ and `dynamic-wind implementation `_. This implementation might not be complete or robust. .. _`apply`: .. idio:function:: apply fn [args] call `fn` with `args` :param fn: function to call :type fn: function :param args: arguments to `fn` :type args: parameters plus list The last element of `args` is special. If it is a list then the elements of that list are appended to the arguments to `fn` .. code-block:: idio apply \+ 1 2 3 ; 6 apply \+ 1 2 3 #n ; 6 apply \+ 1 2 3 '(4 5) ; 15 .. _`exit`: .. idio:function:: exit status attempt to exit with status `status` :param status: exit status :type status: fixnum or C/int Does not return [#]_. This form will attempt to run through the full system shutdown. .. seealso:: :ref:`libc/exit ` for a more abrupt exit .. [#] YMMV .. _`identity`: .. idio:function:: identity e return `e` :param e: expression to return :type e: any :return: `e` .. _`value-index`: .. idio:function:: value-index o i if `i` is a function then invoke (`i` `o`) otherwise index the object `o` by `i` :param o: object to index :type o: any :param i: index :type i: any :return: the indexed value :raises ^rt-parameter-value-error: Indexable object types are those with a ``value-index`` vtable method associated with them. Standard indexable types with the implementation function call are: .. csv-table:: :widths: auto :align: left list, :samp:`(nth {o} {i})`, :ref:`nth ` indexes start at 1 string, :samp:`(string-ref {o} {i})`, :ref:`string-ref ` array, :samp:`(array-ref {o} {i})`, :ref:`array-ref ` indexes can be negative hash, :samp:`(hash-ref {o} {i})`, :ref:`hash-ref ` struct instance, :samp:`(struct-instance-ref {o} {i})`, :ref:`struct-instance-ref ` tagged C/pointer, :samp:`({accessor} {o} {i})` Note that, in particular for struct instance, the symbol used for a symbolic field name may have been evaluated to a value. Quote if necessary: :samp:`{o}.'{i}` ``value-index`` is not as efficient as calling the accessor function directly. :Example: An example where `i` is a function is using :ref:`fields ` to split a string (on :ref:`IFS `): .. code-block:: idio-console Idio> "here and there" . fields #[ "here and there" "here" "and" "there" ] An array example which can use a negative index: .. code-block:: idio-console Idio> a := #[ 'a 'b 'c ] #[ 'a 'b 'c ] Idio> a.2 'c Idio> a.-1 'c .. _`add-value-index`: .. idio:function:: add-value-index o f Associate a indexer function `f` with `o`. `f` will be invoked with the value to be indexed and the index. This is currently only used for: - struct instances where a struct type was associated with a indexer. When we come to index a struct instance we check to see if a indexer exists for its type. .. _`set-value-index!`: .. idio:function:: set-value-index! o i v set value of the object `o` indexed by `i` to `v` :param o: object to index :type o: any :param i: index :type i: any :param v: value :type v: any :return: the indexed value :raises ^rt-parameter-value-error: Indexable object types are those with a defined setter or with a ``set-value-index!`` vtable method associated with them. Standard vtable methods and setters are: .. csv-table:: :widths: auto :align: left string, :samp:`(string-set! {o} {i} {v})` array, :samp:`(array-set! {o} {i} {v})` hash, :samp:`(hash-set! {o} {i} {v})` struct instance, :samp:`(struct-instance-set! {o} {i} {v})` tagged C/pointer, :samp:`({setter} {o} {i})` Note that, in particular for struct instance, the symbol used for a symbolic field name may have been evaluated to a value. Quote if necessary: :samp:`{o}.'{i} = {v}` .. note:: Not all tagged C/pointer types have an associated `setter`. :ref:`struct-stat `, for example, does not have an associated setter. ``set-value-index!`` is not as efficient as calling the setting function directly. .. _`copy-value`: .. idio:function:: copy-value v [depth] copy `v` to `depth` :param v: value to copy :type v: any :param depth: ``'shallow`` or ``'deep`` (default) :type depth: symbol, optional :return: copy of `v` .. _`find-lib`: .. idio:function:: find-lib libname search `IDIOLIB` for `libname` with a set of possible file name extensions :param libname: library name to search for :type libname: string :return: pathname to `libname` :rtype: pathname or ``#f`` .. _`type->string`: .. idio:function:: type->string o return the type of `o` as a string :param o: object :return: a string representation of the type of `o` .. _`typename`: .. idio:function:: typename o return the type name of `o` :param o: object :return: the type of `o` .. _`members`: .. idio:function:: members o return the members of `o` as a list :param o: object :return: a list of the members of `o` `o` should be an object with members such as a :ref:`struct-instance ` or :ref:`C/pointer `. .. _`gc/collect`: .. idio:function:: gc/collect invoke the garbage collector :return: ``#`` .. _`idio-debug`: .. idio:function:: idio-debug fmt o print the string value of `o` according to `fmt` to *stderr* There must be a single %s conversion specification .. code-block:: idio idio-debug "foo is %-20s\n" foo :param fmt: :manpage:`printf(3)` format string :type fmt: string :param o: value to dump :type o: any :return: ``#`` .. _`idio-dump`: .. idio:function:: idio-dump o print the internal details of `o` to *stderr* :param o: value to dump :type o: any :return: ``#`` .. _`ASCII-Decimal_Number?`: .. idio:function:: ASCII-Decimal_Number? cp Is `cp` an ASCII digit? :param cp: code point to test :type cp: unicode :return: boolean This closure, defined in :file:`lib/bootstrap/common.idio` should be overriden by the 'more correct' :ref:`unicode/ASCII-Decimal_Number? ` primitive in :file:`src/usi-wrap.c` but exists for handling printing if bootstrap fails. .. _`help`: .. idio:template:: help sym provide some helpful documentation for `sym` :param sym: name to describe :type sym: symbol :return: ``#`` Some provenance is given for functions; field and ancestry details for structs; imports and exports for modules. .. note:: ``help`` is a template so you do not need to quote `sym`. The documentation is currently the raw reStructuredText. Some re-imagining is required. .. _`idio-version`: .. idio:function:: idio-version [detail] Report details of the Idio version. :param details: provide more details on IDIOLIB, defaults to ``#f`` :type details: boolean, optional :keyword :raw: do not substitute $HOME, defaults to ``#f`` :type :raw: boolean, optional .. include:: ../commit.rst