Conversation started Mar 7, 2018 at 18:29.
Mar 7, 2018 6:29 PM
Welcome to APL Cultivation!
~2 minutes early :D
@EriktheOutgolfer SE is behind, it seems.
As we went through various aspects of classes, some questions came up that I wasn't able to answer on the spot.
I was asked if Dyalog APL supports iterators (and generators) like C#.
Dyalog APL doesn't directly, however you can get much the same effect using :For and having an enumerable property, i.e. using :Property Numbered. Then you can index into the property, but APL will not require calculation of the entire property's value, only of the needed element.
The Get method's argument will then have a member called Indexers which can be used to determine which of the values to return.
Could you make it :Property Default Numbered so you don't have to specify that you're indexing into the one property?
@Adám as in :For foo :In <propertyName>?
@Pavel Yes.
@J.Sallé No, that would try to get all the values and collect them for :For. You'd have to do :For i :In ⍴propertyName ⋄ foo←propertyName[i].
Mar 7, 2018 6:36 PM
0
Q: APL Conditionals, Breakpoints

Jason KramerI am currently working on an APL program for a class and have run into an issue with error handling. In a function I made, I want to check to see that the input is an integer. To do that, I compare to see if it's equal to the floor of itself. If not, I don't want the function to run and want it ...

@Feeds Later…
Another question which came up was how to protect ⎕DF. Answer is that you can't. Of course, the code inside the class can reset ⎕DF whenever it is critical.
@Adám ah, I see. That's what I was going for, I just misinterpreted what you said
Lastly was the question about partially private properties. Say, Get is public but Set is private. JohnD, who wrote the system, was surprised that letting each function have its own :Access declaration didn't work as intended. He said that he will investigate this.
Ah, ok
@all Shall we continue with "multiple properties in one go?"
Mar 7, 2018 6:41 PM
What does that mean?
@Pavel I'll show you :-D
Sometimes a class needs a few properties that have the same or similar getter and setter. Instead of repeating yourself, Dyalog APL lets you collapse the code into a single :Property block.
:Class Person

    :field heightVal
    :field weightVal
    :field ageVal←0

    :Property height,weight,age
    :Access public
        ∇ r←Get x
          r←⌊⍎x.Name,'Val'
        ∇
    :endproperty

