Hello Jürgen! Juergen Sauermann <juergen.sauerm...@t-online.de> writes:
> I would like to explain my point of view regarding Lambdas aka. > D-funs. Thanks. I should mention that I am an APL beginner, so my answer will draw from my experiences with other languages, especially functional ones (in the functions as first class objects sense, not in the strict sense) like Common Lisp, Scheme, Clojure, Haskell and so on. Also, of course I am not in a position to demand anything from you, especially while I am not able to help you implement it. (At least for now – That might change once I have more time on my hands.) > Initially I considered them as not needed; they are not defined in the > APL standard and the rules related to them seem to be rather unclear. > > After seeing some requests to support them I started thinking about this > and I figured that they could be somewhat elegant in particular when > used with the EACH operator. I would not approach this design decision by looking at particular usage examples where the feature might come in handy, or conceive it as a mere syntactic convenience, but think of it more as a decision about supporting a more functional style in general. As far as the standard is concerned, you are of course absolutely correct. Adding support for anonymous functions would go beyond the it, and enable another way of approaching problems and expressing one's thoughts in code. So the question is: Does this new way of approaching problems fit in the general conceptual framework of the language or not? Would it feel bolted on, or integrate nicely? As far as I can say, having not much experience with APL, the language already does have a pretty functional feel to it (operators, i.e. higher order functions, thinking in terms of data flow etc.), and integrating proper anonymous functions would fit in very nicely. I dare to say that I think the father of the language would agree with me, taking a look at the direction he took in writings like Rationalized APL and especially later with the emphasis of functional and especially tacit programming in J. (I wish I could stand the look of it.) > There are still things related to lambdas that I don't like at all because I > believe that they obscure the APL language more than they help. > > For example, IMHO the following is definitely unfortunate (even though > possibly convenient and supported in some APL interpreters): > > - having different binding rules in lambdas than in normal APL functions, > - "guards" like :IF in lambdas > - probably more... I will try restricting my answer to anonymous functions in general. Investigating whether your belief about the features you mention is justified and objectively true or just a matter of taste is not an easy task, and would require another dedicated discussion. Let me just say that, from what I have seen so far, I can symphatize with the opinion of some (many?) APLers, that the structured programming constructs provided by many implementations do feel somehow bolted on, and can lead to code that feels unidiomatic (think curly brace language with APL characters), especially when more idiomatic vectorized solutions are obvious. Still, structured programming has prevailed, and were some hypothetical form of APL just being invented today, it is in my opinion pretty safe to assume that there would be some form of support for it instead of or additional to the computed goto. > Nested lambdas are sort of on the border - I could look into this if you > have a convincing example. A good specification of lambdas would also help. > In the meantime you can work around this by eg: > > A←{⍵} ◊ {⍵+A 1}1 As mentioned above, I do not think that looking for particular usage examples is the way to approach this, and I will not try to provide them. This example was of course just a minimal working example to reproduce what I thought of as a bug. There is almost always a way to express or translate a solution from one paradigm, from one language or a version having a particular feature to another. At least to the point of making it work. Just imagine a language without the means of applying functions to numbers directly. To use a number, you would first have to bind it and then use the bound variable. The answer to the question how to express: 1 + 2 is obvious: x ← 1 ◊ y ← 2 ◊ x + y One might even imagine the hypothetical proponent of the language without "anonymous numbers" arguing that this is much more understandable and explicit. He never felt the need for the fancy new way to do things, and it seems pretty un-language-x-y to him anyway. Now, you might find this example very contreived and exaggerated, but it is actually pretty much to the point and mirrors the gist of similar discussions like structured programming vs. goto, functional vs. OOP, explicit loops vs. vectorization etc. Why should a function not be a first class value in a language that already feels very functional? Why restrict nesting? Sure, there are ways around such limitations, but should a tool of thought not avoid them in the first place? But to get back to more conctrete arguments: In my opinion, assuming that anonymous functions are there to stay, not allowing their nesting would seem like a rather ad-hoc and arbitrary limitation to me. You mentioned that the rules relating to anonymous functions were unclear. That may be true, as far as APL implementations are concerned (the three I use allow nesting and bind locally), but one could do worse than orienting oneself at the untyped lambda calculus, and the use of anonymous functions in other languages. All of them I have ever used allow nesting, and all of them make their bindings local by default. (All the modern ones I know about lexically – even Emacs Lisp allows this nowadays.) > In GNU APL lambdas create normal user-defined functions and normally > follow their rules. That's why x becomes visible in your example, and > IMHO this makes > more sense than hiding x in lambdas but not in user-defined functions. There is, as far as I can tell, general consensus that lexical binding and local by default are how things should be done – at least by default. And since anonymous functions are a new feature, they are a good opportunity to overcome bad decisions of the past. Besides, traditional functions have means of declaring variables local. Anonymous functions, lacking this, should probably use the more sane default. I am sorry that my reply is so long, and I will stop here. To summarize my major points: - Anonymous functions are not just a syntactic convenience - Programming in a functional style and APL go well together - Not allowing nesting is an arbitrary limitation - Local lexical bindings are the sane default I understand that you, as an implementor, are probably approached by several people who would like to see their favorite feature implemented. This decision, however, is not just about someone's favorite pet operator, but about enabling expression in a more functional style in general. If you want to implement the standard, and nothing more, that is fine. If you want to go further, this would, in my opinion, be a direction that fits the language, does not feel bolted on if done right, and agree with the work of its creator in his later years. Personally, I would not even stop there, but also include support for tacit programming. As I said above, take this cum grano salis – I do not know much about APL. Thanks again for your work! Regards, Daniel