473,386 Members | 1,720 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

High Order Messages in Python

I'm reading about "high order messages" in Ruby by Nat Pryce, and
thinking if it could be util and if so, if it could be done in Python.
Someone already tried?

References:
http://lambda-the-ultimate.org/node/view/1047
http://nat.truemesh.com/archives/000535.html
http://nat.truemesh.com/archives/000537.html

Oct 22 '05 #1
12 1796
Hum... I thnk you dont get the ideia: I'm not talking abou High Order
Functions.
What ho call "High Order Methods is some like "connecting" some
'generic' methods created to do things like this:
claimants.where.retired?.do.receive_benefit 50
The 2nd and 3rd links that in the first post is the most relevant to
undestand the concept. Read this too:
http://www.metaobject.com/papers/Hig...OPSLA_2005.pdf

Oct 22 '05 #2
This can be suitably applied to Python with the use of Higher Order
Functions, though. It's not quite the Ruby version because Python
allows you to use functions as first-class objects, complicating the
All-You-Can-Do-Is-Pass-A-Message philosophy. This is my 5-minute
implementation:
class HigherOrderList(list):

def do(self, func):
return HigherOrderList(each(self, func))

def where(self, pred):
return HigherOrderList(mass_test(self, pred))

def mass_test(iterable, pred):
for item in iterable:
if pred(item):
yield item

def each(iterable, method):
for item in iterable:
yield method(item)

Oct 22 '05 #3
"ed************@gmail.com" <ed************@gmail.com> writes:
I'm reading about "high order messages" in Ruby by Nat Pryce, and
thinking if it could be util and if so, if it could be done in Python.
Someone already tried?


Yes, I'm pretty sure it could be done in Python. All it really needs
is the ability to catch references to undefined attributes, which
Python has. You make the HOM of your collection class return an object
with a reference to self, and the __getattr__ method of that classs
then invokes getattr on each object in the referenced collection
instance for the undefined method, manipulating the result as
appropriate for that HOM, and returning a new list.

But this really isn't a very good fit for Python. This is really a
feature for more aggressively OO languages. To make the examples HOMs
described really useful, you want to add them to some base class for
collections. But that base class doesn't exist in Python - Python just
isn't that OO.

You could add various HOMs to lists, tuples, generators and iterators
- but then anyone who wanted to create a new sequence class would have
to add all of the HOMs that their clients might want to use. The
pythonic way would be to add a function that works with all the
various sequence types - which would then automatically work with any
user-defined classes that quacked like a sequence. It's not very OO -
but it is pythonic. In fact, Python already has functions that capture
the functionality of the example HOMs in the links you posted: where
and unless are handled by filter. in_order_of and in_reverse_order_of
are handled by sorted. do is is handled by map. Of course, recent
versions of python provide list comprehensions as preferable to some
of these functions.

That said, HOM's are a *very* powerful mechanism. The examples - and
my discussion of them - cover just one very broad use case. There may
be others where they are a better fit with Python. Having examples of
how to do these kinds of things around is probably worthwhile.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 22 '05 #4
ed************@gmail.com wrote:
I'm reading about "high order messages" in Ruby by Nat Pryce, and
thinking if it could be util and if so, if it could be done in Python.


Nice sunday afternoon exercise. Yes, you can do this in python. This is
based on a relatively naive translation of the ruby version:

class HigherOrderMessage(object):
def __init__(self,handler):
self.handler = handler

class Do(HigherOrderMessage):
def __HOM__(self, methname, *args):
"implement ruby's method_missing idea"
try:
for e in self.handler:
meth = getattr(e, methname)
meth(*args)
except TypeError: # Handle non-iterator, could be nicer
if self.handler is not None:
meth = getattr(self.handler, methname)
meth(*args)
def __getattribute__(self, methname):
try:
return super(Do,self).__getattribute__(methname)
except AttributeError:
def myHom(*args):
return self.__HOM__(methname, *args)
return myHom

class Where(HigherOrderMessage):
def __HOM__(self, methname, *args):
"implement ruby's method_missing idea"
try:
r = List()
for e in self.handler:
meth = getattr(e, methname)
if meth(*args):
r.append(e)
return r
except TypeError:
r = List()
if self.handler is not None:
meth = getattr(self.handler, methname)
if meth(*args):
r.append(self.handler)
return r
#
def __getattribute__(self, methname):
"Probably belongs in the baseclass"
try:
return super(Where,self).__getattribute__(methname)
except AttributeError:
def myHom(*args):
return self.__HOM__(methname, *args)
return myHom

class enumerable(object):
def do(self): return Do(self)
def where(self): return Where(self)

class List(enumerable,list):
"List using enumerable as a mixin"

class Claimant(enumerable):
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
self.benefits = 0

def retired(self):
return (self.gender == "male" and self.age >= 65) or \
(self.gender == "female" and self.age >= 60)

