« first day (392 days earlier)      last day (2265 days later) » 

3:46 PM
SimCorp signed license contracts with eight new #SimCorp Dimension clients in 2017, and met its financial guidance. Learn more in our #annualreport. http://bit.ly/2sH7KP6
Informal APL learning session tonight at 18:30 UTC in https://chat.stackexchange.com/rooms/52405/apl . See https://chat.stackexchange.com/transcript/message/41299896 … if you don't have 20 Stack Exchange rep points
Join our live webinar Total Array Ordering on Thursday 22 March 2018 at 16:00 UTC. Jay & Adám introduce a new feature coming up in Dyalog APL version 17.0 that lets you sort anything. https://dyalog.tv/Webinar Following webinar is scheduled for Thursday 19 April at 15:00 UTC.
 
Ven
SimCorp?
 
@Ven SimCorp is a major and influential Dyalog APL user.
 
Ven
Ah, ok.
 
 
2 hours later…
5:38 PM
@Adám Can I build Dyalog into a standalone .NET executable?
 
5:53 PM
@Pavel Yes, File > Export
 
Thanks!
I'll have to try that and dissassemble it when I get home. I wonder how non-.net calls get translated to ILASM.
 
@Pavel It just packages the interpreter inside the executable and calls to that.
 
6:17 PM
@Adám That's cheating! :-)
 
6:30 PM
Welcome to APL Cultivation!
Last time we introduced classes. Now we will learn how to actually use them.
When you create an instance of a class using ⎕NEW BaseClass, you may want to supply some parameters.
For this, we use a special type of method (function) called a constructor.
When you create a new instance, a constructor (if one exists in the class script) will be called.
:Class cl1

    ∇ Ctor
      :Access public
      :Implements constructor
      ⎕←'Hi!'
    ∇

:EndClass
We define a tradfn called Ctor (it could be called anything, though) and declare it available from the outside (it must be, as you can't be inside yet when you're just creating the instance).
 
@Adám That looks verbose. Is there a... golfier way of doing it? :-)
 
Then the :Implements line declares it a constructor.
@wizzwizz4 Only removing white space and using shorter names. APL is not a golfing language.
The line⎕←'Hi!' is the actual code in the function. It is then executed every time ⎕NEW runs, as you can see in TIO.
 
@Adám Can you set a constructor dynamically?
 
@wizzwizz4 What does that mean? You take a non-constructor method and make it into a constructor later?
 
@Adám Or a function and add it as a constructor.
 
6:38 PM
@wizzwizz4 Well, you can always edit the class script, and all the existing instances will update (this is unique to Dyalog APL, I think), but since a constructor only runs at creation time and never in the base class, it will not run if it was added later. However, any new instances created after the edit will run it.
 
lol TL;DR make your constructors right away
 
@Adám That's a neat feature. Is that due to lack of caching?
 
@wizzwizz4 I'm not sure what you mean by lack of caching. I know that it was a pain to implement.
Now have a look at this modified class:
:Class cl2

    :Field public value

    ∇ Ctor x
      :Access public
      :Implements constructor
      value←x
    ∇

:EndClass
 
@Adám Oh, wow. If that was deliberate, it must have taken some work. I assumed it was a side-effect of the implementation.
 
Here we have an uninitialised field (variable) and a monadic constructor which sets the variable upon construction: Try it online!
@wizzwizz4 It was really complicated to get to work. Indeed, base classes are "cached", because i you delete the base class after making an instance, an unaccessible "phantom" base class is kept until the last instance is gone.
Now:
:Class cl3

    ∇ None
      :Access public
      :Implements constructor
      ⎕←'No arguments.'
    ∇


    ∇ One x
      :Access public
      :Implements constructor
      ⎕←'1 argument:'x
    ∇

:EndClass
Here is a class with two constructors. APL will call the appropriate one (niladic or monadic): Try it online!
 
6:48 PM
Can I set something like C#'s ToString so we can print the output in a prettier way?
 
@Adám This is "overloading"?
 
I don't think so. The methods have different names.
 
@Pavel Yes, yes, but we're not there yet.
@wizzwizz4 Feel free to call it that, if you so wish. It is what it is.
 
@Pavel Open notepad or leafpad or something and write questions there. That way, you can ask them when we get there.
 
