An Overlooked Paradigm in Functional Programming

John Nowak — 2010-01-29 04:07:15

Paper:
http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/ICSOFT.2009.pdf

See also:
http://denkspuren.blogspot.com/2010/01/factor-heilbronn-university.html

chris glur — 2010-01-30 21:18:15

I think/hope denkspuren.blogspot approaches from the human cognition angle,
because that's where productivety increases will come from.

I'm pushing my topic in here, while I've got a connection to the cat-list,
because the Chinese [or rain] has screwed my gmail [which is tied to the
cat-list]

=== joy in the BIG ===

The following extract from joy-docos is informative and fun:======
Consider the following recursive definition and use of the
factorial function in a (fantasy) functional language:
LET factorial(n) = if n = 0 then 1 else n * factorial(n - 1)
----------------> So this 1-lines natural-code is obfiscated to joy's ...
This is the program:
1 5
2 [ [pop 0 =]
3 [pop pop 1]
4 [ [dup 1 -] dip
5 dip i
6 * ]
7 ifte ]
8 dup i
============== end of joy-docos extract==========
But really, it's intolerable to have to do stack-shuffling,
when the computer/compiler should be doing that for me.

The absurdity of MANUALLY translating the 1-line pseudocode
to joy, when a simple/immediate algol-like compilation is
available tells much?

OTOH joy-like seems appropriate at the higher-level: using
routines/utilities/functions which have been programmed in
'proper' language/s where the compiler has done the
stack-shuffling.

IMO an example of a good task for joy-like-capabilities
is "list the file-IDs and lines of all the files newer than
n days, in this dir-tree which contain string <string>".

'Linux-pipes' lists the files [but not the lines] by:
find ./ -ctime -<n> -exec grep -l "<string>" {} \;
where apparently:
find ./ -ctime -3
would give a list of fileID's of files younger than 3 days.
and then
grep -l "<string>" {}
lists [by filtering] only the ones containing "<string>".

From a joy-perspective -- AFAICS the first step maps:
stack/pair(tree-path, daysCount) -> stack/tuple(FileSet/list)
and then the next stage does:
stack/tuple(FileSet/list, <string>) -> stack/tuple(FileSet/list).

AFAICS this task fits naturally into a data-flow-via-stacks
type of process. So joy-like is very appropriate?
But I'm thinking that the lower level utilities should
NOT be joy-like.

What ideas/documentation exist on using a joy-like
language which would call functions from a library?
===================

Is it viable to make a joy framework to handle the basic
control-structures of: IfThenElse, WhileDo; where you'd
just fill-in the eg.: predicate, ThenStmt, ElseStmt; for
the IfThenElse, and be able to concentrate on the
data-structures that are being manipulated and passed through
the various stages?

Or perhaps there's no advantage of going via joy?

Unix-via-piping is a powerfull labour saver, even though the utilities
are a patchwork, rather than a formally designed structure like joy.
So I'm wondering what could happen if the 'library of utilities' was
designed formally to match [in a unified consistent way] the joy-like
superstructure controller.

I'd like to see a cost-benefit-analysis of the attributes of joy-like:--
+ formal code manipulation could possibly lead to [auto] verification of specs.
- manual stack shuffling needed == BIG minus!!
+ can do higher-order functions like lisp/scheme, with a potentially more
natural syntax.
? <fill in>
?<fill in>

== Chris Glur.



On 1/29/10, John Nowak <john@...> wrote:
> Paper:
> http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/ICSOFT.2009.pdf
>
> See also:
> http://denkspuren.blogspot.com/2010/01/factor-heilbronn-university.html
>
>

John Nowak — 2010-01-30 23:13:10

On Jan 30, 2010, at 4:18 PM, chris glur wrote:

> The following extract from joy-docos is informative and fun:======
> Consider the following recursive definition and use of the
> factorial function in a (fantasy) functional language:
> LET factorial(n) = if n = 0 then 1 else n * factorial(n - 1)
> ----------------> So this 1-lines natural-code is obfiscated to
> joy's ...
> This is the program:
> 1 5
> 2 [ [pop 0 =]
> 3 [pop pop 1]
> 4 [ [dup 1 -] dip
> 5 dip i
> 6 * ]
> 7 ifte ]
> 8 dup i
>
> The absurdity of MANUALLY translating the 1-line pseudocode
> to joy, when a simple/immediate algol-like compilation is
> available tells much?