def receive_benefit(self,amount):
self.benefits = self.benefits + amount

def __str__(self):
return "%s,%s age: %s benefits: %s" % (
self.name,
self.gender,
str(self.age),
str(self.benefits)
)

#
# Create an enumerable list capable of responding to
#

claimants = List([ # Just a list which is enumerable as well
Claimant("tom", 32, "male"),
Claimant("dick", 64, "male"),
Claimant("harry", 128, "male"),
Claimant("Ivanova", 32, "female"),
Claimant("Kochansky", 64, "female"),
Claimant("Sung", 128, "female"),
])

# First the normal python way I prefer this)
for claimant in claimants:
if claimant.retired():
claimant.receive_benefit(50)

# Display the results
for claimant in claimants: print str(claimant)
print

# The more direct translation of :
# claimants.select {|e| e.retired?}.each {|e| e.receive_benefit 50}

[ e.receive_benefit(50) for e in claimants if e.retired() ]

# Display the results
for claimant in claimants: print str(claimant)
print

# The single claimant version of the higher order message approach
# re-uses the last claimant from above. This one unconditionally
# grants benefits.
#
claimant.do().receive_benefit(50)
print claimant
print

# Iterating over a bunch of Claimants with the higher order message
# approach. This conditionally updates the claimaints

claimants.where().retired().do().receive_benefit(5 0)
# display results
for claimant in claimants: print str(claimant)

I'm not convinced I'd actually *use* this approach(*), but it does show that
you can certainly take this approach in python. It's certainly interesting
though.
(*) Largely because there's a bunch of magic happening as far as the user
(next programmer to edit the file) is concerned. After all you can't
find the definition of retried in "where" or "claimant"; you can't
find the definition of "receive_benefit" in "do", "retired", "where"
or "claimants".

I'm also pretty sure there's other things you'd want to do more than the
above generally speaking if you wanted to handle inheritance/etc nicely.
(That does make me wonder as well if you'd need to do more in ruby as
well)

However, this certainly isn't a case of "ruby can do this, and python
can't", because clearly python CAN do it :-)

Regards,
Michael

Oct 23 '05 #5
On a (somewhat) related note,
I've always wondered whether it is possible to emulate ruby blocks
using a python generator '+ alpha'. In my limited understanding of the
ruby block, the generator can inject values into a block, I suppose,
but what is the block itself? can it be a function? a class instance?
what would it look like? I am sure someone must have played around with
this.
any pointers?
cheers,
v.

Oct 24 '05 #6
http://www.artima.com/intv/closures.html
http://www.rubyist.net/~matz/slides/...005/index.html

It's a read-write closure, a co-routine, sort of a continuation (tho
Kernel.callcc is considered the real continuation mechanism).
And you can make it a Proc object (basically an unbound object you can
pass to methods) with Proc#new or lambda. HTH

vdrab wrote:
On a (somewhat) related note,
I've always wondered whether it is possible to emulate ruby blocks
using a python generator '+ alpha'. In my limited understanding of the
ruby block, the generator can inject values into a block, I suppose,
but what is the block itself? can it be a function? a class instance?
what would it look like? I am sure someone must have played around with
this.
any pointers?
cheers,
v.


Oct 24 '05 #7
could someone enlighten me what is the advantage of block over named
function ?

One thing that I can see a difference may be lexical scope ?

vdrab wrote:
On a (somewhat) related note,
I've always wondered whether it is possible to emulate ruby blocks
using a python generator '+ alpha'. In my limited understanding of the
ruby block, the generator can inject values into a block, I suppose,
but what is the block itself? can it be a function? a class instance?
what would it look like? I am sure someone must have played around with
this.
any pointers?
cheers,
v.


Oct 24 '05 #8
bo****@gmail.com <bo****@gmail.com> wrote:
could someone enlighten me what is the advantage of block over named
function ?

One thing that I can see a difference may be lexical scope ?


"Yes, but" -- according to the latest Ruby book, the "mixed lexical
scope" of blocks is a highly controversial notion in the Ruby community;
so I wouldn't necessarily count it as an _advantage_ of Ruby blocks...
Alex
Oct 24 '05 #9
counting that out(regardless whether it is (dis)advantage or not), what
else a block can do but not a named function ?

Alex Martelli wrote:
bo****@gmail.com <bo****@gmail.com> wrote:
could someone enlighten me what is the advantage of block over named
function ?

One thing that I can see a difference may be lexical scope ?


"Yes, but" -- according to the latest Ruby book, the "mixed lexical
scope" of blocks is a highly controversial notion in the Ruby community;
so I wouldn't necessarily count it as an _advantage_ of Ruby blocks...
Alex