@Adám looks like you can't have more than 1 argument, can you?
 
6:50 PM
@EriktheOutgolfer I can only type so fast…
:Class cl4

    ∇ None
      :Access public
      :Implements constructor
      ⎕←'No arguments.'
    ∇


    ∇ One x
      :Access public
      :Implements constructor
      ⎕←'1 argument:'x
    ∇

    ∇ Two(a b)
      :Access public
      :Implements constructor
      ⎕←'2 arguments'a b

    ∇

:EndClass
 
@wizzwizz4 Or, in my case, kate.
 
Any guesses?
 
@Adám sorry, but I can't know what you're going to post next :)
 
@Adám Zero, one and two?
 
@wizzwizz4 Yes, and APL will call the appropriate one: Try it online!
 
6:51 PM
@Adám Can you have typed overloading?
 
@Adám I tested it, and the result isn't good...
 
Or is it more like Python in that respect (ignoring types in syntax)?
 
@EriktheOutgolfer You need to be more precise with what you mean. Do you mean that different things happen when you ⎕NEW depending on the type of the argument?
 
@Adám i.e. the result is an error
 
@Adám Yes.
 
6:53 PM
@EriktheOutgolfer Where, doesn't my TIO link work?
 
(Is that a reply to the wrong message?)
 
@wizzwizz4 Hang on.
 
@Adám your TIO what? there's no link for cl4, and this makes it look like it will result in an error
oh
oh you need parentheses?
 
@EriktheOutgolfer It's in the response to wizzwizz4.
 
@Adám yeah I had skipped it
 
6:55 PM
@EriktheOutgolfer Yes, ⎕NEW takes one or two arguments. The second (optional) argument are the constructor args.
 
@Adám uh, maybe it should've been ⎕NEW's left argument instead, if it's not already something else...
 
@EriktheOutgolfer It tries to follow C# syntax.
:Class cl5

    :Field public name←'baby'
    :Field public age←0

    ∇ Ctor x
      :Access public
      :Implements constructor
      :If ' '=⊃0⍴x
          name←x
      :Else
          age←x
      :EndIf
    ∇

:EndClass
 
@Adám yeah, you can't reply with a code block
 
@wizzwizz4 ^^ Has a single constructor which decides what to do. Try it online!
 
@EriktheOutgolfer I think you can if it's quoted (> ). That doesn't exist.
 
6:59 PM
@wizzwizz4 quoting is something different ;)
 
@Adám I expected that to be possible... I was wondering whether the language would do it for you.
 
@wizzwizz4 So the multiple constructors can take care of number of arguments, but you can of course also handle everything in a single fancy constructor.
@wizzwizz4 No, in APL, all arrays are created equal ;-)
 
@Adám Harder to read though, often.
@Adám Are functions first-class objects? (I think yes, just checking.)
 
@wizzwizz4 I had to type it up fast. I'd put in some comments if I was to do this IRL.
@wizzwizz4 Yes. Check previous lessons on operators.
 
Not entirely first-class, i.e you can't have an array of functions
 
7:01 PM
@Adám hm, that's not what I usually think as "first class"
 
@H.PWiz There are actually two ways to do that. But not today's lesson.
 
@Adám I would love to see it. Can you jot reduce one? (let's move on)
 
@Adám If you don't put limitations like that in place, we'll completely derail it in seconds. :-)
 
@Adám Store an array of System.Funcs. :P
 
7:04 PM
OK, final example of multiple constructors:
:Class cl6

    ∇ None
      :Access public
      :Implements constructor
      ⎕←'No arguments.'
    ∇


    ∇ One x
      :Access public
      :Implements constructor
      ⎕←'1 argument:'x
    ∇


    ∇ Two(a b)
      :Access public
      :Implements constructor
      ⎕←'2 arguments'a b

    ∇

    ∇ Three(a b c)
      :Access public
      :Implements constructor
      ⎕←'3 arguments:'a b c
    ∇

:EndClass
We have 0–3. What happens when I call this with more than 3?
 
@Adám One is called with an array?
 
@Adám Varargs of some description?
 
@dzaima Yup. Nice: Try it online!
@wizzwizz4 The one with just a single argument is effectively a "varargs".
 
