Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

The following are some (lightly edited :) initial reactions to your follow post.

Note: Initial.

There are some positive reactions lower down, but I thought that I would get these out of the way first in the hope that the later reactions would erase any bitter taste these might leave.

  1. I never said "this crazy FP stuff".
  2. I get the FP -v- FP-inspired difference.
  3. Phrases like "spectrum of problems", "shape of the problems", "shape-flexing capability", "code at a higher level" & "think at a higher level" all leave

    What is he trying to conceal with flowery language?

    Put that down to having suffered the hyperbole of too many "new programming paradyms". (I realise FP isn't new.)

  4. "The reason you perceive the fp-inspired code as hard to follow is because your brain hasn't "internalized" the meaning of products and zips and the rest of our new vocabulary. To you, these words probably seem like gratuitous functional jargon."

    My question is: "Do I need this new vocabulary?".

  5. "But the words have meaning. When I saw the example problem as first posted by the Seeker of Perl Wisdom, I immediately thought, "Ah, he wants the count of each value from the zipped products." And the code immediately followed."

    Fair enough, but then you had to construct a fairly complicated library of intrastructure in order to be able to code the solution in terms of your vocabulary.

    When I saw the example problem, I thought: "He want's to iterate over the two arrays of strings and count the unique pairs of aligned characters".

    1. "...iterate over the two arrays..."

      Nested for loops.

    2. "...count the unique pairs...".

      Increment a hash.

    3. "...pairs of aligned characters."

      Two substrs and another for loop.

    The code I posted fell straight out of that. No need for any auxillary vocabulary. No need to code a bunch of extra infrastructure. Perl already has all the vocabulary and in-built infrastructure required.

  6. "That's the reward. To have the right words to describe the problem. To have more ways of stringing together ideas. To reduce the gulfs between problem and understanding, understanding and code." & "If this sounds like worthless babble, that's OK."

    {nods} Yes. It does a bit :)

  7. I didn't appreciate functional programming until I had used it to solve real-world sized problems for over a year. Only then could I "feel" fp in my bones and appreciate its potential.

    I've been trying to get into FP since I first starting reading articles on Lisp in Byte magazine circa. 1979/80. I currently have Common Lisp, Scheme, and most recently Haskell.

  8. Have you read Why Functional Programming Matters? If not, read it. Now."

    I pulled the PDF and tried to read it. After a little while it began to seem familiar. Maybe it appeared on Byte, or CoACM or something else I've read a long time ago? Maybe it was referenced from such an article and I tracked it down and tried to read it? Maybe it's just the code examples that seem familiar from some other FP tutorial I've read down the years? Whatever, the PDF sits open on my desktop and I will endevour to try and read it to the end, but I doubt that I made it that far last time either.

    The problem is that in common with many other FP (and, notoriously OO) tutorials, it selects very specifically limited and condusive (to their aims) examples. It then spends an inordinate amount of time concentrating on how to construct the solution--in it's own, very esoteric, terms. Your real world examples are infinitely better (IMO).

    But the single line that sums up my feelings of what I've seen of FP tutorials and advocacy comes from the Abstract on the page you linked to above.

    Since modularity is the key to successful programming, functional languages are vitally important to the real world.

    The problem with that statement is that it implies that the only way to achieve modularity, is through FP--which is clearly not the case.

  9. I love Perl Monks, but don't look at the fp examples on Perl Monks as your window into the fp world. Take a look at the stuff going on in the Haskell Communities Report. Read some of the papers from the ICFP proceedings. That's where you'll find the good stuff.

    As I mentioned, my FP exploration goes back a long way, and my research is definitly not confined to what I see on PM. My exploration of Haskell is very new (and did come about because of articles mentioning it here at PM), so thankyou for those links--they will give me many hours of good reading.

I hope that doesn't all seem negative? It isn't meant to be. I'm continuing to enjoy reading your article and pursue various angles that lead from it. Thankyou for writing it and I look forward to Part 2.

For me, the most significant thing that came out of your response to my initial post is:

Instead of passing in \(@site1,@site2) you can pass in any number of input arrays. And the same code works, as is.

Now that is a benefit that I can understand and internalise :).

I did try to download your code and try this out, but there seem to be some bits missing to allow the examples to work? Perhaps in part 2. This is what I extracted from your OP: {**Code moved to bottom of post**} but I couldn't work out how to fix it up so that I could try out the example with 3 or more lists?

Anyway, the concept of writing a generic solution to the nested loops problem is one that I've been trying to get to grips with for some time. The upshot of your article (for me) is that I've finally gotten around to putting some concerted effort into it, and I came up with a solution. It doesn't look much like FP in it's construction, but it does rely heavily of constructing anonymous subroutine iterators, and constructing lists of these. And combining these iterator functions to contruct a higher order iterator. So, having (probably) butchered the FP vocabulary to death :), this is what my solution looks like:

