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 "