Oct 24 '05 #10
bo****@gmail.com wrote:
counting that out(regardless whether it is (dis)advantage or not), what
else a block can do but not a named function ?
My limited understanding is that the advantage is
- simpler syntax
- high level of integration into the standard library (*many* methods that take closure arguments). Blocks are used not just for iteration but for the kinds of things shown in the examples to PEP 343 http://www.python.org/peps/pep-0343.html

For example to open a file and read from it uses two closures, one to wrap a block with the file open/close, one to iterate lines (from the pickaxe book):

File.open("testfile") do |file|
file.each_line { |line| puts line }
end

Kent

Alex Martelli wrote:
bo****@gmail.com <bo****@gmail.com> wrote:

could someone enlighten me what is the advantage of block over named
function ?

One thing that I can see a difference may be lexical scope ?


"Yes, but" -- according to the latest Ruby book, the "mixed lexical
scope" of blocks is a highly controversial notion in the Ruby community;
so I wouldn't necessarily count it as an _advantage_ of Ruby blocks...
Alex


Oct 24 '05 #11
thanks. Seems that my programs are very simple and don't need these
feature yet.

Kent Johnson wrote:
bo****@gmail.com wrote:
counting that out(regardless whether it is (dis)advantage or not), what
else a block can do but not a named function ?


My limited understanding is that the advantage is
- simpler syntax
- high level of integration into the standard library (*many* methods that take closure arguments). Blocks are used not just for iteration but for the kinds of things shown in the examples to PEP 343 http://www.python.org/peps/pep-0343.html

For example to open a file and read from it uses two closures, one to wrap a block with the file open/close, one to iterate lines (from the pickaxe book):

File.open("testfile") do |file|
file.each_line { |line| puts line }
end

Kent

Alex Martelli wrote:
bo****@gmail.com <bo****@gmail.com> wrote:
could someone enlighten me what is the advantage of block over named
function ?

One thing that I can see a difference may be lexical scope ?

"Yes, but" -- according to the latest Ruby book, the "mixed lexical
scope" of blocks is a highly controversial notion in the Ruby community;
so I wouldn't necessarily count it as an _advantage_ of Ruby blocks...
Alex



Oct 24 '05 #12
Kent Johnson <ke****@tds.net> wrote:
...
For example to open a file and read from it uses two closures, one to wrap
a block with the file open/close, one to iterate lines (from the pickaxe
book):

File.open("testfile") do |file|
file.each_line { |line| puts line }
end


Good example -- Ruby blocks are used both for iteration, and for
non-iterative wrapping of a single action with "try-finally" semantics.

Python's generators, up to 2.4, don't really support the non-iterative
part of this well, and have other limitations (they can get values "out"
with yield, but can't easily or naturally get results back "in"...). In
the forthcoming 2.5, Python generators will be enriched with enough
functionality for these purposes, and a new statement "with" to clearly
indicate the non-iterative case (while "for" indicates iteration).

So, in Python 2.5, the above snippet may become, in Python:

with opening("testfile") as my_file:
for line in my_file:
print line,

The fact that 2.5 will acquire extra functionality to "round out"
generators &c to the power of Ruby blocks may be taken as a clear
indication that, right now (Ruby 1.8.* vs Python 2.4.*), Ruby's blocks
are somewhat more powerful. As for the differences in style that will
remain when Python 2.5 is born, we'll be back to "personal taste" level
issues, it appears to me.
Alex
Oct 24 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

75
by: Howard Nease | last post by:
Hello, everyone. I would appreciate any advice that someone could give me on my future career path. Here is my situation: I am a bright Junior in a very well-respected private high school, taking...
1
by: lothar | last post by:
i want to traverse a set of messages in a Yahoogroups group from a Python program. to get to the messages of the group, one must log in. this presents, i think, two problems, 1) handling the...
7
by: Irmen de Jong | last post by:
Hi, Things like Twisted, medusa, etc.... that claim to be able to support hundreds of concurrent connections because of the async I/O framework they're based on.... can someone give a few...
8
by: York | last post by:
Hi, R language has very high-level IO functions, its read.table can read a total .csv file and recogonize the types of each column. write.table can do the reverse. R's MySQL interface has...
11
by: nephish | last post by:
hello there, all. i have a difficult app that connects to a server to get information for our database here. this server is our access point to some equipment in the field that we monitor. ...
1
by: boney | last post by:
hello All, I am totally unknown to python language.. i need to install mod_python to embed python interpreter with the Apache server, in order to use Trac with Apache Web Server i am using...
0
by: bg_ie | last post by:
Hi all, I'm writing a .net Com object to read messages from an external bus. Also, under certain situations, I output messages to the bus in order to generate bus load, for testing purposes. An...
34
by: Victor Kryukov | last post by:
Hello list, our team is going to rewrite our existing web-site, which has a lot of dynamic content and was quickly prototyped some time ago. Today, as we get better idea of what we need, we're...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.