<https://suhr.github.io/wcpl/intro.html> additiona...
# linking-together
g
k
But concatenative programming is not perfect either. As shown in Why Concatenative Programming Matters, a simple expression
f(x, y, z) = x^2 + y^2 - abs(y)
becomes
drop dup dup × swap abs rot3 dup × swap − +
But why can't you just write
drop dup (^2) + (^2) - abs
instead?
Do you have any sense of how that last program can be anywhere near correct?
g
I found these articles about five minutes before throwing them in here so I'm still working through them (ie: absolutely not)
k
Yeah cool. Keep me posted. I'm always trying to figure out what a seemingly wrong statement may be right about.
g
but I think it's something to do with the idea of distributing the square operations over the top two items of the stack using a slightly different semantics
almost like assigning them to x and y variables without having to name them
like a temporary sub-stack(?) that the popped arguments land on (unsure if clear, had to do dinner between first skim and now so my head isn't back in it)
👍 1
f
it's doing something like
dip
from Factor yeah like,
(^2) + (^2)
is sugar for
(id^2),(id^2) +
, where
3 4 f,g
applies f to 3 and g to 4(assuming they're both arity 1)
💡 2
k
It's really weird to see syntax sugar not enclosed together. My mental model was that the
(^2)
couldn't possibly have anything to do with the
+
at parse time. Doesn't this give up a lot of the benefits of concatenative programming? Reading up on Factor's
dip
now.
f
so for the full statement the reduction is something like
Copy code
x y z | drop dup (^2) + (^2) - abs
x y | dup (^2) + (^2) - abs
x y y | (^2) + (^2) - abs
x y y | ((^2) + (^2)),abs -
x y | ((^2) + (^2)) (y | abs) -
x y | ((^2),(^2) +) (y | abs) -
x y | (^2),(^2) + (y | abs) -
x (^2) (y | ^2) + (y | abs) -
(x | ^2) (y | ^2) + (y | abs) -
(note
,
binds tighter than
)
it's doing a mix of concatenative and infix syntax yup
k
Ok, at least
dip
has the decency to accept a quotation. This is just bonkers. Dismissing.
f
I suppose
a,b
in turn is sugar for
{a} {b} ,
fair or rather, this is a language defined on functions rather than values - but at least
a,b,c
is a monoid 😶
g
agree that the explanation using infix at all is super confusing but I'd chalk it up to someone super new to the paradigm (part of my interest is how people not fully indoctrinated into a paradigm seek to improve it) rather than proposing a real weird compromise
this conversation has caused me to encounter factor's concept of fry syntax which I think is really cool for anyone observing: https://docs.factorcode.org/content/article-fry.html
k
Indeed. That is quite nice.
1
g
factor has always seemed like a fractally insightful language to me but I feel like I'm missing the guided tour
👍 1
w
Once every while, I get on a concatenative kick... so I have opinions. Concatenative languages shine when you sort of have one topic in mind. This makes
f(x, y, z)
naturally awkward. (Perhaps if you could concatenate along multiple paths... spoiler, this leads somewhere.) Instead focus on the cool bits: (1) quotation feels comfy rather than mysterious, which comes from (2) you can basically factor out any sequence of words as a new word.
g
would love to see a multiple path example!
w
With multiple paths, you end up with something more like a dataflow language. Take the original example
drop dup dup × swap abs rot3 dup × swap − +
. Instead of stack twiddling, use can use geometry:
drop
becomes a path the goes away,
dup
is a branch, `swap`and
rot3
reorder things.
g
interesting! reminding me of reactive programming in a way I'm not sure how to describe
k
@wtaysom you aren't suggesting boxes and arrows, are you? 🙂 All combinatorial programs are dataflow in essence. But the eternal question is how you represent them and work with them. And whether it scales.
w
Instead of wires, names can do the same work
x x * y y * + y abs -
. 😮
Store the intermediates to get something like:
Copy code
x x * → x2
y y * → y2
x2 y2 + → x2py2
y abs → yy
x2py2 yy -
Now you end up close to A-normal form. Of course, the concatenative feel is lost somewhere along the way 😏.
k
Yeah. This is an interesting conversation, because we're both saying obvious things. And I know they're obvious to you, and you know they're obvious to me. Yes, names and the stack are complementary. Some things are easier on one end of the spectrum, some on the other. Most don't care. Concatenative languages already have names: function names. The whole point of going concatenative is extremely flexible function boundaries. So I'm not sure this is a problem worth attacking. Even Factor's
locals
feel like something to be used very sparingly. Better to go with the grain of the platform you chose. Yes, some things are hard to write clearly. Then we do what we do in any language: wrap it in a function, slap on a comment and shove it under the carpet. And if you find yourself doing this a lot, look around. You're probably working in a large team inheriting an old codebase you aren't empowered to make radical changes to. In which case a new language or new syntax ideas aren't going to help you.