From: Samuel GOUGEON Date: Fri, 7 Aug 2020 20:33:40 +0000 (+0200) Subject: * Bug 16529 fixed: deff() upgraded: output arg added, one-string def, etc X-Git-Tag: 6.1.1~85 X-Git-Url: http://gitweb.scilab.org/?p=scilab.git;a=commitdiff_plain;h=1e737dd2260acfbf1c71fef8307b9e46c99055a8 * Bug 16529 fixed: deff() upgraded: output arg added, one-string def, etc http://bugzilla.scilab.org/16529 New deff() page (PDF): http://bugzilla.scilab.org/attachment.cgi?id=5175 Change-Id: I37cff6f15eeb1730137e2ce21aaf63ee3a8dba5b --- diff --git a/scilab/CHANGES.md b/scilab/CHANGES.md index c36c1fd..8b8545b 100644 --- a/scilab/CHANGES.md +++ b/scilab/CHANGES.md @@ -227,6 +227,11 @@ Feature changes and additions on 6.1.1 * `polyint` is introduced to compute polynomial antiderivatives. * Listbox uicontrol callback is now triggered by item click in single selection mode. For example, it allows successive execution of a demo in the demonstrations gui. * `det` is now actually extended to sparse matrices. +* `deff` is upgraded: + - The created function may be returned as output argument. + - Providing the function headline and body concatenated in a single input text vector is possible. + - For a simple function, a single string input definition can be provided. + - For assignable calls to `deff`, the `@` symbol can be used as function pseudo-name. Help pages: @@ -398,6 +403,7 @@ Bug Fixes * [#16458](https://bugzilla.scilab.org/16458): `mean()` did not handle sparse numerical matrices. * [#16465](https://bugzilla.scilab.org/16465): Scinotes OpenRecent menu was not updated when it should. * [#16473](https://bugzilla.scilab.org/16473): Deleting rows in a sparse squared the matrix with padding zeros (Scilab 6 regression). +<<<<<<< HEAD * [#16474](https://bugzilla.scilab.org/16474): `imult(%z)` crashed Scilab. * [#16476](https://bugzilla.scilab.org/16476): `issquare` was not overloaded. * [#16488](https://bugzilla.scilab.org/16488): Concatenations mixing boolean and double with at least one operand being sparse were not supported. @@ -447,6 +453,10 @@ Bug Fixes ======= >>>>>>> afb92ac5368 (* Bug 16614 fixed: replot() could fail out of gcf()) +======= +* [#16529](https://bugzilla.scilab.org/16529): `deff` could not return the created function as output argument, preventing to cretae and use anonymous functions. The function's headline and body had to be provided separately. For Simple functions, a one-string input (possibly console-oriented) definition was not supported. + +>>>>>>> 75a0ccd0638 (* Bug 16529 fixed: deff() upgraded: output arg added, one-string def, etc) ### Bugs fixed in 6.1.0: * [#2694](https://bugzilla.scilab.org/2694): `bitget` did not accept positive integers of types int8, int16 or int32. diff --git a/scilab/modules/functions/help/en_US/deff.xml b/scilab/modules/functions/help/en_US/deff.xml index 497a965..54fc0b0 100644 --- a/scilab/modules/functions/help/en_US/deff.xml +++ b/scilab/modules/functions/help/en_US/deff.xml @@ -2,9 +2,8 @@ deff('x = myplus(y,z)', 'x = y+z') --> myplus(1,%i) ans = @@ -85,6 +252,154 @@ a = 3; u = 7. ]]> + + With some single input and output: + + + source = ["r = myFunc(x,y)" ; "r = x.*(x-y)"] + source = + "r = myFunc(x,y)" + "r = x.*(x-y)" + +--> deff(source) +--> myFunc(3, -2) + ans = + 15. +]]> + + Same example with a one-line definition, that then allows a console-oriented + syntax (without optional deff parentheses, but with still mandatory delimiting quotes): + + + deff "r = myFunc(x,y) r = x.*(x-y)" +--> myFunc(1:3, -2) + ans = + 3. 8. 15. +]]> + + For a one-line direct definition with a single output, we can even omit the "r = " duplicate in the body: + + + deff "r = myFunc(x,y) x.*(x-y)" +--> myFunc(1:3, -2) + ans = + 3. 8. 15. +]]> + + Function with no assignable output: Note also the usage of doubled quotes to protect + them in the definition string: + + + + + Defined function assigned to a recipient + + Let's keep similar examples as above: + + + actualName = deff("r = myFunc(x,y) x.*(x-y)") + actualName = +[r]=actualName(x,y) + +--> isdef(["myFunc" "actualName"]) + ans = + F T + +--> actualName(1:3, -2) + ans = + 3. 8. 15. + +--> myFunc(1:3, -2) +Undefined variable: myFunc +]]> + + Since the "internal" function name is fake, we can use "@" instead + (the "@" character is not allowed in actual function names): + + + actualName = deff("r = @(x,y) x.*(x-y)"); +--> actualName(1:3, -2) + ans = + 3. 8. 15. +]]> + + Now, let's directly assign the created function to a nameless recipient. + Although the function becomes anonymous, we can still call it: + + + L = list("abc", deff("r = @(x,y) x.*(x-y)"), %z); +--> L(2)(1.1:4, -2.1) + ans = + 3.52 8.82 16.12 + +--> Abc = L(2) + Abc = +[r]=Abc(x,y) + +--> Abc(1.1:4, -2.1) + ans = + 3.52 8.82 16.12 +]]> + + Finally, let's use deff() to directly define and pass a function + as an input argument of another function: + + + test(rand(2,3), 0.7, deff("r = @(M) sum(size(M).^2)")) + ans = + 13.7 +]]> + + In this example, the passed function is anonymous in the calling environment, + but is assigned and gets its "theFunct" name from inside the called function. + + See also @@ -128,6 +443,25 @@ a = 3; + + 6.1.1 + + + + Output optional argument added. Anonymous functions can be defined. + + + Single input argument supported, concatenating the function headline and body. + + + Single string syntax supported, like deff "r = myFun(x,y) x.^2-y" + + + "@" function's pseudo-name supported. + + + + diff --git a/scilab/modules/functions/help/ja_JP/deff.xml b/scilab/modules/functions/help/ja_JP/deff.xml deleted file mode 100644 index 4d871a8..0000000 --- a/scilab/modules/functions/help/ja_JP/deff.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - deff - 関数のオンライン定義 - - - 呼び出し手順 - deff('[s1, s2,...] = newfunction(e1, e2,...)',text) - - - 引数 - - - e1, e2, ... - - 入力変数. - - - - s1, s2, ... - - 出力変数. - - - - text - - 文字列行列 - - - - - - 説明 - - deff はテキスト文字列で記述された一連の命令から - 関数を定義する際に使用されます. - 得られる関数オブジェクトはテキストファイルで定義され, - exec または exec で - 定義された他の関数と同じ特性を有しています. - - > - 命令の中の引用符(文字列の区切りまたは行列の転置を意味する)は, - ただしく解釈されるように二重化する必要があります(quoteのヘルプを参照). - この仕様のため,作成作業はやや不便となります. - - - - 例 - - deff('x = myplus(y,z)', 'x = y+z') ---> myplus(1,%i) - ans = - 1. + i - ---> deff('[y, z] = mymacro(x)', ['y = 3*x+1'; 'z = a*x + x.^2']) ---> a = 3; ---> [u, v] = mymacro(2) - v = - 10. - - u = - 7. -]]> - - - 参照 - - - function - - - exec - - - getd - - - genlib - - - jdeff - - - jcompile - - - - - 履歴 - - - 6.0.0 - - - - The input option - - opt="c"|"p"|"n" - is no longer available. - - - The defined newfunction is now of type 13 (instead of 11). - - - - - - - \ No newline at end of file diff --git a/scilab/modules/functions/help/pt_BR/deff.xml b/scilab/modules/functions/help/pt_BR/deff.xml deleted file mode 100644 index 55c7050..0000000 --- a/scilab/modules/functions/help/pt_BR/deff.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - deff - definição on-line de função - - - Seqüência de Chamamento - deff('[s1, s2, ...] = newfunction(e1, e2,...)',text) - - - Parâmetros - - - e1, e2, ... - - variáveis de entrada. - - - - s1, s2, ... - - variáveis de saída. - - - - text - - matriz de strings. - - - - - - Descrição - - deff pode ser usada para definir funções de - seqüências de instruções escritas em strings de textos. Objeto função - resultante tem as mesmas propriedades que qualquer outra função definida - em um arquivo de texto e carregada através de exec ou - exec. - - - - Exemplos - - deff('x = myplus(y,z)', 'x = y+z') ---> myplus(1,%i) - ans = - 1. + i - ---> deff('[y, z] = mymacro(x)', ['y = 3*x+1'; 'z = a*x + x.^2']) ---> a = 3; ---> [u, v] = mymacro(2) - v = - 10. - - u = - 7. -]]> - - - Ver Também - - - function - - - exec - - - getd - - - genlib - - - jdeff - - - jcompile - - - - - Histórico - - - 6.0.0 - - - - The input option - - opt="c"|"p"|"n" - is no longer available. - - - The defined newfunction is now of type 13 (instead of 11). - - - - - - - diff --git a/scilab/modules/functions/help/ru_RU/deff.xml b/scilab/modules/functions/help/ru_RU/deff.xml index bd38b86..2fc5d50 100644 --- a/scilab/modules/functions/help/ru_RU/deff.xml +++ b/scilab/modules/functions/help/ru_RU/deff.xml @@ -2,9 +2,8 @@ + xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" + xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" + xml:lang="ru" xml:id="deff"> deff - определение функции во время выполнения программы + вставленное определение (анонимной) функции на языке Scilab Синтаксис - deff('[s1, s2, ...] = newfunction(e1, e2, ...)',text) + + deff(funcHeadline, funcBody) + deff(definition) + deff("[r1, r2, ...] = myFunc(in1, in2, ...)", funcBody) + deff "r = myFunc(x,y) r = x^2 - y" + deff "r = myFunc(x,y) x^2 - y" + deff("r = @(x,y) x^2 - y") // в качестве элемента анонимного контейнера + + myFunc = deff(funcHeadline, funcBody) + myFunc = deff(definition) + myFunc = deff("[r1, r2, ...] = fakeName(in1, in2, ...)", funcBody) + myFunc = deff("r = fakeName(x,y) r = x^2 - y") + myFunc = deff("r = fakeName(x,y) x^2 - y") + myFunc = deff("r = @(x,y) x^2 - y") + Аргументы - e1, e2, ... + x, y, in1, in2, ... + + входные аргументы определяемой функции. Последняя может иметь + любое количество входных аргументов, от 0 до любого N. + + + + + r, r1, r2, ... - входные переменные. + результаты на выходе определяемой функции. Последняя может + иметь любое количество результатов на выходе, от 0 до любого + M. Все выходные аргументы должны быть явными, то есть, + записанными слева от имени функции. + - s1, s2, ... + funcHeadline - выходные переменные. + одиночная строка: заголовок функции, то есть, её первая строчка, + указывающая локальное имя функции и списки её входных аргументов + с правой стороны и выходных аргументов с левой стороны. Примеры: + + + "myFunction(x,y)" : нет аргументов на выходе + + + "r = myFunction(x,y)" : один аргумент на выходе + + + "[a,b] = myFunction(x,y)" : два аргумента + на выходе. И т.д. + + + Пожалуйста, обратите внимание, что a) ключевое слово function + не обязательно указывать. b) запись выходных аргументов, если они есть, на левой + части заголовочной строчки является обязательной. + - text + funcBody - матрица символьных строк. + вектор текстов, то есть Scilab-инструкций тела функции, в том + порядке, в котором они должны быть выполнены. Эти инструкции + должны определять и назначать значения всех выходных аргументов. + Завершающее ключевое слово "endfunction" не ожидается. + + Этот вектор ожидается, когда deff(…) вызывается + с двумя входными аргументами. + + + Одинарные или двойные кавычки внутри инструкций должны + дублироваться для защиты. + + + + + + definition + + Отдельный текст или вектор текстов, включая как заголовочную + строчку функции, так и тело. + + + Если это вектор, то это эквивалентно + definition = [funcHeadline ; funcBody]. + + + В противном случае одностроковое определение эквивалентно + funcHeadline + " " + strcat(funcBody,"; "). + + + Пожалуйста, смотрите разделы "Описание" и "Примеры". + + + + + myFunc + + Публичное имя и идентификатор определяемой функции, неявно + возвращаемый в текущее окружение, либо явно присваиваемый + переменной на выходе deff(…). + + + Когда deff(…) вызывается без явных выходных + аргументов, но в качестве элемента контейнера или в качестве + входного аргумента другой функции, то она неявно присваивается + этому элементу или аргументу, который является анонимным. То + тогда она является + анонимной функцией. Например: + + L = list(3, deff("r=noName(x) x.^2+1"), "Hello");. + Результат deff(…) присваивается L(2). + Тогда L(2)(3.5) // ➜ 13.25. + + @@ -54,23 +150,112 @@ Описание - Функция deff может быть использована для определения функций из - ряда инструкций, написанных в текстовых строках. Полученный объект функции имеет те же - свойства, что и любая другая функция, определённая в текстовом файле и загруженная - с помощью функции exec. + deff(…) может использоваться для определения + отдельной функции из инструкций Scilab, указанных + через матрицу текстов, вместо любого внешнего текстового файла с + инструкциями для исполнения, записанными в блок function … endfunction. + + Файл исходного Scilab-кода может включать в себя определение нескольких + публичных функций. Это не возможно сделать с помощью deff(…): + только одну публичную функцию можно определить. Однако, как и в случае + с файлом, тело определяемой функции может включать в себя один или + несколько блоков function … endfunction, определяющих + вложенные приватные функции. + + + Независимо от синтаксиса deff(…), используемого для + обеспечения исходного кода (см. ниже), если он содержит синтаксическую + ошибку, то deff(…) выдаст ошибку компиляции + и остановит работу. + + + Указание исходного кода + + deff(funcHeadline, funcBody) (2 входа) и + deff([funcHeadline ; funcBody]) + (единый конкатенированный вход) эквивалентны. + + + Когда funcBody сделана только из одной (короткой) + строки, она может быть приклеена и передана вместе с + funcHeadline, как одностроковое определение функции. + Примеры: + + + + + + + + + +
deff("[a,b] = myFunction(x,y) a = x.^2; b = x-y;")
+ deff("r = myFunction(x,y) r = (x-y).^2"). + Это можно даже упростить до +
+ deff("r = myFunction(x,y) (x-y).^2") +
deff("myFunction(x,y) disp(x.^2 - b)")
+
+ + Когда результат deff(…) присваивается или вводится + в любой анонимный контейнер, то оказывается, что псевдоимя + fakeName, определённое в funcHeadline + не играет роли вообще, и может совсем не использоваться для вызова + функции. Это имя может быть тогда заменено символом "@" в + funcHeadline для указания, что определяемая + функция становится анонимной. + +
+ + Идентификатор определяемой функции + + Идентификатор - это фактическое слово (имя), которое используется + для вызова определяемой функции. Следующие три случая представлены + для примера. + + + Когда определяемая функция не предполагает присваиваемый результат, + то её идентификатор возвращается напрямую в вызывающее окружение. + Её публичное имя тогда является именем, используемым в заголовочной + строчке представленного исходного кода. + + + В противном случае, когда deff(…) вызывается с + явным выходным аргументом, то его имя становится единственным + фактическим идентификатором публичной функции. В результате, имя + функции, используемой в исходном коде, нельзя использовать для её + вызова. Оно становится псевдоименем. По этой причине в заголовочной + строчке может быть использован символ "@" (ставящийся для "анонимок") + вместо какого-либо корректного имени функции, определённой в заголовочной + строчке. Но это не обязательно. + + + Последний случай использования deff(…) в качестве + элемента контейнера, например когда определяется или вводится в список, + либо в качестве входного аргумента другой функции. Тогда + deff(…) работает как присвоение. Она возвращает + идентификатор определяемой функции и присваивает его соответствующему + элементу списка или входного аргумента. Они безымянны, следовательно + вызов deff(…) является выражением. Определяемая + функция тогда становиться реально анонимной. + +
Примеры - + Неприсваивающие функции + + - + deff('x = myplus(y,z)', 'x = y+z') --> myplus(1,%i) ans = @@ -85,6 +270,159 @@ a = 3; u = 7. ]]> + + С единственным входным и выходным аргументом: + + + source = ["r = myFunc(x,y)" ; "r = x.*(x-y)"] + source = + "r = myFunc(x,y)" + "r = x.*(x-y)" + +--> deff(source) +--> myFunc(3, -2) + ans = + 15. +]]> + + Тот же пример с одностроковым определением, которое затем позволяет + синтаксис, ориентированный на командную строку (без необязательных + скобок deff, но с, по-прежнему, обязательными разделительными кавычками): + + + deff "r = myFunc(x,y) r = x.*(x-y)" +--> myFunc(1:3, -2) + ans = + 3. 8. 15. +]]> + + Для однострокового прямого определения с единственным выходным аргументом, + мы можем даже опустить дубликат "r = " в теле функции: + + + deff "r = myFunc(x,y) x.*(x-y)" +--> myFunc(1:3, -2) + ans = + 3. 8. 15. +]]> + + Функция без присваиваемого выходного аргумента: обратите также внимание + на использование удвоенных кавычек для защиты их в строке определения: + + + + + Определяемая функция, присваиваемая реципиенту + + Придержимся примеров, похожих на приведённые выше: + + + actualName = deff("r = myFunc(x,y) x.*(x-y)") + actualName = +[r]=actualName(x,y) + +--> isdef(["myFunc" "actualName"]) + ans = + F T + +--> actualName(1:3, -2) + ans = + 3. 8. 15. + +--> myFunc(1:3, -2) +Undefined variable: myFunc +]]> + + Поскольку имя "внутренней" функции является псевдоименем, то мы + можем вместо него использовать "@" (символ "@" нельзя использовать + в фактических именах функций): + + + actualName = deff("r = @(x,y) x.*(x-y)"); +--> actualName(1:3, -2) + ans = + 3. 8. 15. +]]> + + Теперь напрямую присвоим созданную функцию безымянному реципиенту. + Хотя функция становится анонимной, мы, по-прежнему, можем вызывать её: + + + L = list("abc", deff("r = @(x,y) x.*(x-y)"), %z); +--> L(2)(1.1:4, -2.1) + ans = + 3.52 8.82 16.12 + +--> Abc = L(2) + Abc = +[r]=Abc(x,y) + +--> Abc(1.1:4, -2.1) + ans = + 3.52 8.82 16.12 +]]> + + Наконец, давайте используем deff() для прямого + определения и передачи функции в качестве входного элемента другой + функции: + + + test(rand(2,3), 0.7, deff("r = @(M) sum(size(M).^2)")) + ans = + 13.7 +]]> + + В этом примере передаваемая функция является анонимной в вызывающем + окружении, но присваивается и получает своё имя "theFunct" внутри + вызываемой функции. + + Смотрите также @@ -118,12 +456,35 @@ a = 3; Входная опция - + opt="c"|"p"|"n" - более не доступна. + больше не доступна. + + + Определяемая newfunction теперь имеет + тип 13 (вместо 11). + + + + + + 6.1.1 + + + + Добавлен необязательный выходной аргумент. Могут определяться + анонимные функции. + + + Поддерживаются одиночные входные аргументы, конкатенирующие + заголовочную строку функции и её тело. + + + Поддерживается синтаксис одиночной строки, вроде + deff "r = myFun(x,y) x.^2-y" - Определённая новая функция newfunction теперь имеет тип 13 (вместо 11). + Поддерживается псевдоимя функции "@". diff --git a/scilab/modules/functions/macros/deff.sci b/scilab/modules/functions/macros/deff.sci index b4e0c6f..9d75208 100644 --- a/scilab/modules/functions/macros/deff.sci +++ b/scilab/modules/functions/macros/deff.sci @@ -1,21 +1,60 @@ -function deff(varargin) - if size(varargin) <> 2 then - error(msprintf(_("%s: Wrong number of input arguments: %d expected.\n"), "deff", 2)); - end +// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab +// Copyright (C) INRIA +// Copyright (C) 2012 - 2016 - Scilab Enterprises +// Copyright (C) 2020 - 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. - //try to build execstr string - str = "function " + varargin(1); - str = [str ; varargin(2)(:); "endfunction"]; +function varargout = deff(varargin) + [lhs, rhs] = argn(); + if rhs < 1 | rhs > 2 then + msg = _("%s: Wrong number of input arguments: %d or %d expected.\n") + error(msprintf(msg, "deff", 1, 2)) + end + if rhs == 2 then // Usual deff syntax + prototype = varargin(1) + text = matrix(varargin(2), -1, 1) + else + text = matrix(varargin(1), -1, 1) + if size(text,"*")==1 + // We must split the input into the prototype and the definition + // The prototype is ended with the first ")": + [b, e, prototype] = regexp(text,"/.*?\)/", "o") + text = part(text,e+1:$) + // Case r = fun(x,y) x^2+y (single output, no r= in the definition: + if grep(prototype, "=") <> [] & grep(text,"=")==[] + outvar = strtok(prototype, "=") + if grep(outvar,",")==[] + text = outvar + " = " + text + end + end + else + prototype = varargin(1)(1) + text = varargin(1)(2:$) + end + end + // Detect @ in the prototype and replace it, if any (can't be a function's name): + if grep(prototype, "@") <> [] // "/(?:[^(]*?)=\s*(.+?)(?:\s*\()/") + prototype = strsubst(prototype, "@", "%funcname"); + end + // try to build execstr string + str = ["function " + prototype ; text ; "endfunction"]; execstr(str); - funcs = funclist(); - if size(funcs, "*") <= 0 then - return; - elseif size(funcs, "*") <> 1 then - return; + %deff_func = funclist(); + if size(%deff_func, "*") <= 0 | size(%deff_func, "*") <> 1 then + return else - execstr(funcs + "= return(" + funcs + ")"); + if argn(1) == 0 + execstr(%deff_func + "= return(" + %deff_func + ")"); + else + execstr("varargout = list(" + %deff_func + ");") + end end - endfunction diff --git a/scilab/modules/functions/tests/unit_tests/deff.dia.ref b/scilab/modules/functions/tests/unit_tests/deff.dia.ref deleted file mode 100644 index b760f5d..0000000 --- a/scilab/modules/functions/tests/unit_tests/deff.dia.ref +++ /dev/null @@ -1,43 +0,0 @@ -// ============================================================================= -// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab -// Copyright (C) 2009 - DIGITEO - Allan CORNET -// -// This file is distributed under the same license as the Scilab package. -// ============================================================================= -// <-- CLI SHELL MODE --> -deff("[x] = myplus(y,z)","x=y+z"); -assert_checktrue(isdef("myplus")); -assert_checkequal(myplus(3,2), 5); -clear myplus; -assert_checkfalse(isdef("myplus")); -deff("[x] = mymacro(y,z)",["a=3*y+1"; "x=a*z+y"]); -assert_checktrue(isdef("mymacro")); -assert_checkequal(mymacro(5,2), 37); -clear mymacro; -assert_checkfalse(isdef("mymacro")); -deff("[a,b,c] = mymacro(varargin)",["a = varargin(1); b = varargin(2) * a; c = varargin(3) * b"]); -assert_checktrue(isdef("mymacro")); -[a,b,c] = mymacro(3,4,5); -assert_checkequal(a, 3); -assert_checkequal(b, 12); -assert_checkequal(c, 60); -clear mymacro; -assert_checkfalse(isdef("mymacro")); -deff("[varargout] = mymacro(varargin)",["for i = 1 : size(varargin)"; " varargout(i) = varargin(i) * 2;";"end"]); -assert_checktrue(isdef("mymacro")); -[a,b,c] = mymacro(3,4,5); -assert_checkequal(a, 6); -assert_checkequal(b, 8); -assert_checkequal(c, 10); -clear mymacro; -assert_checkfalse(isdef("mymacro")); -deff("[varargout] = mymacro(varargin)", ["deff(""varargout = mymacro2(varargin)"", [""for i = 1 : size(varargin)""; "" varargout(i) = varargin(i) * 2;"";""end""]);";"[a,b,c] = mymacro2(varargin(:));";"varargout(1) = a*2;";"varargout(2) = b*2;";"varargout(3) = c*2;"]); -assert_checktrue(isdef("mymacro")); -assert_checkfalse(isdef("mymacro2")); -[a,b,c] = mymacro(3,4,5); -assert_checkequal(a, 12); -assert_checkequal(b, 16); -assert_checkequal(c, 20); -assert_checkfalse(isdef("mymacro2")); -clear mymacro; -assert_checkfalse(isdef("mymacro")); diff --git a/scilab/modules/functions/tests/unit_tests/deff.tst b/scilab/modules/functions/tests/unit_tests/deff.tst index b724c91..ef0002b 100644 --- a/scilab/modules/functions/tests/unit_tests/deff.tst +++ b/scilab/modules/functions/tests/unit_tests/deff.tst @@ -1,11 +1,14 @@ // ============================================================================= // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab // Copyright (C) 2009 - DIGITEO - Allan CORNET +// Copyright (C) 2020 - Samuel GOUGEON // // This file is distributed under the same license as the Scilab package. // ============================================================================= // <-- CLI SHELL MODE --> +// <-- NO CHECK REF --> + deff("[x] = myplus(y,z)","x=y+z"); assert_checktrue(isdef("myplus")); @@ -48,3 +51,53 @@ assert_checkfalse(isdef("mymacro2")); clear mymacro; assert_checkfalse(isdef("mymacro")); +// Other syntaxes +clear Fun +deff(["r = Fun(x)" "r = x.^2 - 3"]); // Only one deff argin, being a vector +assert_checktrue(isdef("Fun","l")); +assert_checkequal(Fun(4), 13); +clear Fun +deff "r = Fun(x) r = x.^2 - 3"; // Only one deff argin, being a scalar +assert_checktrue(isdef("Fun","l")); +assert_checkequal(Fun(4), 13); +clear Fun +deff("r = Fun(x) x.^2 - 3"); // Fun argout implicit assignment (missing in definition) +assert_checktrue(isdef("Fun","l")); +assert_checkequal(Fun(4), 13); + +// output = deff(..) +// ================= +clear Fun myFun +myFun = deff("res = Fun(a,b)",["res = a+b" "res = res.^2"]); +assert_checkequal(myFun(1,1), 4); +assert_checkfalse(isdef("Fun","l")); + +clear myFun +e = execstr("myFun = deff(""res = Fun(a,b)"",[""res = a+"" ""res = res.^2""]);", "errcatch"); +assert_checktrue(e <> 0); // syntax error ^^^ +assert_checkfalse(isdef("myFun","l")); +assert_checkfalse(isdef("Fun","l")); + +in = list(["r = Fun(x)" "r = x.^2"], .. // Only one deff argin, being a vector + "r = Fun(x) r = x.^2", .. // Only one deff scalar argin + "r = Fun(x) x.^2",.. // Fun argout implicit assignment (missing in definition): + "[a,b] = Fun(x) a=x.^2; b=x-3"); // Only one deff scalar argin. 2 outputs +for argin = in + clear myFun + myFun = deff(argin); + assert_checktrue(isdef("myFun","l")); + assert_checkfalse(isdef("Fun","l")); + if grep(argin(1), "[a,b]") <> [] + [u,v] = myFun(4); + assert_checkequal([u v], [16 1]); + else + assert_checkequal(myFun(4), 16); + end + + // Anonymous "@" + clear myFun + argin = strsubst(argin, "Fun", "@") + myFun = deff(argin); + assert_checktrue(isdef("myFun","l")); + assert_checkequal(myFun(4), 16); +end