@Adám Can you set a different one as varargs?
e.g. to distinguish between... can't remember the syntax but ((1 2 3 4 5 6 7 8)) and (1 2 3 4 5 6 7 8)?
 
@wizzwizz4 You probably mean ⊂1 2 3 4 5 6 7 8 and 1 2 3 4 5 6 7 8.
@wizzwizz4 No, the a single named argument indicates that it can take a variable number of args. If you want to refuse construction with non-scalar arg the constructor will have to inspect the arg and throw an error.
OK, enough about constructors. Lets talk about something fun: Destructors.
 
7:11 PM
@Adám Will the error then be interpreted as an invalid call?
Oops.
 
@wizzwizz4 oops what?
 
@wizzwizz4 You can throw any error you want with any message you want, so yes, you can throw a length error.
 
@Adám How much violence are we talking?
@EriktheOutgolfer We've moved on.
 
@wizzwizz4 Not a problem. I should have prompted for questions. I just assume you all will interrupt me. (Which is what I want!)
 
Are APL Destructors basically C++ Destructors?
 
7:13 PM
@Adám Ok. If the constructor throws an error, will it be recalled with the variable argument format?
 
Sometimes when an instance ceases to exist, you want to do some clean-up. E.g. when the webserver is closed, you want to free ports and write a message to the log, etc.
 
@Pavel s/++/#/?
 
@wizzwizz4 Recalled?
 
@Adám *re-called
E.g. if Two throws, will One be called with an array of two?
 
I did mean C++, but it sounds like they actually are like C#'s Finalize.
 
7:14 PM
@wizzwizz4 No.
 
Ok. So, no special errors.
 
@Pavel I don't know any C++, but maybe you'll be able to tell in a little bit.
:Class cl7

    ∇ Hi
      :Access public
      :Implements constructor
      ⎕←'Hello there!'
    ∇

    ∇ Bye
      :Implements destructor
      ⎕←'See you later!'
    ∇

:EndClass
Do I need to explain?
 
In C#, when the garbage collector deletes an object, it calls its Finalize method. You can override it to do cleanup.
 
@Pavel Ah, but in Dyalog APL you can call most methods what you want. Hence the need to declare it a destructor.
 
@Adám Can you have more than one?
 
7:18 PM
@wizzwizz4 No, because ceasing to exist doesn't have any arguments. Should be obvious, no? I suppose you could have a method that takes arguments, does something with them, and then kills the self somehow.
 
@Adám It is... but what about subclass destructors?
How would they work if you can only have one?
Is there an equivalent of Python's super?
 
@wizzwizz4 Ah, each level can have a destructor and they will all be called. That's fine.
@wizzwizz4 What does that do/what is that?
 
@Adám In Python magic methods are named, e.g. __del__. super().__del__ is a reference to the parent's __del__, going up the MRO (method resolution order, a solution to multiple inheritance) to invoke the closest version. Otherwise the parent class destructors aren't implicitly called if overridden.
How do you stop a parent's destructor from running?
For example, if you subclass your webserver so it shares a socket (like SATA's master/slave).
 
@wizzwizz4 You can call base class methods with ⎕BASE.MethodName.
 
@Adám Interesting.
 
7:23 PM
@wizzwizz4 IFAIK, you can't.
 
What if you don't know the name, but you know its implementee?
 
@wizzwizz4 why wouldn't you know its name >_>
 
@wizzwizz4 If something is shared, then it it won't go away when the instance dies. And of course, the instance destructor shouldn't just close the socket. Rather it should check whether there are any others that use it first.
 
@EriktheOutgolfer If you're using somebody else's code and they're terrible at keeping a consistent API?
 
@wizzwizz4 The name of what? And what is an implementee?
 
7:25 PM
@wizzwizz4 uh, then you shouldn't use their code, simple ;)
 
@Adám Sorry. The thing it implements, e.g. destructor.
@EriktheOutgolfer That's often not a choice in Serious Business Programming™.
 
@wizzwizz4 You shouldn't (and can't) call the base (or any) destructor. I don't understand what you're getting at.
 
@Adám Trying to do something I shouldn't. Never mind.
Wait... if we can't call it, why does it have a name?
 
