Still more enhancement suggestions for APL+Win

General discussions on potential enhancements to the APL+Win system.

Still more enhancement suggestions for APL+Win

Postby Eric.Lescasse » February 14th, 2017, 7:34 pm

13. A Union primitive (dyadic ∪)
14. An Intersection primitive (dyadic ∩)
(the symbols are there)
15. A ⎕a system constant returning 'abcdefghijklmnopqrstuvwxyz'
16. A ⎕b system constant returning 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
17. A ⎕c system constant returning '∆⍙_'
18. A ⎕d system constant returning '0123456789'
19. The equivalent of ⎕watchpoints but for ⎕wi property value changes
(i.e. execution would halt as soon as a given property, say 'caption' is set: in large and complex applications it sometimes is very cumbersome and time consuming to find out where a ⎕wi property has been changed in the code)
20. A ⎕days system function returning the day names in a given culture
Example: ⎕days'en-US' or ⎕days'fr-FR'
21. A ⎕months system function returning the month names in a given culture
Example: ⎕months'en-US' or ⎕months'sv'
22. What I call "Virtual Functions" i.e. functions which are not in the workspace, only in a file repository (maybe UCMD file) but that would completely behave as if they were in the workspace. For this to work, they could be prefixed by an ampersand (&).
So, in an empty workspace:
5 &plus 6
would work by the interpreter seeing the & prefix, thus fetching the plus function from the repository, executing it and erasing it
Extension of this could be:
)ed &plus
would fetch the function plus from the repository
load it in the APL+Win Editor
when Ctrl+E would save the function back to the repository and erase it from the workspace
Another extension is that &plus should work in a function body, so the following should be possible:
Code: Select all
    ∇ r←a Test b
[1]   r←a &Test1 b
    ∇

    ∇ r←a Test1 b
[1]   r←a &plus b
    ∇

    ∇ r←a plus b
[1]   r←a+b
    ∇

      ⍝ save the Test Test1 and plus functions to the repository

      ⍝ then:

      )clear
CLEAR WS

      5 &Test 10
15

      )fns


The functions file repository could be defined in the [Config] section of the APLW.INI file.
Eric.Lescasse
 
Posts: 52
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France

Re: Still more enhancement suggestions for APL+Win

Postby Davin Church » February 14th, 2017, 7:55 pm

Eric.Lescasse wrote:19. The equivalent of ⎕watchpoints but for ⎕wi property value changes
(i.e. execution would halt as soon as a given property, say 'caption' is set: in large and complex applications it sometimes is very cumbersome and time consuming to find out where a ⎕wi property has been changed in the code)

This would be nice, but there IS a way to fake it using ⎕WI 'onAction'. I've had to do that on occasion - it's just a trick to set up sometimes (you could probably build a utility to help).
Davin Church
 
Posts: 651
Joined: February 24th, 2007, 1:46 am

Re: Still more enhancement suggestions for APL+Win

Postby Davin Church » February 14th, 2017, 8:16 pm

Eric.Lescasse wrote:22. What I call "Virtual Functions" i.e. functions which are not in the workspace, only in a file repository (maybe UCMD file) but that would completely behave as if they were in the workspace. For this to work, they could be prefixed by an ampersand (&).

I do like lots of your suggestions, and this kind of thing is certainly intriguing. I do seem to hear of a suggestion like this from time to time ever since I started in APL (in the early 70's).

While I think it could be useful, I don't really like your implementation method. Personally, I prefer to keep the language more "pure" (if that's the way to talk about it) and not create symbols that do "external" things. Likewise, speed is a real issue here, having to bring in and ⎕FX functions every time they're used is a huge waste of resources for more than just developer utilities.

