Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Lisp's "some" and "every" functions

Reply
Thread Tools

Lisp's "some" and "every" functions

 
 
J. Romano
Guest
Posts: n/a
 
      11-13-2004
Dear Perl community,

Recently I've been learning some Lisp on my own, and I've come
across two Lisp functions that I wish Perl had: "some" and "every".

They work somewhat like "grep" and "map" in that they operate on a
list given a function, but they return only a boolean value.

For example, in Lisp, to find out if at least one number in a list
is an odd number, you could write:

(some #'oddp '(1 2 3 4 5))

or even:

(some (lambda (x) (= 1 (mod x 2))) '(1 2 3 4 5))

In Perl, you COULD write:

if ( grep { $_ % 2 == 1 } (1, 2, 3, 4, 5) )
{
print "An odd number exists in the given list.\n";
}

but according to 'perldoc -q "element is contained"', use of "grep" is
undesirable (especially on large lists) because "grep" checks every
element even if the first matches.

As for the "every" function, you can use it to find out if every
element passes a certain test. For example, in Lisp you could use it
like this to see if every element in a list is an even number:

(every #'evenp '(2 4 5 6 )

or even:

(every (lambda (x) (= 0 (mod x 2))) '(2 4 5 6 )

In Perl, you COULD write:

my @list = (2, 4, 5, 6, ;

if ( @list == grep { $_ % 2 == 0 } @list )
{
print "All number in given list are even.\n";
}

but, of course, this suffers from the same inefficiency as the
previous Perl example.

This inefficiency is not worth worrying about if the list to
examine has only a few elements, but if it has a large number of
elements (or the number of elements is arbitrary), there exist a few
work-arounds.

One work-around is mentioned in 'perldoc -q "element is
contained"', so I won't discuss it here. Another work-around is to
create a module that defines the "some" and "every" functions to be
used similarly to how Perl's "grep" and "map" functions are called.
I've written the code, and here it is (more discussion follows):


use strict;
use warnings;

sub some (&@)
{
my $sub = shift(@_);

foreach (@_)
{
return 1 if &$sub;
}

return 0;
}

sub every (&@)
{
my $sub = shift(@_);

foreach (@_)
{
return 0 if not &$sub;
}

return 1;
}

1;

__END__


Now, when this module is "use"d, you can now check for the
existence of an odd number with the "some" function like:

my @list = (2, 4, 5, 6, ;

if ( some { $_ % 2 == 1 } @list )
{
print "An odd number exists in the given list.\n";
}

You can also verify that all the numbers in a list are even numbers
with the "every" function like:

my @list = (2, 4, 5, 6, ;

if ( every { $_ % 2 == 0 } @list )
{
print "All number in given list are even.\n";
}

These functions don't suffer then same inefficiency discussed in
the perldoc because they will stop examining the list once the "some"
function verifies the answer is true, or the "every" function verifies
that the answer is false.

A few things to note:

* The "some" function always returns false on an empty list.
(because no element exists that passes the test).
* The "every" function always returns true on an empty list
(because no element exists that fails the test).
* These functions always return a true or false (boolean) value.
They DO NOT return a list, like "map" and "grep" do.
* These functions must be specified with a block of code.
In other words, where "grep" can be used like this:
grep m/^a/i, @list
or like this:
grep { m/^a/i } @list
the "some" and "every" functions can only be used like this:
some { m/^a/i } @list
every { m/^a/i } @list


That's all I have to say on this subject, so Happy Perling!

-- Jean-Luc Romano
 
Reply With Quote
 
 
 
 
Rhesa Rozendaal
Guest
Posts: n/a
 
      11-13-2004
J. Romano wrote:
> Dear Perl community,
>
> Recently I've been learning some Lisp on my own, and I've come
> across two Lisp functions that I wish Perl had: "some" and "every".
>
> They work somewhat like "grep" and "map" in that they operate on a
> list given a function, but they return only a boolean value.
>
> One work-around is mentioned in 'perldoc -q "element is
> contained"', so I won't discuss it here. Another work-around is to
> create a module that defines the "some" and "every" functions to be
> used similarly to how Perl's "grep" and "map" functions are called.
> I've written the code, and here it is (more discussion follows):
>


The other work-around would be to use List::Any.
http://search.cpan.org/~vparseval/Li...ib/List/Any.pm

Rhesa
 
Reply With Quote
 
 
 
 
Rhesa Rozendaal
Guest
Posts: n/a
 
      11-13-2004
Rhesa Rozendaal wrote:
> J. Romano wrote:
>
>> Dear Perl community,
>>
>> Recently I've been learning some Lisp on my own, and I've come
>> across two Lisp functions that I wish Perl had: "some" and "every".
>>
>> They work somewhat like "grep" and "map" in that they operate on a
>> list given a function, but they return only a boolean value.

>
> >

>
>> One work-around is mentioned in 'perldoc -q "element is
>> contained"', so I won't discuss it here. Another work-around is to
>> create a module that defines the "some" and "every" functions to be
>> used similarly to how Perl's "grep" and "map" functions are called.
>> I've written the code, and here it is (more discussion follows):
>>

>
> The other work-around would be to use List::Any.
> http://search.cpan.org/~vparseval/Li...ib/List/Any.pm
>
> Rhesa


It seems Tassilo merged the code of List::Any into List::MoreUtils.
 
Reply With Quote
 
Tassilo v. Parseval
Guest
Posts: n/a
 
      11-13-2004
Also sprach Rhesa Rozendaal:

> Rhesa Rozendaal wrote:


>> The other work-around would be to use List::Any.
>> http://search.cpan.org/~vparseval/Li...ib/List/Any.pm
>>
>> Rhesa

>
> It seems Tassilo merged the code of List::Any into List::MoreUtils.


Not so much merged into but renamed to. I was made aware that
List::MoreUtils would be a better namespace choice. So that means the
latest release is always at

http://search.cpan.org/~vparseval/List-MoreUtils/

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus}) !JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexi ixesixeseg;y~\n~~dddd;eval
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      11-13-2004


Tassilo v. Parseval wrote:

> Also sprach Rhesa Rozendaal:
>
>
>>Rhesa Rozendaal wrote:

>
>
>>>The other work-around would be to use List::Any.
>>>http://search.cpan.org/~vparseval/Li...ib/List/Any.pm
>>>
>>>Rhesa

>>
>>It seems Tassilo merged the code of List::Any into List::MoreUtils.

>
>
> Not so much merged into but renamed to. I was made aware that
> List::MoreUtils would be a better namespace choice. So that means the
> latest release is always at
>
> http://search.cpan.org/~vparseval/List-MoreUtils/
>
> Tassilo


Any chance the old apply() function could find a home there?


=item apply BLOCK LIST

Similar to C<map> in that it evaluates BLOCK setting C<$_> to each
element of LIST in turn. C<apply> returns a list made up of the
values of C<$_> after BLOCK has been evaluated. In a scalar context
the last element is returned. Unlike C<map> and C<grep> the elements
of LIST are not altered.

@foo = apply { s/\s+/ /g } @bar; # canonicalise whitespace

This function is nothing more than syntactic sugar for people who find
the following syntax unpalatable.

for (@foo = @bar) { s/\s+/ /g }

=cut

sub apply (&@) {
my $action = shift;
&$action for my @values = @_;
wantarray ? @values : $values[-1];
}

 
Reply With Quote
 
Tassilo v. Parseval
Guest
Posts: n/a
 
      11-13-2004
Also sprach Brian McCauley:

> Tassilo v. Parseval wrote:


>> Not so much merged into but renamed to. I was made aware that
>> List::MoreUtils would be a better namespace choice. So that means the
>> latest release is always at
>>
>> http://search.cpan.org/~vparseval/List-MoreUtils/
>>
>> Tassilo

>
> Any chance the old apply() function could find a home there?


Ah, sure. I'm always looking for more useful list operations.

> sub apply (&@) {
> my $action = shift;
> &$action for my @values = @_;
> wantarray ? @values : $values[-1];
> }


I can use that verbatimly for the pure-Perl implementation. The XS one
shouldn't be too tricky either. I'll do that tomorrow.

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus}) !JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexi ixesixeseg;y~\n~~dddd;eval
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Static functions and C++ member functions mafiQ C++ 0 04-22-2009 08:33 PM
Does ruby have a similar functions to the Python dir and help functions? py Ruby 5 03-24-2007 08:54 AM
private virtual functions and pure virtual functions with bodies John Goche C++ 10 12-08-2006 04:00 PM
Shared functions vs Non-Shared Functions tshad ASP .Net 11 05-27-2005 05:53 PM
please help me in distinguish redefining functions, overloading functions and overriding functions. Xiangliang Meng C++ 1 06-21-2004 03:11 AM



Advertisments