Page 2 of 2
Re: Importing a namespace in the same directory
Posted: Tue Feb 12, 2019 9:59 am
by augustk
Adam|Dyalog wrote:If your N namespace script has a line saying M←#.M then all subsequent references to M will go to M in the root of the namespace.
OK, thanks! (It requires two lines per import though).
Adam|Dyalog wrote:However, it may be of interest to use M←##.M instead which goes to the N's sibling M wherever N is.
As far as I understand, since :Require cannot be used inside a :Namspace, there is no added flexibility in using M←##.M instead of M←#.M in this case, right?
The only thing I miss now is a feature to prevent a variable or a function defined in a namespace from being exported from it, so that it cannot be accessed from the outside. In the absence of such a feature, a naming convention can be used. In the programming language Go, exported identifiers start with an uppercase letter whereas non-exported identifiers start with a lower-case letter. I consider adopting this convention. One drawback with this approach, however, is that it makes it harder to distinguish a non-exported function from a (lower camel case) variable in an expression.
Re: Importing a namespace in the same directory
Posted: Tue Feb 12, 2019 5:24 pm
by Adam|Dyalog
:Require is directive, which is global to its file, telling ⎕FIX to load another file, while M←##.M is a per-namespace shortcut. Your script could potentially contain more than one namespace (or nested namespaces), some of which have the shortcut, some of which don't).
What :Require does it to ⎕FIX the specified file into the same namespace as where ⎕FIX is being called from, so if ⎕FIX is being called in a sub-namespace, ##.M will reach the required M, but #.M will not.
⎕FIX':Namespace M' '∇R←F Y' 'R←Y-1' '∇' ':EndNamespace' ⍝ this M goes into # and its F function subtracts 1
'M.dyalog'⎕NPUT⍨⊂':Namespace M' '∇R←F Y' 'R←Y+1' '∇' ':EndNamespace' ⍝ this file contains the M we want
'N.dyalog'⎕NPUT⍨⊂':Require file://M.dyalog' ':Namespace N' '∇Run' '#.M.F 1' '∇' ':EndNamespace' ⍝ this N.F uses #.M
'N2.dyalog'⎕NPUT⍨⊂':Require file://M.dyalog' ':Namespace N2' '∇Run' '##.M.F 1' '∇' ':EndNamespace' ⍝ this N.F uses ##.M
sub←⎕NS⍬
sub.⎕FIX'file://N.dyalog'
sub.N.Run ⍝ this ends up calling #.M.F instead of the required sub.N.F
sub.⎕FIX'file://N2.dyalog'
sub.N2.Run ⍝ this one uses the M that it required
Try it online!If you write M as a :Class instead of as a :Namespace then you can declare which members should be public with :Access Public Shared as follows:
⎕FIX':Class M' '∇R←F Y' ':Access Public Shared' 'R←Y+1' '∇' '∇R←G Y' 'R←Y-1' '∇' ':EndClass'
⎕FIX':Namespace N' '∇Run' '##.M.F 1' '##.M.G 1' '∇' ':EndNamespace'
N.Run
2
VALUE ERROR: Undefined name: G
Run[2] ##.M.G 1
∧
Try it online!
Re: Importing a namespace in the same directory
Posted: Wed Feb 13, 2019 1:04 pm
by augustk
Adam|Dyalog wrote:What :Require does it to ⎕FIX the specified file into the same namespace as where ⎕FIX is being called from, so if ⎕FIX is being called in a sub-namespace, ##.M will reach the required M, but #.M will not.
OK, thanks for the explanation. Now I understand.
Adam|Dyalog wrote:If you write M as a :Class instead of as a :Namespace then you can declare which members should be public with :Access Public Shared...
In this case I don't need classes, only a way to encapsulate plain functions. When incorporating modularity in a programming language I think Oberon is a good language to learn from. In Oberon, encapsulation is an orthogonal feature which is not tied to object oriented programming.