However, you can do something very much like that in APL+Win already by using "user commands" and can call them from a running function using ⎕CMD (which I often do). At least this way is cleaner syntactically (it doesn't integrate into the interpreter any more than necessary) and provides a generic link to an outside facility that you can control completely. It's not as good as a direct function call, but it does give you a way to do most things in the way you describe.

Of course, Dyalog has this facility in a completely different form (last I saw). They allow you to create a separate namespace that you can attach to the session/application which would then be dynamically searched to find (and invoke) any references to a name that would otherwise produce a Value Error. This gets around much of the overhead needed to support global utilities without introducing any new language features (that they didn't already have anyway).
Davin Church
 
Posts: 651
Joined: February 24th, 2007, 1:46 am

Re: Still more enhancement suggestions for APL+Win

Postby Garth Hutchinson » February 15th, 2017, 8:04 am

22. What I call "Virtual Functions" i.e. functions which are not in the workspace, only in a file repository (maybe UCMD file) but that would completely behave as if they were in the workspace. For this to work, they could be prefixed by an ampersand (&)..


and noting Davin's comments, particularly respecting attached namespaces. This has long been a desire of mine in order to have only one copy of (especially) utility functions. Up to this point I have used "indexed" .SF (previously .ASF so you can see how long I have used it) files to bring in all needed functions. But they would only be loaded once and a set of interdependent functions could be loaded together (sort of like ] commands). This avoided restrictions in runtime versions re []copy.
R. Garth Hutchinson, BTh, FCIA
In systems since 1962, APL-er since 1970's
Garth Hutchinson
 
Posts: 45
Joined: September 24th, 2008, 9:24 am
Location: Aurora, Ontario, Canada

Re: Still more enhancement suggestions for APL+Win

Postby Davin Church » February 15th, 2017, 10:27 am

Garth Hutchinson wrote:This has long been a desire of mine in order to have only one copy of (especially) utility functions.

I think most of us have wanted to do that for most of our careers. I have, however, occasionally found exceptions to the rule. For example, I have old utility code in some applications that I don't generally want to update if the utility gets an enhancement - it risks breaking large and complex applications without prohibitively expensive testing. So I do my best to keep most utilities updated where I can and leave the necessary ones alone.

More recently (over the past several years) I've had a tool to help me with this. I wrote an APL-based code management system I called ARM and now use it to handle all my applications. One of its features includes the designation of toolkits, which may be permanently "copied" into applications. When a tool gets updated at its source, all the applications that use it automatically get the new copy the next time they're referenced. This provides a pretty effective way to keep one common set of tools, except where I need to specifically override that.

Garth Hutchinson wrote:Up to this point I have used "indexed" .SF (previously .ASF so you can see how long I have used it) files to bring in all needed functions. But they would only be loaded once and a set of interdependent functions could be loaded together (sort of like ] commands).

Of course this works fine, but I don't much like having to keep listed and up to date everything that needs to be brought in (and similar administration). At least loading them only once lets them run at full speed.

I don't expect you'd want to change your own processes after all this time, but you might like to look over my "cFiles" utilities that I wrote to be a generalized and efficient implementation of the indexed files you mentioned. They're based off of ⎕CF files and I think can do anything that anyone has ever used indexed files for (and can mix with unindexed usage as well). I ended up using these functions internally in my ARM system (above).

Talking about this it occurs to me (and has in the distant past as well) that someone might want to mix some of these ideas for a more seamless methodology. What if we started with Dyalog's concept of trapping Value Errors and use that as a trigger to load a utility function from a function-file and resume? It's not my favorite method, and we'd have to be careful of re-execution of code, but it's cute and does has some advantages in ease-of-use.
Davin Church
 
Posts: 651
Joined: February 24th, 2007, 1:46 am

Re: Still more enhancement suggestions for APL+Win

Postby Eric.Lescasse » February 15th, 2017, 11:19 am

Answering to Davin and Gary:

As a consultant (probably like Davin) I have been working to maintain and enhance very large APL applications typically with several thousands APL functions.

Invariably, the companies running these applications or products have developed a "functions repository" to store all their functions and this for several reasons:

    allowing multiple developers to work on the same application (much less risky to save one function to file than to save a entire workspace and have someone else override your changes!)
    working with applications using multiple workspaces where many common functions must be shared between these workspaces
    cleaning up the workspaces and making them more manageable by keeping only a hard nut of core functions and bringing the other ones on demand while the app runs

Every such client has developed this kind of functions repository, and that is exactly the problem: every one has HAD to develop it and it is imperfect of course, and not as fast as it could be and not as general as it could be.

Sure one can do it with User Command files or Indexed Functions file, but what I'd really like is more flexibility, i.e.:

)ed &Function

where you could directly edit the function (from the repository) even if not in the APL workspace, etc.

I think the & notation would be nice as it could be transparent:

    If the function is already in the workspace it will be just called and not erased after running
    If the function is not in the workspace it will be brought in, called and erased (or not erased for better performance: the system should be flexible enough to allow that)

The beauty would be to never have to bother if a function is there in the workspace or not: basically all calls should use the & prefix and everything would work "as if" the function were in the workspace (whether it really is, or not), with the Editor or with calls in code.

This is the thing I was suggesting.
Obviously, just like others, I have also developed my own functions repository system to load in functions with goodies.

But, a system like the one I described would be much nicer to use if it were built into the interpreter.