:EndClass
Notice the comma-separated "name list".
Now you can also see why the argument to Get needs to be a namespace; so that we can determine which property was requested.
Oooh
@Adám How might I make a setter? I'm guessing wouldn't really work there.
@Pavel Exactly the same way as the getter, and yes, can work, but you can also make some decisions using :If x.Name≡ or :Select x.Name.
@Adám So, if we want to get the height of the person, we'd just do x←Person.height?
Is :Select Dyalog's Switch/Case?
Mar 7, 2018 6:49 PM
@J.Sallé Yes.
@Pavel yes
@Pavel ^ See Lesson 15 at your convenience.
Not to paste too long scripts in the chat, here is the full Person class:
https://tio.run/##jVJLToNAGN5zin/XNm0JPhoTdq1pmibadKXrKYxAHJjJMA3lAmqMbdwYr@ANPEBvwkVwYIaHxlZZwff/fI/5BjEydFNEqJfn9iVBcQxLzGMaGQbIx74LMHHBx4HnixtE2mDyG4g8LJHs4dVSBNnTI0wCLvyuD0mvhOTu2HGwVGLrFQmcCpyHjOAQRyIGh0ax4GtHUK6n3dpCo9uTMpK10tGOl5wyzEWqTQ/U@kAaMw5qK59c8s2wgE2NQollL8/ZdrcxFyjEg44U7rR/U6w4cpkWboLPOE3ACY@lrmP1pZBerbOUHCiI4N47xpG0OfTqN44rGuP/cgwPcIw9DOkxBtV8YSH90Uh1MDC5nisEHexgFQaqhVYHCpMtWOaoXxvdf@7fs@2H33yfWNYfxdjTyC0veZ6zgnL3tpje6gsP3ZEFZz2DmeWRW@aFfFVqBVZUeWqOmvF5eyyTfQE
OK, let's talk about inheritance.
Yes, please!
A quite fundamental idea in OOP is that you can make a more sophisticated object based on a simpler or more general object.
For this we have derived or "child" classes.
Notice the difference between an instance and a derived class.
The instance also inherits from class, but it is fundamentally of the same nature as its sibling instances.
A derived class is a new class that you can make instances of. They inherit the members of the base class (although the derived class's code may overwrite base members), but cal also have additional features.
Instances of a derived class are also instances of the base class, of course.
Enough talking. Let me show you!
:Class American : Person

    :field public ssn

    ∇ Birth(w h)
      :Access public
      :Implements constructor :base w h
      ssn←1↓∊('-'@1∘⍕¨⊢+¯1+?)1000 100 10000
    ∇

:EndClass
So in the :Class header line, we have an additional colon (:) and the name of the base class.
An American is really just another person, but with a social security number.
The social security number is given at birth, so we have a constructor that sets ssn.
But we can't just replace the constructor of the Person class, because it performs some important stuff too, namely initialising the weight and height.
If we define this class, and then someone changes the ⎕ML globally, would that cause the use of to break, or does the class definition have a ⎕ML scoped to itself?
Mar 7, 2018 7:02 PM
@Pavel ⎕ML is namespace scope. A namespace inherits its parent namespace's ⎕ML when it is created, but then it keeps it (and can change it of course). So, no, changing ⎕ML globally does not affect existing namespaces.
Ok, cool.
@Pavel However, if you distribute a class in text form for others to use, you'd be wise to include the necessary settings at the very top. In Dyalog, we most often write ⎕ML ⎕IO←1 at the top of our scripts.
Of course, if your namespace exists inside some other of your code, you don't have to worry about that.
Back to our American example: Notice the :base in the constructor declaration. It tells APL to call the constructor of the base class. w h is used to propagate the constructor arguments to the base constructor.
if you don't declare :field public ssn, what does ssn default to?
I wrote w h out for clarity, but it could also just have said Birth args:base args. APL would have made sure to find the right base constructor (for 2 arguments), and would have thrown an error if the user didn't supply exactly two arguments.
@Cowsquack The default is private instance.
Of course, you can also have a base class that doesn't need any arguments to construct, but a derived class that does need arguments. In such a case, you'd have a monadic derived class constructor, with the line :Implements constructor :base.
And of course, you can have the opposite too, and differing number of args, etc. Mix and match as you see fit!
@Adám that's enlightening, I'll most certainly use it.
Mar 7, 2018 7:16 PM
@J.Sallé Great.
Sorry for the wait. I was editing a large example:
https://tio.run/##tVPBattAFLz7K95NFraD1NCLLq0TQgi0IZDS@1raSkulldiVUfwDrjFVaCmmPRcKufUSyD35k/0R91kry4prKSa0BoM9ejtvZmdEknDgTUgY@8ulcxwSKeGCChnzTgfw43xgNPQgoMwP0vckrIPZLpD4FBE1/WJpAjX7BEdMpEE3gMwsIJwdui7FTcl4FDJ3DZ5FSUgjylMJbsxlKsZuGovyabeSsNlr4hpkXe8pFV@IOKEinZSi@3q8j8I6jbu1ToF8pzSFqwqFAlOf5yq/vjo4JxHtG7jYqB/TrJR7Sbl4Y/xUxBm4UZvrylYPF5WjlZeCgzAOH/02jqzOUY4@4ngTS7ovx6CBY@hTmLQx6ORXEiZbiawvBo7enmmENGYwiphOoZaBxjAF6@BlrxL6cPfwXeU3wea/bVlPBOOccK8oOf7UZT@PsZvDiArmEg7OrvJrlRAS7o/RJEoxTrgfMhkYWx0HInz5jI6DMyKYUHW6uLq/tdZkPpK9S62UfPsFzCAwny8OT5dzSI13
So, I've extended our classes as follows:
:Class NorthAmerican : Person

    :field public language←'English'

    ∇ Birth args
      :Access public
      :Implements constructor :base args
    ∇

:EndClass

:Class American : NorthAmerican

    :field public ssn

    ∇ Birth(w h)
      :Access public
      :Implements constructor :base w h
      ssn←1↓∊('-'@1∘⍕¨⊢+¯1+?)1000 100 10000
    ∇

:EndClass
(there's also a Canadian in the same vein as the American)
So here we have Americans and Canadians being derived from NorthAmerican which is a type of person (yes, really).
Each "level" adds its features to the final class's instances.
Now, if you deal with a lot of such derivations, you may want to know the hierarchy of a certain class or instance.
Monadic ⎕CLASS gives you a vector of refs beginning with the class and ending with the most basic class.
You may also want to know the opposite: Which instances does this class have?
Monadic ⎕INSTANCES gives you a vector of refs to all the instances of the given class.
Remember that we can use ⎕DF to give our objects more palatable display forms, and have a look at this example:
@all There's a lot there to look at, so give me some feedback when you're ready.
@Adám Can you ⎕DF a class inside the class itself, or only after assigning it to an instance?
@Adám sorry but my mind is a little tired for feedback :)
Mar 7, 2018 7:32 PM
@J.Sallé Any object can get a display form, even a raw class.
@Adám okay, good.
@J.Sallé Here:
⍞←cl⊣(⎕FIX':class cl' '∇r←SetDF x' ':access public shared' '⎕DF x' 'r←1' '∇' ':endclass').SetDF'yo!'
@Adám yo!
Ah, you can .SetDF
Nice!
@J.Sallé Well, I just wrote a method called that which, well, does that.
There's another nice system function when dealing with classes (and other scripted objects); ⎕SRC (SouRCe):
⎕←↑⎕SRC cl⊣(⎕FIX':class cl' '∇r←SetDF x' ':access public shared' '⎕DF x' 'r←1' '∇' ':endclass').SetDF'yo!'
Mar 7, 2018 7:37 PM
@Adám
:class cl
∇r←SetDF x
:access public shared
⎕DF x
r←1
∇
:endclass
@J.Sallé See ^?
@all Shall we do interfaces as well?
Are interfaces useful in a dynamic type system?
@Pavel I'm so uneducated. Care to elaborate?
Interfaces don't mean anything by themselves, so they're used in C++/C#/Java only for static type checking.
Dyalog doesn't have that.
A Dyalog interface is a script (unsurprisingly :Interface:EndInterface) which defines some properties and/or methods.
Then multiple classes can use a common skeleton framework.
This can help ensure a harmonised API.
Consider for example the following:
:Interface FishBehaviour
∇ R←Swim ⍝ Returns description of swimming capability
∇
:EndInterface ⍝ FishBehaviour
Notice that there isn't any code in Swim. It is just a stub for the actual class to fill in.
It could also have multiple such stubs:
:Interface BirdBehaviour
∇ R←Fly ⍝ Returns description of flying capability
∇
∇ R←Lay ⍝ Returns description of egg-laying behaviour
∇
∇ R←Sing ⍝ Returns description of bird-song
∇
:EndInterface ⍝ BirdBehaviour
Mar 7, 2018 7:45 PM
@Adám yeah I see it now hahahah
Now we can define a class with a baseclass, which implements these methods:
:Class Penguin: Animal,BirdBehaviour,FishBehaviour
    ∇ R←NoCanFly
      :Implements Method BirdBehaviour.Fly
      R←'Although I am a bird, I cannot fly'
    ∇
    ∇ R←LayOneEgg
      :Implements Method BirdBehaviour.Lay
      R←'I lay one egg every year'
    ∇
    ∇ R←Croak
      :Implements Method BirdBehaviour.Sing
      R←'Croak, Croak!'
    ∇
    ∇ R←Dive
      :Implements Method FishBehaviour.Swim
      R←'I can dive and swim like a fish'
    ∇
:EndClass ⍝ Penguin
Is there multiple inheritance from classes?
@Pavel Well, a derived class can only have a single base class, but you can use these interfaces to have something resembling multiple inheritance. Notice the :Class line. Animal is the base class, whereas methods and properties from BirdBehaviour and FishBehaviour are included in the Penguin class
@Pavel You can also :Include a namespace of methods, which, just like with interfaces, does not copy them into your class, but still makes them available. This means there is no memory overhead in doing so.
Oh, and you can write :Using Namespace or :Using Namespace,Assembly to gain access to members of .NET namespaces.
OK, I think we've covered more than enough for today, and indeed we've covered most things regarding OO in Dyalog APL.
@all Any questions?
I don't think you mentioned overriding
can't cover 'em all in just 90 minutes :P he did already cover much though
Mar 7, 2018 7:59 PM
@Pavel Right, OK. Maybe I'll do that next time. Another thing I've only mentioned but not shown is numbered and keyed properties. Let's do that next week.
Thank you for participating!
 
Conversation ended Mar 7, 2018 at 20:00.