#! perl -slw use strict; sub loops { my @iters = map{ my @list = ( @$_, undef ); sub { $list[ @list ] = shift @list || () }; } @_; my @rv = map{ $iters[ $_ ]() } 0 .. $#iters; return sub { my $rv = [ @rv ]; for my $i ( reverse 0 .. $#iters ) { $rv[ $i ] = $iters[ $i ]() and return $rv; $rv[ $i ] = $iters[ $i ](); } return; }; } my $iter = loops [ 'a' .. 'd' ], [ 1 .. 4 ], [ 'me', 'you' ]; print "@$_" while $_ = $iter->(); __END__ [13:51:21.14] P:\test>loops a 1 me a 1 you a 2 me a 2 you a 3 me a 3 you b 1 me b 1 you b 2 me b 2 you b 3 me b 3 you c 1 me c 1 you c 2 me c 2 you c 3 me

I'm pretty pleased with that. Your article has been invaluable to me because it has prompted me to look at this problem in a completely different way to that in which I have been looking at it in the past. And it has triggered a lot of thoughts about using similar techniques to generalise several other pieces of code I have kicking around.

So thankyou again for posting your very thought provoking article. I really look forward to part 2.

I think the conclusion I'm drawing is that it's possible to learn and adopt techniques from other languages and styles of coding, without having to adopt the vocabularies and working practices wholesale. Once you understand (if I have?), the underlying techniques, it becomes possible to utilise them whilst retaining the flavour of the language in which your writing.

The code I extracted from your OP. Moved to the bottom to avoid interupting the main post. (Wouldn;t it be nice if readmore tags only expanded when asked? Even if viewing the containing post directly).

#! perl -w use strict; use List::Util qw( reduce ); use Data::Dumper; #package Sequence; #sub new { # my ($proto, $seq) = @_; # bless $seq, $proto; #} #sub seqsub(&) { # Sequences->new(@_); #} sub seq { my ($i, $elems) = (0, \@_); seqsub { $i < @$elems ? ( $elems->[ $i++ ] ) : do { $i = 0; () }; } } sub enumerate { local $Data::Dumper::Terse = 1; local $Data::Dumper::Indent = 0; my ($i, $seq) = (0, $_[0]); while (my @val = $seq->()) { @val = map { ref ($_) ? Dumper($_) : $_ } @val; printf "%2d => %s\n", $i++, "@val"; } $seq; } sub seq_prod2 { my ($s, $t) = @_; my @sval; seqsub { @sval = $s->() unless @sval; my @tval = $t->(); @tval ? ( @sval, @tval ) : do { @sval = $s->(); @sval ? ( @sval, $t->() ) : () }; } }; sub seq_prod { reduce { seq_prod2($a,$b) } @_ ; } sub seqs { map seq(@$_), @_; } sub seq_from_spec { seq_prod( seqs(@_) ); } sub seq_foreach { my ($seq, $fn) = @_; while (my @val = $seq->()) { $fn->(@val); } $seq; } sub seq_foreach_from_spec { my ($spec, $fn) = @_; seq_foreach( seq_from_spec( @$spec ), $fn ); } sub seq_filter { my ($seq, $filter_fn) = @_; seqsub { my @val; 1 while @val = $seq->() and !$filter_fn->(@val); return @val; } } sub seq_map { my ($seq, $fn) = @_; seqsub { my @val = $seq->(); @val ? $fn->(@val) : (); } } sub seq_reset { my $seq = shift; if ($seq) { 1 while $seq->(); } $seq; } sub seq_zip { my $seqs = seq( @_ ); # seq of seqs (!) my $seq_count = @_; seqsub { my @outvals; while (my $seq = $seqs->()) { if (my @val = $seq->()) { push @outvals, @val; } else { seq_reset( $seqs->() ) for 1 .. $seq_count; seq_reset( $seqs ); return (); } } return @outvals; } } my @site1 = qw( AATKKM aatkkm ); my @site2 = qw( GGGGGG gggggg ); my %counts; seq_foreach_from_spec( [ \(@site1, @site2) ], sub { seq_foreach( seq_zip( ( map seq(split//), @_ ) ), sub { $counts{"@_"}++ } ) } ); print Dumper(\%counts), "\n";

Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

In reply to Re^3: A mini-language for sequences (part 1) by BrowserUk
in thread A mini-language for sequences (part 1) by tmoertel

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (2)
As of 2023-10-05 02:38 GMT
Find Nodes?
    Voting Booth?

    No recent polls found