And to answer Davin more precisely about Dyalog, Davin is right: one can use error handling to solve the problem. I had written a system in Dyalog APL back 15-20 years ago exactly similar to what Davin describes, based on error handling where I had put all my functions and utilities in their ⎕se namespace which every workspace has access to. At the time I was using the ⎕ (not the & symbol) as the prefix.

This means that I could call any of my functions or utilities (niladic, monadic or dyadic) as if it were a Dyalog APL System Function, in any workspace, even a CLEAR WS. This was also working under program control. Many of my Dyalog APL customers had adopted that at the time as it was really nice using. Such a system is nice because all your functions or utilities are always available at any time in any workspace without you having to do anything to bring them in. It really makes a difference.

Code: Select all
      ⍝ Assuming Dyalog APL
      ⍝ and deb being my Dyalog DEB utility
      ⍝ saved in ⎕se

      )clear
CLEAR WS

      ⎕deb'   This    is  a  test'
This is a test

    ∇ r←Test a
[1]   r←⎕deb a
    ∇

      ⍝ save Test in ⎕se

      )clear
CLEAR WS

      ⎕test'    This is     a test'
This is a test
Eric.Lescasse
 
Posts: 52
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France

Re: Still more enhancement suggestions for APL+Win

Postby Davin Church » February 15th, 2017, 1:18 pm

Eric.Lescasse wrote:Invariably, the companies running these applications or products have developed a "functions repository" to store all their functions...

These are among the many reasons that I wrote my ARM system in the first place. The only thing it wasn't designed to do is provide dynamic functions at run-time - it's a little too slow for that. But with the other organizational capabilities I don't have any trouble managing very large applications that are all workspace-resident -- it's not like the old days when we had 32K (or less) WS sizes. (With ARM, the whole workspace need not even be built except for placing the final version in production.)

But ARM was designed from the ground up to be general enough and flexible enough for everyone to use so everyone no longer has to build their own separate system. I really want to make it available to everyone (probably for free) but I haven't had any spare time lately to add a few more enhancements that I think others would really want.

As far as editing is concerned, it would be easy to write something ourselves to bring up editing on non-resident functions. What seems to be most concerning to you about your request is the ability to use the )EDIT system command directly. What if we instead asked APL2000 for a hook into )EDIT where we could place our own user-written programs to use in place of (or in preparation for) the system editor? I've had that facility available before (when using IEDIT on an APL2 mainframe) and it was very useful.
Davin Church
 
Posts: 651
Joined: February 24th, 2007, 1:46 am

Re: Still more enhancement suggestions for APL+Win

Postby Eric.Lescasse » February 15th, 2017, 6:40 pm

Here is a User Command that allows to programmatically edit functions from User Command files, even if they are not in the workspace.

Code: Select all
      GRPCMDUEDIT
CMDUEDIT UEDIT_End UEDIT_Saved SmgrHandles

    ∇ CMDUEDIT a;b;c;f;h;s
[1]   ⍝∇ ]uedit object {/f=ucmdfile}
[2]
[3]   :if~0∊⍴'ueditf'⎕wi'*self'
[4]       ⎕error'Please close other ]uedit session first with:',⎕tcnl,'      "ueditf"⎕wi"*Delete"'
[5]   :endif
[6]
[7]   c←¯1+a⍳'/'
[8]   b←c↑a
[9]   f←c↓a
[10]  f←(f⍳'=')↓f
[11]
[12]  :if 0∊⍴f~' ' ⋄ f←⍙UFILES[1;] ⋄ :endif
[13]
[14]  :try *
[15]      :if c←0=⎕nc b←b~' '
[16]          ⎕ucmd']uload ',b,' /quiet /f=',f
[17]      :endif
[18]      '#'⎕wi'*onEditEnd'('"',b,'"UEDIT_End"',f,'"')
[19]      '#'⎕wi'*onEditSaved'('UEDIT_Saved"',b,'"')
[20]
[21]      s←SmgrHandles
[22]      ←⎕wcall'W_Edit'b
[23]      h←''⍴SmgrHandles~s
[24]
[25]      ←'ueditf'⎕wi'*Create' 'Form'('*style'4)('*where'¯5000 ¯5000)
[26]      ←'ueditf'⎕wi'*onWait'('←⎕wcall"SetFocus"',⍕h)
[27]      ←'ueditf'⎕wi'*Wait'
[28]  :catchall
[29]      ⎕←⎕dm
[30]  :finally
[31]      :if c ⋄ ←⎕ex b ⋄ :endif
[32]  :endtry
    ∇

    ∇ UEDIT_Saved object
[1]   :if⎕warg≡object~'∇'
[2]       uedit_saved←⎕warg
[3]   :endif
    ∇

    ∇ object UEDIT_End ucmdfile
