⎕USING and Dfns

General APL language issues
paulmansour
Posts: 431
Joined: Fri Oct 03, 2008 4:14 pm

⎕USING and Dfns

Post by paulmansour »

Consider the following function:

Code: Select all

OpenExcelFile←{
     ⍝ ⍵ ←→ File Name
     ⍝ ← ←→ .NET ZipArchive
     ⎕USING←'System.IO.Compression,System.IO.Compression.FileSystem.dll'
     ZipFile.OpenRead⊂⍵
 }


It works. But only if there is not some object (a variable, function, or namespace) named ZipFile as a sibling of OpenExcelFile. (Leaving aside what ⎕PATH might do!).

I can covert to a trad function, and localize ZipFile in the header, and then it will work properly in all cases. (The trad function in more functional than the dfn!)

Two questions:

1. Is there any way to properly do this in a dfn? That is, is there a more explicit way to say I want to use a .NET class?

2. In trad function, it would seem a requirement to localize any top-level .NET name one accesses as otherwise the function only really works by accident as is the case with the dfn. Or am I missing something?
paulmansour
Posts: 431
Joined: Fri Oct 03, 2008 4:14 pm

Re: ⎕USING and Dfns

Post by paulmansour »

To answer my own question (#1), while it does not explicitly locate the .NET class, we can localize a non-existing variable in a dfn, achieving the same result of putting a name in the header of a trad function, by creating it and deleting it. Thus:

Code: Select all

OpenExcelFile←{
     ⍝ ⍵ ←→ File Name
     ⍝ ← ←→ .NET ZipArchive
     ZipFile←0
     _←⎕EX 'ZipFile'
     ⎕USING←'System.IO.Compression,System.IO.Compression.FileSystem.dll'
     ZipFile.OpenRead⊂⍵
 }


This also has the salutary effect of not leaving behind a reference to ZipFile in the workspace. Not sure if that is a performance hit or not.
paulmansour
Posts: 431
Joined: Fri Oct 03, 2008 4:14 pm

Re: ⎕USING and Dfns

Post by paulmansour »

Some rough testing indicates no meaningful performance hit for localization of the .NET class.
User avatar
PGilbert
Posts: 440
Joined: Sun Dec 13, 2009 8:46 pm
Location: Montréal, Québec, Canada

Re: ⎕USING and Dfns

Post by PGilbert »

In case it might help this post is explaining my understanding of ⎕USING. I am retaining this passage from John:

The interpreter optimizes multiple assignments to ⎕USING so that assemblies are loaded all at once when a reference might need them - thus the behaviour you are seeing - the assemblies are not loaded into the appdomain until you force a reference.


I have tried the code in your first post in a )CLEAR WS (v18) and it is working for me.
paulmansour
Posts: 431
Joined: Fri Oct 03, 2008 4:14 pm

Re: ⎕USING and Dfns

Post by paulmansour »

I have tried the code in your first post in a )CLEAR WS (v18) and it is working for me.

Yes, it works in a clear workspace. The point is that is does not work in a workspace with a variable, function, or namespace named "ZipFile". It specifically relies are there NOT being such an object.
User avatar
PGilbert
Posts: 440
Joined: Sun Dec 13, 2009 8:46 pm
Location: Montréal, Québec, Canada

Re: ⎕USING and Dfns

Post by PGilbert »

Sorry Paul, you are correct, it does not work when 'ZipFile' is defined outside of the dfn and does not seems to be the correct behavior to me also.

I have tried many things and I can't make it work the way you presented it.
Veli-Matti
Posts: 94
Joined: Sat Nov 28, 2009 3:12 pm

Re: ⎕USING and Dfns

Post by Veli-Matti »

Hi,
.NET is not my favourite thing, but just occurred to me that this trick might work:

      OpenExcelFile←{
ZipFile←#
⎕USING←'System.IO.Compression,System.IO.Compression.FileSystem.dll'
_←⎕EX'ZipFile'
ZipFile.OpenRead⊂⍵
}


-Veli-Matti
paulmansour
Posts: 431
Joined: Fri Oct 03, 2008 4:14 pm

Re: ⎕USING and Dfns

Post by paulmansour »

Hi Veli-Matti,

That does indeed work as I showed above when I (partly) answered my own question. In a dfn, simply assigning 0 (or anything) to a name and then expunging the name effectively localizes the name. A subsequent reference to that name will produce a value error even if the name exists globally.
User avatar
StefanoLanzavecchia
Posts: 113
Joined: Fri Oct 03, 2008 9:37 am

Re: ⎕USING and Dfns

Post by StefanoLanzavecchia »

paulmansour wrote:To answer my own question (#1), while it does not explicitly locate the .NET class, we can localize a non-existing variable in a dfn, achieving the same result of putting a name in the header of a trad function, by creating it and deleting it. Thus:


I'd do the same. But I'd probably set ZipFile to []NS'' just to show my intention of later overriding it with another "namespace".
This said, let me warn you of something I discovered empirically: if you localise ZipFile in a trad-fn and work with multiple APL threads (&), sometimes the interpreter does not put the external names back in ZipFile when switching from thread to thread. The bug has been reported more than once but there does not seem to be a simple solution at the horizon. And I got a recommendation by JD himself to never localize directly a .NET namespace but to always encapsulate those in a traditional namespace.
In other words, I changed all my code to be:

Code: Select all

     _NET←⎕NS''
     _NET.⎕USING←,⊂''

      counter←_NET.System.DateTime.UtcNow.ToBinary.ToString ⍬


and I only localize _NET.
This works flawlessly. Notice that you can set []USING to your taste. My taste is to always use full names which makes my invocations very verbose, but you don't need to.
I don't know if the issues can be replicated in d-fns but I wouldn't be surprised if that was the case.
User avatar
norbertjurkiewicz84
Posts: 62
Joined: Mon Nov 01, 2010 7:26 pm

Re: ⎕USING and Dfns

Post by norbertjurkiewicz84 »

StefanoLanzavecchia wrote:
paulmansour wrote:To answer my own question (#1), while it does not explicitly locate the .NET class, we can localize a non-existing variable in a dfn, achieving the same result of putting a name in the header of a trad function, by creating it and deleting it. Thus:


I'd do the same. But I'd probably set ZipFile to []NS'' just to show my intention of later overriding it with another "namespace".
This said, let me warn you of something I discovered empirically: if you localise ZipFile in a trad-fn and work with multiple APL threads (&), sometimes the interpreter does not put the external names back in ZipFile when switching from thread to thread. The bug has been reported more than once but there does not seem to be a simple solution at the horizon. And I got a recommendation by JD himself to never localize directly a .NET namespace but to always encapsulate those in a traditional namespace.
In other words, I changed all my code to be:

Code: Select all

     _NET←⎕NS''
     _NET.⎕USING←,⊂''

      counter←_NET.System.DateTime.UtcNow.ToBinary.ToString ⍬


and I only localize _NET.
This works flawlessly. Notice that you can set []USING to your taste. My taste is to always use full names which makes my invocations very verbose, but you don't need to.
I don't know if the issues can be replicated in d-fns but I wouldn't be surprised if that was the case.



Very interesting. By chance I started doing this a years ago. I create a #.DotNET namespace where I initialize 99% of the .NET code at application startup.
Post Reply