That's not even a remotely fair translation as it's not recursive like
the example. The straight-forward recursive function is as such:

fact = [zero?] [pop 1] [dup 1 - fact *] ifte

Or, alternatively, I'd rather write:

fact = [zero?] [pop 1] [[] [1 -] bi fact *] ifte

There's only one "shuffle" word in the entire thing; 'pop'. 'bi' makes
it explicit that you're deriving two values from one value given the
identity function and the predecessor function. The rest are the same
things you'd see in the mathematical definition.

What concatenative languages do you let you do well is write an
efficient iterative version without meaningless names for accumulator
variables:

fact = dup [1 - dup 1 >] [[*] keep] while pop

But, more likely, you're just using the proper combinator anyway:

fact = [1] [*] primrec

Or, in a more Haskell-like style:

fact = 1 enum-to-from 1 [*] fold

Or:

fact = 1 enum-to-from product

-jn

John Nowak — 2010-01-30 23:37:52

On Jan 30, 2010, at 6:13 PM, John Nowak wrote:

> Or, alternatively, I'd rather write:
>
> fact = [zero?] [pop 1] [[] [1 -] bi fact *] ifte

For what it's worth, this is essentially identical to the FP version:

fact = zero? -> ~1; * . <id, fact . pred>

The only real difference is that constant (~) is used instead of pop
and that it's made explicit that 'fact' is applied only to the result
of 'pred'. The latter is an advantage, although it's one that goes
away when the stack-based version is written out visually (which is
something I'll be harassing you all with soon enough).

You can do the same thing in Haskell of course:

bi f g x = (f x, g x)
ifte c f g x = if c x then f x else g x
pred = flip (-) 1
fact = ifte ((==) 0) (const 1) (uncurry (*) . bi id (fact . pred))

... but it's not amazingly pretty.

- jn

William Tanksley, Jr — 2010-01-31 01:06:32

John Nowak <john@...> wrote:

> of 'pred'. The latter is an advantage, although it's one that goes
> away when the stack-based version is written out visually (which is
> something I'll be harassing you all with soon enough).
>

Ah! This sounds promising.

- jn


-Wm


[Non-text portions of this message have been removed]

chris glur — 2010-01-31 08:28:59

> The absurdity of MANUALLY translating the 1-line pseudocode
> to joy, when a simple/immediate algol-like compilation is
> available tells much?
]That's not even a remotely fair translation as it's not recursive like
]the example. The straight-forward recursive function is as such:

I MIGHT analyse your code in the future, but:
I merely PASTED the joy-author's ample 1-line pseudocode and HIS
joy version.

I won't follow your NEW argument about Haskell etc. on the going
nowhere [because it's fun] journey. Can't someone answer MY question/s?
I've got a specific goal and am NOT just playing 'look ma no hands' !


On 1/31/10, William Tanksley, Jr <wtanksleyjr@...> wrote:
> John Nowak <john@...> wrote:
>
>> of 'pred'. The latter is an advantage, although it's one that goes
>> away when the stack-based version is written out visually (which is
>> something I'll be harassing you all with soon enough).
>>
>
> Ah! This sounds promising.
>
> - jn
>
>
> -Wm
>
>
> [Non-text portions of this message have been removed]
>
>

William Tanksley, Jr — 2010-01-31 19:09:35

chris glur <crglur@...> wrote:

> > The absurdity of MANUALLY translating the 1-line pseudocode
> > to joy, when a simple/immediate algol-like compilation is
> > available tells much?
> ]That's not even a remotely fair translation as it's not recursive like
> ]the example. The straight-forward recursive function is as such:
> I MIGHT analyse your code in the future, but:
> I merely PASTED the joy-author's ample 1-line pseudocode and HIS
> joy version.
>

