<?xml version="1.0" encoding="UTF-8"?>
<!--
 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 * Copyright (C) ????-2008 - INRIA
 * Copyright (C) 2012 - 2016 - Scilab Enterprises
 * Copyright (C) 2021 - Samuel GOUGEON
 *
 * This file is hereby licensed under the terms of the GNU GPL v2.0,
 * pursuant to article 5.3.4 of the CeCILL v.2.1.
 * This file was originally licensed under the terms of the CeCILL v2.1,
 * and continues to be available under such terms.
 * For more information, see the COPYING file which you should have received
 * along with this program.
 *
 -->
<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
          xmlns:svg="http://www.w3.org/2000/svg" xmlns:db="http://docbook.org/ns/docbook"
          xmlns:scilab="http://www.scilab.org" xml:lang="ru" xml:id="library">
    <refnamediv>
        <refname>library</refname>
        <refpurpose>тип данных библиотеки</refpurpose>
    </refnamediv>
    <refsection>
        <title>Описание</title>
        <para>
            <emphasis role="bold">
                Из чего сделана библиотека функций, написанных на языке Scilab?
            </emphasis>
        </para>
        <para>
            Такая библиотека сделана из директории, содержащей
            <itemizedlist>
                <listitem>
                    редактируемый XML-файл, который всегда называется <literal>lib</literal>.
                    Этот файл содержит
                    <orderedlist>
                        <listitem>
                            имя библиотеки;
                        </listitem>
                        <listitem>
                            список имён публичных функций, принадлежащих библиотеке.
                        </listitem>
                    </orderedlist>
                    Этот файл сгенерирован с помощью <literal>genlib(..)</literal>.
                    Его нельзя сделать вручную.
                    <para/>
                </listitem>
                <listitem>
                    набор двоичных файлов с расширением <literal>.bin</literal>,
                    чьи основные имена являются именами функций возможно зарегистрированных
                    в файле <literal>lib</literal>,
                    <para/>
                </listitem>
                <listitem>
                    и возможно -- но это необязательно для загрузки и использования
                    библиотеки --, <literal>.sci</literal>-файлы исходников, написанные
                    на языке Scilab, чья компиляция с помощью <code>genlib(..)</code>
                    генерирует файлы <literal>lib</literal> и <literal>.bin</literal>.
                    <para/>
                    <warning>
                        Если файл-исходник <literal>foo.sci</literal> функции
                        <literal>foo()</literal> не предоставлен в директории библиотеки,
                        то <literal>edit foo</literal> не может править его Scilab-код
                        и откроет пустой файл с нуля.
                    </warning>
                    <para/>
                </listitem>
            </itemizedlist>
        </para>
        <para>
            <emphasis role="bold">
                Загрузка / декларирование библиотеки в сессии
            </emphasis>:
        </para>
        <para>
            <literal>load("/path/to/lib")</literal> загружает предназначенную библиотеку
            в сессию Scilab: создаётся переменная, чьё имя является именем библиотеки
            -- скажем <literal>libname</literal>. Относящийся к ней тип
            <literal>type(libname)</literal> равен 14. Её <literal>typeof(libname)</literal>
            соответствует <literal>"library"</literal>. Этот дескриптор библиотеки содержит
            <itemizedlist>
                <listitem>
                    путь к корневой директории библиотеки;
                </listitem>
                <listitem>
                    список имён публичных функций, принадлежащих библиотеке.
                </listitem>
            </itemizedlist>
        </para>
        <para>
            Обе части могут быть получены либо с помощью функции <literal>libraryinfo()</literal>,
            либо с помощью функции <literal>string()</literal>.
        </para>
        <para>
            Пример: <literal>interpolationlib</literal> является родной библиотекой Scilab:
            <screen>
--> interpolationlib
 interpolationlib  =

Functions files location : SCI\modules\interpolation\macros\.
interp1  mesh2d  interpln  smooth