[1]   :if⎕warg≡object~'∇'
[2]       :try
[3]           :if 2=⎕nc'uedit_saved'
[4]               ⎕ucmd']usave ',uedit_saved,' /r /f=',ucmdfile
[5]           :endif
[6]       :finally
[7]           ←⎕ex'uedit_saved'
[8]           '#'⎕wi'onEditStart' ''
[9]           '#'⎕wi'onEditSaved' ''
[10]          '#'⎕wi'onEditEnd' ''
[11]          ←'ueditf'⎕wi'*Delete'
[12]      :endtry
[13]  :endif
    ∇

    ∇ list←SmgrHandles;h;hc
[1]   ⍝∇hndls←SmgrHandles -- Return handles for all session manager edit windows
[2]   ⍝∇These handles can be used as arguments in calls to ⎕wcall to get (or
[3]   ⍝∇change) the text, selected text, cursor position, etc., in the various
[4]   ⍝∇editor windows.  Examples are the SmgrWindowName and SmgrWindowText fns.
[5]   ⍝∇Requires APLFrame
[6]   list←⍳0
[7]   h←'#'⎕wi'hwndmain'
[8]   h←⎕wcall'GetWindow'h'GW_CHILD' ⍝ Intermediate MDI window
[9]   h←⎕wcall'GetWindow'h'GW_CHILD' ⍝ First editing window
[10]  :while h≠0
[11]      hc←⎕wcall'GetWindow'h'GW_CHILD' ⍝ Eliminate icon windows
[12]      :if hc≠0 ⋄ list←list,h ⋄ :end
[13]      h←⎕wcall'GetWindow'h'GW_HWNDNEXT'
[14]  :endwhile
    ∇


and the accompanying documentation:

Code: Select all
      ]uedit?

]uedit fnName {/f=ucmdfile}
]uedit ∇fnName {/f=ucmdfile}
]uedit varName {/f=ucmdfile}

If function <fnName> is in the workspace:
- loads it in the editor
- saves it to the specified UCMD file when Ctrl+E
- leaves it in the workspace

If function <fnName> is not in the workspace:
- loads the function from the specified UCMD file
- loads it in the editor
- saves it back to the specified UCMD file when Ctrl+E
- erases it from the workspace
  (this can be changed by commenting the line in
  the :finally clause in CMDUEDIT)

If /f=ucmdfile is not specified, the top level UCMD file is assumed

⍝ (c)Eric Lescasse


You're all welcome to use this User Command as you wish.

I have attached a User Command file called UEDIT that just contains this User Command.

Note that you should NOT use this user command on a function or variable if it is already in use on another function or variable.
If you attempt to do so, you'll be warned that you have to first delete the 'ueditf' object and you may lose the changes you had made in the first ]uedit session.

I have worked with this User Command for a long time, but I think it would still be nicer to have this kind of mechanism available in the interpreter.
Attachments
UEDIT.sf
User Command File containing the ]uedit command
(4.9 KiB) Downloaded 387 times
Eric.Lescasse
 
Posts: 52
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France

Re: Still more enhancement suggestions for APL+Win

Postby Garth Hutchinson » February 16th, 2017, 6:15 am

Thank you, Eric & Davin for your code & examples. It is interesting to see the various approaches used to remedy a deficiency in APL which has been provided in most of the mainframe, mini & micro languages I have used through the years. I am challenged by the resourcefulness both of you have shown.
R. Garth Hutchinson, BTh, FCIA
In systems since 1962, APL-er since 1970's
Garth Hutchinson
 
Posts: 45
Joined: September 24th, 2008, 9:24 am
Location: Aurora, Ontario, Canada

Re: Still more enhancement suggestions for APL+Win

Postby Eric.Lescasse » February 16th, 2017, 6:34 am

Oops!
Sorry Garth: I see that I have erroneously called you Gary in a former post!
Eric.Lescasse
 
Posts: 52
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France

Re: Still more enhancement suggestions for APL+Win

Postby Eric.Lescasse » February 16th, 2017, 7:37 am

Davin said
This would be nice, but there IS a way to fake it using ⎕WI 'onAction'. I've had to do that on occasion - it's just a trick to set up sometimes (you could probably build a utility to help).


That's a pretty good idea Davin, but that does not work in my case.