@wizzwizz4 Although I've previously pondered why you can't kill an instance by calling its destructor. That way, you could have destructors with arguments… Anyway, I'm only teaching what Dyalog APL currently offers…
 
@Adám That might not have been a possibility that entered the original developer's mind. But it should be easy enough to replace the socket itself in that scenario so it didn't close when bidden.
@Adám Because then APL would have to deal with null.
 
7:29 PM
@wizzwizz4 I guess it technically doesn't need to have one, but for sanity and the ability to find it in the class tree-view.
 
@Adám Can you reuse its name?
 
@wizzwizz4 Null?
 
@Adám Well, technically NULL...
If you've destructed an object, you're left with references to...
Garbage data?
An unresponsive object?
 
@wizzwizz4 Re-use the name of the destructor? I guess you could shadow it and then reuse it, but I wouldn't recommend it.
@wizzwizz4 The destructor won't run until the last ref is eliminated.
 
@Adám Would anything particularly bad happen, apart from the inward groaning of anybody looking at the code?
 
7:31 PM
(as if like that's not bad enough)
 
@Adám You've answered your pondering, I think.
Unless you're willing to deal with that, destructors shouldn't be callable.
 
@wizzwizz4 I don't think so. But really, APL allows arbitrary length names and gives you three alphabets (upper, lower, circled/underlined)…
 
I didn't really expect them to be except by a technicality, which would cause Bad Things™ to happen.
 
@wizzwizz4 Ah, I see what you mean now. But ⎕EXing an instance has the same problem. Calling the destructor with an argument could just keep that argument on storage for later.
 
@Adám Then what happens if it's called again?
Also, you're not really dealing with destructors any more.
That's a queue.
It doesn't belong in destructor-handling code.
 
7:35 PM
@wizzwizz4 Right. Let's put that idea aside.
 
You can shadow the destructor if you like... :-)
@EriktheOutgolfer Bad enough yet? :-p
 
@all Any other questions about constructors and destructors? Or other things about classes that we've covered so far?
 
@Adám is calling a class's destructor from within the instance intended to throw a VALUE ERROR?
 
@Adám Are there true primitives, or are those instances of classes?
 
@EriktheOutgolfer It surely should throw some kind of error.
 
7:39 PM
@EriktheOutgolfer I don't think there's a WHY? ERROR.
 
:Class ICallDestructorsImLame

    ∇ Destruct
      :Implements destructor
    ∇

    Destruct

:EndClass
inst←⎕NEW ICallDestructorsImLame
 
@wizzwizz4 What APLers call primitives are the built-in functions and operators. But APL isn't OO in itself.
 
those two together raise a VALUE ERROR
@Adám
 
@EriktheOutgolfer What happens if you call something unnamed?
 
@wizzwizz4 like what?
 
7:41 PM
@EriktheOutgolfer the Destruct should be in a function
 
@EriktheOutgolfer It sure does make sense, doesn't it? APL gives value errors for things you don't have access to, e.g. trying to call a public method from outside, or an instance method from of base class..
 
@EriktheOutgolfer Trying to call Distressed. My theory is that the error will be the same.
If I understand the language feature.
 
@dzaima Doesn't make a difference: Try it online!
 
@wizzwizz4 uh, yes? although that's not what I call "something unnamed" but rather "unassigned name" :P
 
@Adám this seems to work
 
7:43 PM
@EriktheOutgolfer You're right; I misspoke.
 
oh, :access public was required :p
 
@dzaima Oh, yes. Silly me. And now I remember that that works even though you really shouldn't be allowed to do that.
 
