|
From: | Juergen Sauermann |
Subject: | Re: [Bug-apl] [PATCH]: allow using lambdas in ]USERCMD |
Date: | Thu, 23 Feb 2017 18:04:18 +0100 |
User-agent: | Mozilla/5.0 (X11; Linux i686; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 |
Hi Alexey, Blake, I have applied the patch, SVN 892. I don't think that it hurts too much even though its not APL. Nor are lambdas, so the ⍎ of )COMMANDs and {...} should fit nicely. /// Jürgen On 02/23/2017 08:47 AM, Alexey
Veretennikov wrote:
Hi, I'm updating the ]USERCMD functionality which is already non-standard extension in GNU APL. Similar extension exists in Dyalog APL for quite many years as well. These commands targeted use in the interpreter and have nothing to do with a new syntax. What I did is just fixed its limitation where I always had to create a named function to add a user command. P.S. Example with ]pwd was bogus, the proper one is ]usercmd ]pwd {⎕FIO 30 ⍵} User-defined command ]pwd installed. ]pwd /Users/alexeyv Blake McBride <address@hidden> writes:Not sure I like this. Doesn't seem like APL. You are mangling program-ability with system commands. APL has no history of that. It may be an okay idea, but it's not APL. Adding program-ability to system commands is essentially adding a whole new syntax to APL. Just one opinion. Blake On Wed, Feb 22, 2017 at 4:18 PM, Alexey Veretennikov <address@hidden> wrote: Hi, The proposed patch allows usage of dfns as a ]USERCMD. The mode (monadic or dyadic) is not needed since it is derived from the lambda function itself. Possibility to use lambdas as a user commands allows to have commands without polluting the global namespace with the function names. Usage example: ]usercmd ]pwd {⎕FIO 30 ⍵ ← ⍺} User-defined command ]pwd installed. ]pwd /Users/alexeyv/Sources/apl-svn/src ]usercmd ]cd {⎕FIO[54] (⎕IO+1) ⊃ ⍵ ← ⍺} User-defined command ]cd installed. ]cd /Users/alexeyv 0 ]pwd /Users/alexeyv -- Br, /Alexey Index: src/Command.cc =================================================================== --- src/Command.cc (revision 891) +++ src/Command.cc (working copy) @@ -1277,6 +1277,7 @@ // ]USERCMD REMOVE ]existing-command // ]USERCMD ]new-command APL-fun // ]USERCMD ]new-command APL-fun mode + // ]USERCMD ]new-command LAMBDA-fun // if (args.size() == 0) { @@ -1321,14 +1322,54 @@ return; } - if (args.size() > 3) + // check if the user command is not followed by the string + if (args.size() == 1) + { + out << "BAD COMMAND+" << endl; + MORE_ERROR() << "user command syntax in ]USERCMD: ]new-command APL-fun [mode]"; + return; + } + UCS_string command_name = args[0]; + UCS_string apl_fun = args[1]; + int mode = 0; + + // check if lambda + bool is_lambda = false; + if (apl_fun[0] == '{') { + // looks like the user command is a lambda function. + UCS_string result; + // lambdas could contain spaces, collect all arguments in one string + for (int i = 1; i < args.size(); ++ i) + { + result << args[i]; + } + // check if lamda-function closed properly + if (result.last() == '}') + { + is_lambda = true; + apl_fun = result; + // determine the mode: if both alpha and omega present, assume dyadic, + // otherwise - monadic usage + mode = (apl_fun.contains(UNI_OMEGA) && apl_fun.contains(UNI_ALPHA)) ? 1 : 0; + } + else + { + out << "BAD COMMAND+" << endl; + MORE_ERROR() << "not found closing } in lambda function"; + return; + } + } + + if (args.size() > 3 && !is_lambda) + { out << "BAD COMMAND+" << endl; MORE_ERROR() << "too many parameters in command ]USERCMD"; return; } -const int mode = (args.size() == 3) ? args[2].atoi() : 0; + // check mode + if (!is_lambda && args.size() == 3) mode = args[2].atoi(); if (mode < 0 || mode > 1) { out << "BAD COMMAND+" << endl; @@ -1339,11 +1380,11 @@ // check command name // - loop(c, args[0].size()) + loop(c, command_name.size()) { bool error = false; - if (c == 0) error = error || args[0][c] != ']'; - else error = error || !Avec::is_symbol_char(args[0][c]); + if (c == 0) error = error || command_name[c] != ']'; + else error = error || !Avec::is_symbol_char(command_name[c]); if (error) { out << "BAD COMMAND+" << endl; @@ -1355,28 +1396,31 @@ // check conflicts with existing commands // #define cmd_def(cmd_str, _cod, _arg, _hint) \ - if (check_name_conflict(out, cmd_str, args[0])) return; + if (check_name_conflict(out, cmd_str, command_name)) return; #include "Command.def" - if (check_redefinition(out, args[0], args[1], mode)) + if (check_redefinition(out, command_name, apl_fun, mode)) { out << " User-defined command " - << args[0] << " installed." << endl; + << command_name << " installed." << endl; return; } // check APL function name - // - loop(c, args[1].size()) + // Only needed when not a lambda function + if (!is_lambda) { - if (!Avec::is_symbol_char(args[1][c])) - { - out << "BAD COMMAND+" << endl; - MORE_ERROR() << "bad APL function name in command ]USERCMD"; - return; - } + loop(c, apl_fun.size()) + { + if (!Avec::is_symbol_char(apl_fun[c])) + { + out << "BAD COMMAND+" << endl; + MORE_ERROR() << "bad APL function name in command ]USERCMD"; + return; + } + } } -user_command new_user_command = { args[0], args[1], mode }; +user_command new_user_command = { command_name, apl_fun, mode }; user_commands.append(new_user_command); out << " User-defined command " |
[Prev in Thread] | Current Thread | [Next in Thread] |