As you know, I am almost exclusively developing using my zObjects APL framework (which is free and that anyone is welcome to download from http://www.lescasse.com and use) and unfortunately I have to distinguish APL+Win standard object properties from custom object properties by prefixing them with a *.

For example, there is a zList object which is a wrapper around the APL+Win List object, but has additional behavior and has a value property just like the List object but behaving differently.

Assuming I have created a zList object in a zForm with:

Code: Select all
      ←'ff'⎕wi'*Create' 'zForm'
      ←'ff'⎕wi'*.lst.Create' 'zList'('*list'(⎕cn ⎕nl 3))


If I want to use my custom zList value property I would write:

Code: Select all
      'ff'⎕wi'.lst.value'


If instead I want to use the underlying APL+Win List object value property, I would write:

Code: Select all
      'ff'⎕wi'*.lst.value'


This works pretty well, but when a property is prefixed with *, the onAction event does not fire!

Code: Select all
      ←'ff'⎕wi'*Create' 'Form'
      ←'ff'⎕wi'*.ed.Create' 'Edit'('*onAction' '⎕←⎕warg')
      ←'ff'⎕wi'.ed.text' 'Eric'
 text Eric
      ←'ff'⎕wi'*.ed.text' 'Eric'

      ←'ff'⎕wi'*Create' 'zForm'
      ←'ff'⎕wi'*.lst.Create' 'zList'('*list'(⎕cn⎕nl 3))('*onAction' '⎕←⎕warg')
      'ff'⎕wi'.lst.value' 2
 value 2
      'ff'⎕wi'*.lst.value' 2


So, unfortunately your good idea can't work (or at least can't always work) when using custom objects, which often requires that you prefix properties with * in your code.
Eric.Lescasse
 
Posts: 52
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France

Re: Still more enhancement suggestions for APL+Win

Postby Davin Church » February 16th, 2017, 10:05 am

Eric.Lescasse wrote:That's a pretty good idea Davin, but that does not work in my case.

Sorry, I didn't realize that your zObjects required the use of "*". When I've built onAction handlers of my own, I allow any normal properties & methods to pass through it invisibly and don't require special "*" coding.
Davin Church
 
Posts: 651
Joined: February 24th, 2007, 1:46 am

Re: Still more enhancement suggestions for APL+Win

Postby Eric.Lescasse » February 16th, 2017, 12:51 pm

Davin wrote:
Sorry, I didn't realize that your zObjects required the use of "*".


This is not inherent to my zObjects but it is the way custom APL+Win objects work in general.

When a custom APL+Win object has a custom property that has the same name as a property of the underlying APL+Win object it depends on, the only way to access and run the property in the underlying APL+Win object is to prefix it with a *.

In other words, if one writes his own YellowEdit object that is based on the standard APL+Win Edit object and defines a custom text property in his YellowEdit object, and assuming that ff.yedit is an instance of the YellowEdit object:

running:
'ff.yedit'⎕wi'text' ⍝ will execute the custom text property in the YellowEdit object
running:
'ff.yedit'⎕wi'*text' ⍝ will execute the standard text property of the underlying APL+Win Edit object

It actually often happens when developing custom objects, that, for various reasons, one needs to define custom properties that have the same name as the underlying APL+Win object, so, unfortunately trying to use onAction to detect ⎕wi property changes will miss all the * prefixed ⎕wi calls.
Eric.Lescasse
 
Posts: 52
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France

Re: Still more enhancement suggestions for APL+Win

Postby Davin Church » February 16th, 2017, 4:22 pm

Eric.Lescasse wrote:This is not inherent to my zObjects but it is the way custom APL+Win objects work in general.

I understand. I simply don't have duplicate names and then the problem never arises.
Davin Church
 
Posts: 651
Joined: February 24th, 2007, 1:46 am

Re: Still more enhancement suggestions for APL+Win

Postby Eric.Lescasse » February 16th, 2017, 5:11 pm

Davin wrote
I understand. I simply don't have duplicate names and then the problem never arises.


Well, it still arises because you should use the * prefix for the following reason:

When you use custom objects, even if you do not have duplicate names for your custom objects, and if you want to achieve the best performance in your app, it is highly advisable to use the * prefix when you call the native APL+Win objects properties and methods. It is much faster as it precisely bypasses the onAction event handler step completely. It also bypasses the whole object inheritance chain and directly calls the property or method at the raw APL+Win object level.

zObjects fully supports inheritance and you can have custom objects inheriting other custom objects which themselves inherit other custom objects, etc. which at the end of the chain inherit a standard APL+Win object.

Inheritance and visual inheritance is what gives a real great power to custom objects.

Using * when you need to access the raw level APL+Win object is very much faster in those cases.

This is precisely why the * prefix has been invented, I think.
Eric.Lescasse
 
Posts: 52
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France

Next

Return to APL+Win Wish-List

Who is online

Users browsing this forum: No registered users and 11 guests

cron