@Adám yeah... (although I don't think a destructor should contain ⎕OFF)
 
@dzaima I guess that does allow you to have a single clean-up function which you can call early, e.g. to reset the state of the instance when things went wrong or the user wants to start over.
 
@Adám Isthat a bug?
 
7:45 PM
@wizzwizz4 A bug or a feature (^^), I'm not sure.
@EriktheOutgolfer Why not? E.g. an application could e.g. close APL (i.e. itself) when a certain object is closed by the user, rather than dumping the user to the session.
 
@Adám like PATCH.DWS does, and I find that a bit annoying :P
 
@Adám Is there really no way to override a parent class's behaviour?
 
@EriktheOutgolfer That's probably because APL must be restarted after patching. Windows sometimes forces a restart when updating critical parts of itself.
 
@Adám no, I don't think so, although sometimes it begs you for a restart constantly
 
@wizzwizz4 Sure there is. You can declare a method overridable with :Access Public Overridable
 
7:49 PM
@Adám I mean with the constructors and destructors.
But that's good to know.
 
@wizzwizz4 Constructors doesn't make sense. How can the instance override the base constructor before it has been instantiated? If you don't want that constructor, you're using the wrong base class.
 
@EriktheOutgolfer What version are you on? It's forced since Windows 10 (and has done before that but then they turned it off).
@Adám Good point. I suppose the same logic holds for the destructor.
So can you call another base class's methods on your class?
 
@wizzwizz4 Also, there are two ways to override. If the derived class has an identically named method, it overrides the base class method for the derived class only, but if the identically named method is :Access Public Override, then even if code in the base class calls that method, it is redirected to the derived class one.
@wizzwizz4 "on your class"?
 
@Adám I meant "instance".
 
@wizzwizz4 You can call any public methods from anywhere. If they are in a base class, they of course need to be :Access public shared.
 
7:56 PM
@Adám Can you call them as if the base class of your instance was the base class defining them?
Like Python's str.join (base.method) having a pseudoparameter at the beginning giving a reference to the object.
 
@wizzwizz4 You can put such common methods in a namespace, and then write :Include MyNamespace. This allows calling that namespace's methods as if they were in the base class. This way, multiple classes can share a set of methods, as if they had multiple inheritance.
Thank you for participating!
… but feel free to hang around and ask questions. Now and any time.
@Pavel Sorry we didn't get around to that this week. However, it does fit better into my planned subject for next week.
 
@Adám That's really clever.
However, can you include a class's "hidden" namespace in any way?
 
@wizzwizz4 What is a class's "hidden" namespace?
 
@Adám The one containing the methods.
I assume it's mirrored in some way for that really hard feature.
 
@wizzwizz4 Every class is just another namespace, but with some restrictions and added features.
@wizzwizz4 No, you can't :Include SomeClass. Pushing silliness again? ;-)
 
8:06 PM
@Adám No, I'm trying to do a serious thing.
The other time I was trying seriously to do a stupid thing, which is slightly different. :-D
@Adám But if they're just namespaces...
Or is that one of the restrictions?
 
@wizzwizz4 Sorry then. I'm not understanding why you would want to include methods from one base class in another. You could just have a base-base class which implements the shared methods for all the classes that need them, no?
 
@Adám Yes, if I were designing the whole codebase.
I'm assuming you can import modules.
Or libraries.
Or namespaces from files.
 
@wizzwizz4 So you're trying to merge two 3rd party classes. Sounds like recipe for name clashes.
@wizzwizz4 ⎕FIX 'file://path/filename.ext' will do that, and works for classes (and more) too.
 
@Adám I'm trying to ducktype and use methods for another class that should cope well with ducktyping.
@Adám Is that just the thing that's marked as Code on TIO (don't remember the feature name)?
 
@wizzwizz4 The TIO wrapper uses ⎕FIX, yes. But that's an unusual interface to APL. In fact, Header+Code+Footer gets wrapped in :Namespace, :EndNamespace and then that file gets ⎕FIXed, and then the members of that anonymous namespace get copied into #.
@wizzwizz4 Ah, I see. Well, as I said, you can call public methods across from classes, but you'd have to use explicit references to the target class. You could possibly also explicitly copy the members from one class to another. I've not tried doing that, but hang on…
 
8:32 PM
@Adám random question: why the hell does this work? does APLs inverting just brute force values?
 
@dzaima Yeah, I think it eventually falls back to a numeric solver if the function is invertible but the internal rules don't suffice to give an exact result.
@dzaima Btw, you do know you can use constants in trains, right?
 
@Adám ah okay, but it feels like that this should work fine then too
 
@Adám uh, that's exactly what I arrived to too
 
@Adám Don't leave me hanging! *+1 quotation points*
 
@Adám yeah, that was so ugly because transpiling to that is hard :p
 
8:36 PM
@wizzwizz4 Sorry, got distracted.
@dzaima This illustrates the problem clearer. I'll submit a bug report.
 
@Adám Bugs are more important. :-)
 
