Open OlegAlexander opened 2 years ago
I started with an attempt at the getting started tutorial
Thank you, that's very helpful!
The first thing I did was redefine . == °
so it's easier to type in the composition operator. And now the example becomes:
sum . ((id * id) aa) . iota . 10
385
Hopefully the .
isn't already bound to something else :)
Edit: And now I see in the reference pdf that I can just use the letter o
for composition. Never mind!
Partial conversion of quickinfo.pdf to English.
Is the ° circle symbol hard to reach on English keyboard?
Yes, the ° symbol is not available on the US keyboard. I've been copying and pasting it from your code examples.
Partial conversion of document.pdf to English. And a few English additions in reference.pdf.
the "loop fusion" example of https://twitter.com/TheOlegarchy/status/1533976236732522498 looks like
avgb == / ° fold ° 'sumLength, (0;0;), id, // ([0] / [1]) = / ° [0],[1],
// sumLength ° (sumAcc,lenAcc,),x,
sumLength == ([1]+[0]°[0]),(1+[1]°[0]),
// fold ° 'expr,initdata,list,
fold == (isatom°[2]) -> [1] ; fold ° [0],([0] app [1] ee head°[2]),(tail°[2]),
in PF
Awesome! Thanks! I just tried it. It's nice to see a more advanced PF example like this.
I was going to ask you, does PF have where clauses like the FL spec? See section 5. https://theory.stanford.edu/~aiken/publications/trs/RJ7100.pdf
Thanks for the hint. Unfortunately, there is no syntactic where clause in Pointfrip. To use local identifiers there are tables/dicts in Pointfrip. With this one could try to build something like clauses. Maybe like this:
((#f app 1,2,3,)+(#g app 1,2,3,)) ° (f:='(head°tail)) ° (g:='(head°tail°tail))
But there is no cyclic reference to other definitions. Pointfrip only works with instance variables. So it is free of lambda variables as in wikipedia. Backus initially spoke out against lambda variables, as here, but then introduced them to FL in order to be able to add new functional forms. The definition of new functional forms also worked in Pointfrip without lambda variables. What do you think, can one do without lambda variables or not?
My understanding is that as long as the language has a sufficient number of combinators and allows recursion, then lambda variables are not necessary. There is a good article about concatenative languages. Read the section called The Dark Side for an example of when you might want lambdas. I believe the Factor language has lambdas but they are rarely used. I don't think PF needs lambdas.
But the where clause would be nice because it allows you to nest definitions. This is useful for two reasons. First, it allows you to reuse def names. Second, and more importantly, a program using where clauses has less surface area. That is, when defs can be nested, the reader has more local context about where a def is used. In long point-free programs, this can be a big boost to readability.
But the where clause would be nice because it allows you to nest definitions. This is useful for two reasons. First, it allows you to reuse def names. Second, and more importantly, a program using where clauses has less surface area. That is, when defs can be nested, the reader has more local context about where a def is used. In long point-free programs, this can be a big boost to readability.
You're right.
Since Pointfrip is a hybrid, one could use classes for the programming at large. I mean for reusing def names:
main ° (prog :: 1;2;3;) // the prog object
f == [f] fn fail
g == [g] fn fail
inc == [inc] fn fail
sqr == [sqr] fn fail
main == [main] fn fail
prog == .. { list // the prog class
[f] == g ° tail
[g] == head dip
[inc] == (id + 1) dip
[sqr] == (id * id) dip
[main] == sqr ° inc ° f
}
The names f
to main
for the selectors can then also be used for other classes.
Should I take a leave of absence from Google?
I don't understand the question. Do you work at Google? Could you elaborate?
Maybe the English wording sounds a bit strange because I used google translate to translate from German to English.
Yes, that's what I thought :)
I think this quote is taken out of context. The full interview PDF is here and the video is here. It's hard to say exactly why Backus thought his work was ultimately unsuccessful because he didn't go into much detail. My guess is that he meant he couldn't get IO to work or that he couldn't model time with expressions.
I'm amazed at how deep you've delved into this topic. I could learn something from you.
With the interesting links you could create a great collection of links, for example.
That is a great list! The "Function Level Programming and the FL Language" video is one of my favorites. Here are a few more links. The Algebraic Programming material is very hard for me, but hopefully one day I'll be able to fully understand it :)
The Algebraic Programming material is very hard for me, but hopefully one day I'll be able to fully understand it
John Backus wanted to fight the complexity, example
I just tried to modify the README directly but it didn't work. It wanted me to create a pull request. Maybe giving members direct edit permission is a paid feature? Not sure.
Try that again.
Yes, it works now! Thank you!
I just watched part of the FL video. Why didn't this man get an engineering chance for his FL?
Sorry, what do you mean by "engineering chance"?
He wanted to make programming with FL an engineering discipline. (min. 9:00)
I thought about my own technique for side effects, but found out later that it is the monadic technique. I then extended them with algebraic effects in the class-oriented way (io-driver). With the continuations >>
it looks like a pipeline. it
then always returns the effect result. It passes the instance variables through every continuation.
((#draco loadtext)°(draco:=corepath & "drache.pf") eff 'io)>>(it showinfo)>>(#draco run)>>()
If the example doesn't run, you can also use "drache.txt"
.
(I may have made a mistake with the monad stack because there is no word return
.)
I thought the IO monad was only needed in a lazy evaluation language, where the monad is used to force the order of evaluation. In a strict (eager) evaluation language the IO monad isn't necessary. Is PF strict or lazy by default?
So that these rules and laws can also be used in IT - this is the reason for the use of FP - referential transparency must be maintained. No side effects may occur within the referential transparency. For a side effect to happen, a break or termination must occur. A monad is a termination given a continuation, which also results in sequencing. Pointfrip doesn't have a lazy evaluation, but I tried it with this one.
To the mission, a stack language like Joy is very flexible, but tends towards obfuscation (last point) and has problematic exception handling because of the stack.
I found this on Twitter: What do you think, is programming with lambdas better or without? (LtU Comment)
My conclusion is that programming with lambdas is better. The point free style sometimes works in higher order functions, but should not be used at the top level.
Should one only recommend the film or should the Pointfrip archive continue to exist so that Backus FP interested parties can gain experience with a 100% point-free style in order to be able to understand the failure. So that this development of the PF interpreter is not repeated. ?
Of course, the Pointfrip archive should continue to exist! Do you agree with my conclusion that a 100% point-free style is not a viable way to write programs? And that it can never be made viable, even with the "right" combinators, like construction?
Do you agree with my conclusion that a 100% point-free style is not a viable way to write programs? And that it can never be made viable, even with the "right" combinators, like construction?
Unfortunately, I lack the right feeling and experience for this. I think the point behind PF and FP is that you can rearrange* equations like you do in math. Whether lambdas are a hindrance for the purpose is just speculation for me. Should be examined more closely.
Others have had problems with Backus' suggestion too, like here. But it was mentioned that the creators of Haskell are smart people and they use lambdas.
(*) Example from POPL, rules like that: α (f ° g) = (α f) ° (α g)
Originally I thought the same thing--that point-free code is ideal for algebraic reasoning and that lambdas somehow interfere with this. But later I realized that algebraic reasoning could be done with lambda also. In fact, you can gradually eliminate one arg at a time with manual eta-reduction. I love this stack overflow answer by Jon Purdy where he recommends a partially point-free style: https://stackoverflow.com/a/47042937/3512820
Is working with Pointfrip a madness?
Honestly, I haven't done that much coding in Pointfrip specifically. But theoretically, any 100% point-free or concatenative or stack-based language is hard to program in, even with a lot of practice.
Without wanting to influence you, Backus has also experimented with lambdas. The script has been available for free for the last few months: Function Level Programs as Mathematical Objects
Summary
Nice paper! Haven't read that one before. He mentions that in Lisp programming with lambdas usually has more than one parameter. However, in OCaml/F#/Haskell all functions are curried by default which means that let add x y = x + y
is just syntax sugar for let add = fun x -> fun y -> (+) x y
and this can be eta-reduced to let add = (+)
. Currying satisfies his requirement that every function takes only a single parameter and makes it possible to do equational reasoning even in the presence of lambdas.
However, my disenchantment with the point-free style is not about lambdas vs no lambdas. It's about brevity and clarity. I originally thought that if a little bit of point-free style is shorter and clearer then more point-free style would be even shorter and even clearer. However, it turned out that point-free style is like salt--to be used only in moderation.
No matter how hard I tried--and you know I tried very hard--I kept running into examples where the point-free style was longer and less readable than the pointful style. The basic problem is that the point-free style is inherently stack-like, so any time the data flow becomes even a little bit non-linear--where a computed value needs to be used in several places later--the code becomes very hard to read and write, even with the "right" combinators from Backus!
I realized I was wasting my time trying to "be the compiler"--the compiler already turns pointful code into stack commands for me and makes many optimizations on top of that. The benefits of algebraic reasoning promised by the point-free style do not outweigh the difficulties of trying to "be the compiler".
So you see, my conclusion is a practical one--the point-free style is good in moderation, like salt. And it doesn't mean I have any less respect for John Backus!
Idea of a restricted where-clause. If you define the following where combinator:
where == (top°term) app prop°arg,'_it,(top°pop°term),
You could then design this working function that way:
addsqinc == (it + #square app #inc app it)
where ( (id*id) square
(id+1) inc )
You would have to change the syntax for the parenthesis and then you would have this picture:
addsqinc == (it + #square app #inc app it)
where ( square == id*id
inc == id+1 )
But it is only an idea for a restricted clause. You can't do recursion and other things. And it would be limited to just using the instance variables.
Dear @metazip, thank you for creating Pointfrip! Could you please add more documentation and a getting started tutorial in English? I can see that the reference PDF is in English but the other documents are in German. Thank you!