[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-apl] [PATCH]: allow using lambdas in ]USERCMD

From: Juergen Sauermann
Subject: Re: [Bug-apl] [PATCH]: allow using lambdas in ]USERCMD
Date: Sat, 25 Feb 2017 15:38:46 +0100
User-agent: Mozilla/5.0 (X11; Linux i686; rv:45.0) Gecko/20100101 Thunderbird/45.2.0

Hi Alexey,

yes, but that will be the case except for existing workspaces.

When you create a new workspace then SETUP will be executed and the commands
will be saved from then on (unless you delete them).

For existing workspaces you can )COPY the SETUP workspace and )SAVE or )DUMP it again.

In the case of )CLEAR is it really to much work to )LOAD SETUP instead of )CLEAR ? My expectation
after )CLEAR would be that I have a clear WS with no functions, no variables and no commands

What I don't like is too much "automatic magic" that is difficult to comprehend for those not
familiar with it. And while you would like to have your commands regardless of )CONTINUE,
some others (including myself) may be irritated by such behavior.

/// Jürgen

On 02/25/2017 03:12 PM, Alexey Veretennikov wrote:

The point I have about user commands not cleared is rather a feature
than a bug: I would like to have a set of my user commands
irrespectively of loaded workspace. In other words, if I define ]pwd in
setup.apl, I want to be able use it in regardless of )load, )clear or
)continue and do not copy this workspace every time.

Juergen Sauermann <address@hidden> writes:

Hi Alexey,

the fact that commands are not saved with a workspace is a bug and
I will fix it. Also )CLEAR or )LOAD should remove existing user defined commands.

My point with the CONTINUE workspace was that this is exactly the functionality
that you are proposing. It is executed before anything else if you start APL. The only problem
is that the )CONTINUE command overrides the CONTINUE workspace. But we could have
a workspace with a different name, like SETUP.apl that behaves like CONTINUE but can not be
overridden by a command like )CONTINUE.

Running SETUP even if COUNTINUE is present would, in my opinion, be wrong because the
expectation of )CONTINUE is that you continue at the same point, which can not be guaranteed
because SETUP might do weird things that damage the CONTINUE workspace.

So the logic would be:

- start apl,
if CONTINUE exists - load it,
otherwise if SETUP exists - load it.

I can take care of this because there are other aspects to consider, see main.cc lines 417.

/// Jürgen

On 02/24/2017 08:24 PM, Alexey Veretennikov wrote:


The solution with )continue is not helping me: I want to have the my
commands available in all workspaces.
Right now if I )load workspace, all functions from previous workspace
got lost.
But user commands stays! meaning they will refer to unexisting
With the introduction of lambdas as user commands one could overcome
this limitation by encoding necessary functionality as lambdas.

In Dyalog APL I can create a file MyUCMDs/setup.dyalog with the
Setup←{_←⎕SE.UCMD'cd /Users/alexeyv/Sources/apl/dyalog-workspaces '}

and every time I start the interpreter my current directory is changed
to the specified.

I want to have something like this in GNU APL, so every time I run
interpreter I can:
- change the directory
- set my user commands
regardless of existence of CONTINUE workspace.

This could be solved by introducing the ~/.gnu-apl/setup.apl file with
APL source code, which if exists executes before any other workspaces.

How does it sound? If it is ok I'll implement it.

Juergen Sauermann <address@hidden> writes:

 Hi Alexey,

I believe it would be more useful to have a facility that loads an arbitrary apl script at startup
instead of a specific one for user defined commands.

Actually you can do that already with the )CONTINUE workspace, which is loaded automatically
if it exists. You could replicate the )CONTINUE logic (or simply call your workspace CONTINUE.apl).

I would also suggest that we try to exploit existing functionalities before we invent new ones.
Most non-standard functions of GNU APL are fairly useless because nobody knows them.

/// Jürgen

On 02/23/2017 07:11 PM, Alexey Veretennikov wrote:


Actually I'm thinking about a patch which will load these usercmds from
the config file at the startup. In this case every user will be
able to create own commands (like ]pwd and ]cd below) to interact with
interpreter and store them independent of the workspaces.

It will definitely helpful for me, what about others?

Christian Robert <address@hidden> writes:

 It would be fun if those ]USERCMD could be saved in workspace  and )loaded

Not sure if it's possible ...


On 2017-02-23 12:04, Juergen Sauermann wrote:

 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:


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.

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.


On Wed, Feb 22, 2017 at 4:18 PM, Alexey Veretennikov
<address@hidden> wrote:


 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.


 ]usercmd ]cd {⎕FIO[54] (⎕IO+1) ⊃ ⍵ ← ⍺}
 User-defined command ]cd installed.

 ]cd /Users/alexeyv



 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 @@

 - 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";

 -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;

 // 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 };

 out << " User-defined command "


reply via email to

[Prev in Thread] Current Thread [Next in Thread]