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 <
alexey.veretenni...@gmail.com> 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 "
>
>

Reply via email to