That's a lousy excuse for refusing to accept an answer to your problem. Just
because you did no research doesn't mean there's no answer.

I won't follow your NEW argument about Haskell etc. on the going
> nowhere [because it's fun] journey. Can't someone answer MY question/s?
> I've got a specific goal and am NOT just playing 'look ma no hands' !


Your specific goal *seems* to be to program in a low-level non-concatenative
language and a high-level concatenative language. Since that goal is
reversed from anyone else's I've ever met, I'm mildly interested -- I like
contrarian thinking (that's why I'm studying concatenative languages).

It so happens that there's plenty of solutions to your specific problem,
even though they don't match your specific question.

-Wm


[Non-text portions of this message have been removed]

chris glur — 2010-02-01 13:31:30

> That's a lousy excuse for refusing to accept an answer to
> your problem. Just because you did no research doesn't mean
> there's no answer.

We seem to have lost each other completely ?
The author defined the factorial function in one short line of near english;
and then gave the multi-step joy interpretation.
Since my aim is to REDUCE mental load, it's irrelevant WHAT the finer
considerations of his joy-translation may be, because I don't want
to transform conceptual simplicity into complexity.
For all I know his joy-translation may have error/s, but that's
irrelevant. I merely pasted it to show how he's transformed simplicity
into complexity.

> Your specific goal *seems* to be to program in a low-level
> non-concatenative language and a high-level concatenative
> language. Since that goal is reversed from anyone else's I've
> ever met, I'm mildly interested -- I like contrarian thinking
> (that's why I'm studying concatenative languages).

I'll give a real-life example:
for part of a task, I needed the list of pid/S with the open file
'on mc'.
An existing function called lsof shows a zillion lines, typically:-
mc 3499 root txt REG 3,14 519624 375343 /usr/bin/mc

Since all I want is [each]: (3499, /usr/bin/mc) pair, I merely pass it
[NB the use of "it" to lambda-like eliminate IDs] through filters which:
1. show only the lines which have "/mc"
2 show only the part of the lines with the 2nd field [the 3499] and the
last field.

So there are 3 'library available' BIG functions:
= lsof [list open files]
= grep "/mc" [ but show only lines with "/mc"]
= cut <something> [but show only the wanted part of the lines]

I don't WANT to know how these, no doubt complex, functions work.
They are constructed by a 'proper language' - as you call "low level".
And the the cat-like just does:
lsof | grep "/mc" | cut <as required>

So altho' cat-like is no good for the real heavy-lifting, it's good
to chain/pipe existing functions together to do the hi-level tasks.

== Chris Glur.


On 1/31/10, William Tanksley, Jr <wtanksleyjr@...> wrote:
> chris glur <crglur@...> wrote:
>
>> > The absurdity of MANUALLY translating the 1-line pseudocode
>> > to joy, when a simple/immediate algol-like compilation is
>> > available tells much?
>> ]That's not even a remotely fair translation as it's not recursive like
>> ]the example. The straight-forward recursive function is as such:
>> I MIGHT analyse your code in the future, but:
>> I merely PASTED the joy-author's ample 1-line pseudocode and HIS
>> joy version.
>>
>
> That's a lousy excuse for refusing to accept an answer to your problem. Just
> because you did no research doesn't mean there's no answer.
>
> I won't follow your NEW argument about Haskell etc. on the going
>> nowhere [because it's fun] journey. Can't someone answer MY question/s?
>> I've got a specific goal and am NOT just playing 'look ma no hands' !
>
>
> Your specific goal *seems* to be to program in a low-level non-concatenative
> language and a high-level concatenative language. Since that goal is
> reversed from anyone else's I've ever met, I'm mildly interested -- I like
> contrarian thinking (that's why I'm studying concatenative languages).
>
> It so happens that there's plenty of solutions to your specific problem,
> even though they don't match your specific question.
>
> -Wm
>
>
> [Non-text portions of this message have been removed]
>
>

chris glur — 2010-02-01 13:33:38

> That's a lousy excuse for refusing to accept an answer to
> your problem. Just because you did no research doesn't mean
> there's no answer.

We seem to have lost each other completely ?
The author defined the factorial function in one short line of near english;
and then gave the multi-step joy interpretation.
Since my aim is to REDUCE mental load, it's irrelevant WHAT the finer
considerations of his joy-translation may be, because I don't want
to transform conceptual simplicity into complexity.
For all I know his joy-translation may have error/s, but that's
irrelevant. I merely pasted it to show how he's transformed simplicity
into complexity.

> Your specific goal *seems* to be to program in a low-level
> non-concatenative language and a high-level concatenative
> language. Since that goal is reversed from anyone else's I've
> ever met, I'm mildly interested -- I like contrarian thinking
> (that's why I'm studying concatenative languages).

I'll give a real-life example:
for part of a task, I needed the list of pid/S with the open file
'on mc'.
An existing function called lsof shows a zillion lines, typically:-
mc 3499 root txt REG 3,14 519624 375343 /usr/bin/mc

Since all I want is [each]: (3499, /usr/bin/mc) pair, I merely pass it
[NB the use of "it" to lambda-like eliminate IDs] through filters which:
1. show only the lines which have "/mc"
2 show only the part of the lines with the 2nd field [the 3499] and the
last field.

So there are 3 'library available' BIG functions:
= lsof [list open files]
= grep "/mc" [ but show only lines with "/mc"]
= cut <something> [but show only the wanted part of the lines]

I don't WANT to know how these, no doubt complex, functions work.
They are constructed by a 'proper language' - as you call "low level".
And the the cat-like just does:
lsof | grep "/mc" | cut <as required>

So altho' cat-like is no good for the real heavy-lifting, it's good
to chain/pipe existing functions together to do the hi-level tasks.

== Chris Glur.


On 1/31/10, William Tanksley, Jr <wtanksleyjr@...> wrote:
> chris glur <crglur@...> wrote:
>
>> > The absurdity of MANUALLY translating the 1-line pseudocode
>> > to joy, when a simple/immediate algol-like compilation is
>> > available tells much?
>> ]That's not even a remotely fair translation as it's not recursive like
>> ]the example. The straight-forward recursive function is as such:
>> I MIGHT analyse your code in the future, but:
>> I merely PASTED the joy-author's ample 1-line pseudocode and HIS
>> joy version.
>>
>
> That's a lousy excuse for refusing to accept an answer to your problem. Just
> because you did no research doesn't mean there's no answer.
>
> I won't follow your NEW argument about Haskell etc. on the going
>> nowhere [because it's fun] journey. Can't someone answer MY question/s?
>> I've got a specific goal and am NOT just playing 'look ma no hands' !
>
>
> Your specific goal *seems* to be to program in a low-level non-concatenative
> language and a high-level concatenative language. Since that goal is
> reversed from anyone else's I've ever met, I'm mildly interested -- I like
> contrarian thinking (that's why I'm studying concatenative languages).
>
> It so happens that there's plenty of solutions to your specific problem,
> even though they don't match your specific question.
>
> -Wm
>
>
> [Non-text portions of this message have been removed]
>
>

William Tanksley, Jr — 2010-02-01 15:09:01

chris glur <crglur@...> wrote:

> > That's a lousy excuse for refusing to accept an answer to
> > your problem. Just because you did no research doesn't mean
> > there's no answer.
> We seem to have lost each other completely ?
> The author defined the factorial function in one short line of near
> english;
> and then gave the multi-step joy interpretation.
>

You're talking about Manfred's Joy paper posted at
http://www.latrobe.edu.au/philosophy/phimvt/joy/j02maf.html. Manfred's paper
wasn't trying to express factorial in the simplest manner possible, nor in
the best way to express the English; rather, it's a "tour de force", to use
the author's own words about the program you quoted, intended only to show
the most primitive breakdown of the program's operation for tutorial
purposes. It's much like reading a .NET CIL dump and concluding that C# is
not suitable for programming in-the-large.

Manfred himself explains this immediately after the section you quote: "Of
course this program is a *tour de force*, it is ugly and inefficient. With
more suitable combinators much crisper and more efficient programs can be
written." He suggests using "primrec", as Nowak did, to produce the program
"[1] [*] primrec"; he also explains how high-level concepts would increase
the actual efficiency of the program by reducing the amount of data moving
and copying.

Yet you take that out of context to "prove" that all concatenative programs
are messy and nasty, when in fact all you've proven is that low-level
operations are low-level.

Since my aim is to REDUCE mental load, it's irrelevant WHAT the finer
> considerations of his joy-translation may be, because I don't want
> to transform conceptual simplicity into complexity.
>

That doesn't make sense. The reason he wrote the program dictates why it's
messy and low-level -- because he wanted to expose the low-level details of
the implementation.

> Your specific goal *seems* to be to program in a low-level
> > non-concatenative language and a high-level concatenative
> > language. Since that goal is reversed from anyone else's I've
> > ever met, I'm mildly interested -- I like contrarian thinking
> > (that's why I'm studying concatenative languages).
> I'll give a real-life example:
> Since all I want is [each]: (3499, /usr/bin/mc) pair, I merely pass it
> [NB the use of "it" to lambda-like eliminate IDs] through filters which:
>

You ARE aware that lambda creates IDs, right? It doesn't eliminate them.

So there are 3 'library available' BIG functions:
> = lsof [list open files]
> = grep "/mc" [ but show only lines with "/mc"]
> = cut <something> [but show only the wanted part of the lines]
> I don't WANT to know how these, no doubt complex, functions work.
> They are constructed by a 'proper language' - as you call "low level".
> And the the cat-like just does:
> lsof | grep "/mc" | cut <as required>
>

That's usually called a "compositional" language, in existing terminology.
There's nothing particularly concatenative about it; compositional pipe
languages usually support only one pipe at a time, whereas a concatenative
language has as many data streams as you want to push on the stack.
Concatenative languages also don't use an operator to denote composition,
preferring the syntax of juxtaposition (and hence making concatenation map
to composition, whence the name 'concatenative').


> So altho' cat-like is no good for the real heavy-lifting, it's good
> to chain/pipe existing functions together to do the hi-level tasks.


Compositional languages are typically not used to build complex features, as
you say; but concatenative languages _are_.

== Chris Glur.


-Wm


[Non-text portions of this message have been removed]

chris glur — 2010-02-02 04:02:00

Can someone add value to my query/idea that 'perhaps cat-like is
effective/productive
in using pre-existing functions'. I'm only interested in productivety
increases, which
IMO come mostly by managing complexity ie. reducing the cognative
load; that's why
I found <the German-uni article> appropriate. Pity that THAT blog
needs a pasword.

Perhaps http://concatenative.org/wiki/view/Staapl
is talking about 'layered' system/s: like cat-like using pre-existing functions;
but at this stage of life, I'm not interested in 'playing cross word puzzles',
which seems the motivation of many contributors here.


On 2/1/10, William Tanksley, Jr <wtanksleyjr@...> wrote:
> chris glur <crglur@...> wrote:
>
>> > That's a lousy excuse for refusing to accept an answer to
>> > your problem. Just because you did no research doesn't mean
>> > there's no answer.
>> We seem to have lost each other completely ?
>> The author defined the factorial function in one short line of near
>> english;
>> and then gave the multi-step joy interpretation.
>>
>
> You're talking about Manfred's Joy paper posted at
> http://www.latrobe.edu.au/philosophy/phimvt/joy/j02maf.html. Manfred's paper
> wasn't trying to express factorial in the simplest manner possible, nor in
> the best way to express the English; rather, it's a "tour de force", to use
> the author's own words about the program you quoted, intended only to show
> the most primitive breakdown of the program's operation for tutorial
> purposes. It's much like reading a .NET CIL dump and concluding that C# is
> not suitable for programming in-the-large.
>
> Manfred himself explains this immediately after the section you quote: "Of
> course this program is a *tour de force*, it is ugly and inefficient. With
> more suitable combinators much crisper and more efficient programs can be
> written." He suggests using "primrec", as Nowak did, to produce the program
> "[1] [*] primrec"; he also explains how high-level concepts would increase
> the actual efficiency of the program by reducing the amount of data moving
> and copying.
>
> Yet you take that out of context to "prove" that all concatenative programs
> are messy and nasty, when in fact all you've proven is that low-level
> operations are low-level.
>
> Since my aim is to REDUCE mental load, it's irrelevant WHAT the finer
>> considerations of his joy-translation may be, because I don't want
>> to transform conceptual simplicity into complexity.
>>
>
> That doesn't make sense. The reason he wrote the program dictates why it's
> messy and low-level -- because he wanted to expose the low-level details of
> the implementation.
>
>> Your specific goal *seems* to be to program in a low-level
>> > non-concatenative language and a high-level concatenative
>> > language. Since that goal is reversed from anyone else's I've
>> > ever met, I'm mildly interested -- I like contrarian thinking
>> > (that's why I'm studying concatenative languages).
>> I'll give a real-life example:
>> Since all I want is [each]: (3499, /usr/bin/mc) pair, I merely pass it
>> [NB the use of "it" to lambda-like eliminate IDs] through filters which:
>>
>
> You ARE aware that lambda creates IDs, right? It doesn't eliminate them.
>
> So there are 3 'library available' BIG functions:
>> = lsof [list open files]
>> = grep "/mc" [ but show only lines with "/mc"]
>> = cut <something> [but show only the wanted part of the lines]
>> I don't WANT to know how these, no doubt complex, functions work.
>> They are constructed by a 'proper language' - as you call "low level".
>> And the the cat-like just does:
>> lsof | grep "/mc" | cut <as required>
>>
>
> That's usually called a "compositional" language, in existing terminology.
> There's nothing particularly concatenative about it; compositional pipe
> languages usually support only one pipe at a time, whereas a concatenative
> language has as many data streams as you want to push on the stack.
> Concatenative languages also don't use an operator to denote composition,
> preferring the syntax of juxtaposition (and hence making concatenation map
> to composition, whence the name 'concatenative').
>
>
>> So altho' cat-like is no good for the real heavy-lifting, it's good
>> to chain/pipe existing functions together to do the hi-level tasks.
>
>
> Compositional languages are typically not used to build complex features, as
> you say; but concatenative languages _are_.
>
> == Chris Glur.
>
>
> -Wm
>
>
> [Non-text portions of this message have been removed]
>
>

William Tanksley, Jr — 2010-02-02 05:04:21

chris glur <crglur@...> wrote:

> Can someone add value to my query/idea that 'perhaps cat-like is
> effective/productive in using pre-existing functions'.


I haven't seemed to be able to add the value you're looking for, so good
luck. I hope you come up with some interesting ideas.

I'm only interested in productivety increases, which
> IMO come mostly by managing complexity ie. reducing the cognative
> load;


If productivity truly is your main goal, you might consider being a little
more open to other possible factors contributing to productivity. For
example, the things that make a large team productive are not the things
that make a single person productive. This is why Java is so successful with
huge websites, and so unpleasant for personal projects. Anyone can slap
together a website for Python; but to merely get started with Java requires
you to choose between many competing frameworks for a million little parts
of the language, all of which have a million little configuration choices --
a large team has a specialist for each area, so the team can do the best
possible thing... the one person can't possibly figure out the best thing,
and will usually just pull some boilerplate code off the web.

Aside from the question of whether there are other ways to increase
productivity, the ways in which one manages complexity also matter. Compare
the solution in Java to the solution in Ruby -- and then look at Arc's
theory. (Arc's theory is that productivity is directly related to the
shortness of the natural solution in the language.)

Figuring out what's actually going on to cause productivity is a hard, hard
question... I hope you contribute to answering it someday.

Perhaps http://concatenative.org/wiki/view/Staapl
> is talking about 'layered' system/s: like cat-like using pre-existing
> functions;
> but at this stage of life, I'm not interested in 'playing cross word
> puzzles',
> which seems the motivation of many contributors here.
>

Playing with puzzles is sometimes useful, if the puzzles have never been
solved. We all have a part to play, if we're willing to do the work to play
it.

-Wm


[Non-text portions of this message have been removed]