bug-apl
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-apl] D-fn binding leackage, Nested d-fns


From: Daniel H. Leidisch
Subject: Re: [Bug-apl] D-fn binding leackage, Nested d-fns
Date: Mon, 03 Mar 2014 15:55:22 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux)

Hello Jürgen!

Juergen Sauermann
<address@hidden> 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]