--> type(interpolationlib)
 ans  =
   14.

--> [typeof(interpolationlib), typeof(interpolationlib, "overload")]
 ans  =
  "library"  "f"

--> string(interpolationlib)
 ans  =
  "SCI\modules\interpolation\macros\"
  "interp1"
  "mesh2d"
  "interpln"
  "smooth"

--> [fnames, libpath] = libraryinfo("interpolationlib")
 fnames  =
  "interp1"
  "mesh2d"
  "interpln"
  "smooth"

 libpath  =
  "SCI\modules\interpolation\macros\"
</screen>
        </para>
        <para>
            <emphasis role="bold">Автозагрузка при первом вызове функции</emphasis>:
        </para>
        <para>
            Если имя функции -- скажем, <literal>foo()</literal> -- принадлежащей
            библиотеке, вызвана в сессии, то Scilab делает следующее:
            <orderedlist>
                <listitem>
                    Является ли <literal>foo</literal> именем встроенной функции?
                    Если так, то эта встроенная функция вызывается. В противном
                    случае,
                    <para/>
                </listitem>
                <listitem>
                    Является ли <literal>foo</literal> именем локальной переменной,
                    возможно требуемой <literal>foo()</literal> (предполагая, что
                    она уже была вызвана)? Если так, то используется эта переменная.
                    В противном случае,
                    <para/>
                </listitem>
                <listitem>
                    Сканируются все загруженные библиотеки -- в обратном алфавитному порядку имён
                    библиотек -- для поиска <literal>foo()</literal>. Первая найденная
                    "загружается" из её <literal>.bin</literal>-файла и, наконец, вызывается.
                    Следующие вызовы <literal>foo()</literal> будут переходить к шагу №2,
                    который будет успешным, пока дескриптор <literal>foo</literal> не
                    будет удалён по ходу дела.
                    <para/>
                </listitem>
            </orderedlist>
        </para>
        <para>
            Без шага №3 пользовательская функция, не принадлежащая ни к одной библиотеке
            и поэтому в случае удаления не может быть автоматически восстановлена.
        </para>
        <para>
            <warning>
                Если файл<literal>foo.sci</literal> изменён, когда <literal>foo()</literal>
                уже была вызвана, то перекомпиляция и перегрузка её библиотеки не обновит
                текущее поведение <literal>foo()</literal>: <literal>foo()</literal>,
                является уже известной, поэтому Scilab остановится на шаге №2 без
                перегрузки обновлённой библиотеки и будет использовать прежнюю
                <literal>foo()</literal>. Введение <literal>clear foo</literal> перед
                следующим вызовом <literal>foo()</literal> заставит Scilab перейти
                к шагу №3 во время следующего вызова и таким образом загрузит и будет
                использовать обновлённую <literal>foo()</literal>.
            </warning>
        </para>
        <para>
            <emphasis role="bold">Одноимённые функции в разных библиотеках: libname.foo()</emphasis>
        </para>
        <para>
            Если несколько загруженных библиотек имеют публичную функцию
            <literal>foo()</literal>, то обратный алфавитный приоритет может быть
            неуместным. К счастью, всегда можно заставить использовать содержимое
            указанной библиотеки с помощью синтаксиса разделения точкой:
            <literal>libname.foo(..)</literal> будет вызывать содержимое
            <literal>foo()</literal>, принадлежащее библиотеке <literal>libname</literal>.
        </para>
    </refsection>
    <refsection>
        <title>Примеры</title>
        <para>
            <literal>interpolationlib</literal> является родной библиотекой Scilab:
        </para>
        <programlisting role="example"><![CDATA[
interpolationlib        //отображает содержимое библиотеки
type(interpolationlib)
[typeof(interpolationlib), typeof(interpolationlib, "overload")]
string(interpolationlib)
[fnames, libpath] = libraryinfo("interpolationlib")
     ]]></programlisting>
        <para>
            Вывод иллюстрируется в разделе Описание выше.
        </para>
        <para/>
        <para>
            Вызовы обработки одноимённых функций:
        </para>
        <programlisting role="example"><![CDATA[
whereis(blanks)
clear blanks, isdef("blanks","l")
blanks(20)          // загрузка blanks() и её вызов
isdef("blanks","l") // она остаётся в workspace

// Построение библиотеки с нашей собственной одноимённой функцией blanks()
libDir = fullfile(TMPDIR, "mylib");
code = ["function r = blanks(n, nbsp)"
        "    if nbsp, r = part(ascii(160),ones(1,n)),"
        "    else r = ""ABC"","
        "    end"
        "endfunction" ];
mkdir(libDir);
mputl(code, libDir + filesep() + "blanks.sci");
genlib("mylib", libDir);    // Компиляция нашей собственной библиотеки

clear blanks
ascii(blanks(3)) // вызывается stringlib.blanks() ⇐ "stringlib" > "mylib"
clear blanks
ascii(mylib.blanks(3,%t)) // принудительный вызов mylib.blanks()
blanks(3)        // следующий вызов по умолчанию stringlib.blanks()
     ]]></programlisting>
        <screen><![CDATA[
--> whereis(blanks)
 ans  =
  "stringlib"

--> clear blanks, isdef("blanks","l")
 ans  =
  F

--> blanks(20)          // loads blanks() and calls it
 ans  =
  "                    "
--> isdef("blanks","l") // It stays in the workspace
 ans  =
  T

--> // Building a library with our own homonymous blanks() function
--> libDir = fullfile(TMPDIR, "mylib");
--> code = ["function r = blanks(n, nbsp)"
  >         "    if nbsp, r = part(ascii(160),ones(1,n)),"
  >         "    else r = ""ABC"","
  >         "    end"
  >         "endfunction" ];
--> mkdir(libDir);
--> mputl(code, libDir + filesep() + "blanks.sci");
--> genlib("mylib", libDir);    // Compiling our own library

--> clear blanks
--> ascii(blanks(3)) // stringlib.blanks() is called ⇐ "stringlib" > "mylib"
 ans  =
   32.   32.   32.

--> clear blanks
--> ascii(mylib.blanks(3,%t)) // forced call to mylib.blanks()
 ans  =
   194.   160.   194.   160.   194.   160.

--> blanks(3)        // Next call is with the default stringlib.blanks()
 ans  =
  "   "
]]></screen>
    </refsection>
    <refsection role="see also">
        <title>Смотрите также</title>
        <simplelist type="inline">
            <member>
                <link linkend="load">load</link>
            </member>
            <member>
                <link linkend="lib">lib</link>
            </member>
            <member>
                <link linkend="genlib">genlib</link>
            </member>
            <member>
                <link linkend="libraryinfo">libraryinfo</link>
            </member>
            <member>
                <link linkend="string">string</link>
            </member>
            <member>
                <link linkend="whereis">whereis</link>
            </member>
            <member>
                <link linkend="librarieslist">librarieslist</link>
            </member>
        </simplelist>
    </refsection>
    <refsection role="history">
        <title>История</title>
        <revhistory>
            <revision>
                <revnumber>6.0.0</revnumber>
                <revdescription>
                    <itemizedlist>
                        <listitem>
                            Библиотека теперь содержать только функции, а не переменные
                            любого типа.
                        </listitem>
                        <listitem>
                            Файл lib теперь является редактируемым XML-файлом, а не бинарным.
                        </listitem>
                        <listitem>
                            Если файл исходного кода foo.sci содержит несколько последовательных
                            блоков function/endfunction, то только определённая foo() теперь
                            записывается в библиотеку. Остальные определённые функции теперь
                            являются приватными и известными только из foo().
                        </listitem>
                    </itemizedlist>
                </revdescription>
            </revision>
        </revhistory>
    </refsection>
</refentry>