@wizzwizz4 I'd say that helping doing useful stuff is more important than adding support for horrible code that shouldn't be used anywhere :p
or maybe I'm misunderstanding how much does Dyalog want to support ⍣¯1 :p
 
@dzaima Mine's bad too! :-p
 
8:51 PM
45 mins ago, by wizzwizz4
@Adám No, I'm trying to do a serious thing.
 
@dzaima Logged as issue 15512.
 
@Adám does that number give anything to me?
 
@dzaima You may see it one day in a list of fixed bugs.
 
@Adám ah okay.
 
@dzaima Emphasis on trying.
It's still a bad thing to do, despite being necessary sometimes.
 
9:01 PM
@wizzwizz4 Hey, I'm the one who's trying. So far all my attempts at fooling APL into doing this have failed, but I have one more idea.
 
@Adám Thanks, by the way.
I didn't think it'd be possible, really.
 
@wizzwizz4 Woo, I found a (very hacky) way. Making TIO link.
 
@Adám Well done! :-D
 
@wizzwizz4 Here you go!
@wizzwizz4 Let me know if there's anything in ^ I need to explain.
 
@Adám How are methods evaluated?
 
9:14 PM
@wizzwizz4 What? They're just… called. Although if you can capture the "value" of a non-niladic function by using its name without giving it any argument(s).
 
@Adám I phrased that really badly.
 
Btw, you may want to change the 9s to 8s to avoid copying the entire Cl1 into Cl2.
 
@Adám I don't understand the copying thing, but I'd assume that that's what it did from looking at it.
It's copying internal namespaces, so that's the only thing it could do.
@Adám How will that work?
 
@wizzwizz4 No, it is copying all visible identifiers. But a class can see itself, so when it looks at the symbol table inside Cl1 it also sees Cl1. But it is easy to code around that.
 
@Adám Visible identifiers... that's hackish.
 
9:19 PM
@wizzwizz4 OK, you want me to explain {⍎⍵,'←##.Cl1.',⍵}¨##.Cl1.⎕NL-⍳9 step by step?
@wizzwizz4 Told ya.
 
... Of course it's hackish! Idon't know why I said that.
@Adám Yes please
 
@wizzwizz4 ⎕NL-⍳9 gives the Name List of item types 1 through 9. That's all of them.
##.Cl1. means ⎕NL is being called inside the Cl1 which is inside the Cl2's parent namespace.
 
@Adám Item types... I feel like I should know this. Brb.
 
@wizzwizz4 Check out lesson 14.
 
@Adám Thanks.
 
9:25 PM
Now we have a list of names, we call the anonymous function {} on each ¨ name.
⍵,'←##.Cl1.',⍵ simply concatenates the name ( is right arg) with an assignment arrow and a reference to the name inside Cl1.
Finally, evaluates that as an APL expression. Assignments done inside are not local to the dfn (the function in braces), so they instead populate the current namespace, i.e. Cl2, which is what we wanted.
@wizzwizz4 Clear?
 
@Adám Yes.
Eval isn't safe to let unprivileged access, is it?
 
@wizzwizz4 Great, that makes me happy to hear. Again, this is super hacky, and I would strongly discourage doing this.
 
@Adám But it can be used to manually import individual ones, correct?
 
@wizzwizz4 No. And in fact, what I did there was dangerous. If any function in Cl1 had been niladic, then evaluating them would have called them…
 
@Adám Ouch.
So, never ever use it?
 
9:32 PM
@wizzwizz4 Yeah. But a better (though more labour intensive) way to do this, would be to get the representation of each function in the target class with ⎕NR and then establish it here with ⎕FX. There is a difference though: This way will actually create new functions here, while the assignment method will create references.
@wizzwizz4 ^ is a safe method though. But of course, since you want to access (and run, I suppose) code from a 3rd party class, you must trust them not to include malicious code.
 
@Adám What do you mean by labour-intensive?
 
@wizzwizz4 It isn't a simple catch-all assignment. For each member, you'd have to find out what type it is. Variables would need copying using assignment to the same name over here. Functions and Operators would need ⎕FX ⎕NR, scripted objects would need ⎕FIX ⎕SRC and unscripted objects would need name ⎕NS ref.
 

« first day (392 days earlier)      last day (2265 days later) »