map(f,items)
is equivalent to:
for x in items:
f(x)
But what is the functional equvalent of:
for x in items:
x.f()
Thanks.
: map(f,items)
: is equivalent to:
: for x in items:
: f(x)
map() collects the results of calling f() over all the x in items, so a
closer translation would be:
###
results = []
for x in items:
results.append(f(x))
###
: But what is the functional equvalent of:
: for x in items:
: x.f()
Here's one way to do it:
###
map(lambda x: x.f(), items)
###
We need to feed map() a function that does the action 'x.f()'. If we
don't want to use lambda, we can do something like this:
###
def call_function_f_from_x(x):
return x.f()
results = map(call_function_f_from_x, items)
###
If you have more questions, please feel free to ask. Good luck!
> : But what is the functional equvalent of:
>
> : for x in items:
> : x.f()
>
>
>
> Here's one way to do it:
>
> ###
> map(lambda x: x.f(), items)
> ###
I'd prefer
[x.f() for x in items]
It's not functional syntax, but so what?
--
David Eppstein UC Irvine Dept. of Information & Computer Science
epps...@ics.uci.edu http://www.ics.uci.edu/~eppstein/
Actually, map does more than that. map returns the results of f(x) as a new
list, of the same length as the original items. If f() returns no value,
then you get a list of Nones.
>>> map(string.upper, ['dfbdfg','sdfgberg','dfbsadg','dfbdfag'])
['DFBDFG', 'SDFGBERG', 'DFBSADG', 'DFBDFAG']
> But what is the functional equvalent of:
>
> for x in items:
> x.f()
List comprehensions make easy work of this:
>>> [ x.upper() for x in ['dfbdfg','sdfgberg','dfbsadg','dfbdfag'] ]
['DFBDFG', 'SDFGBERG', 'DFBSADG', 'DFBDFAG']
so in your example, "[ x.f() for x in items ]". Cool, eh?
--
# Joshua Muskovitz
# jo...@taconic.net
def lyyrs(sig): return '-'.join(sig.split()+["ly y'rs"])
lyyrs('Hire me! I need the work!')
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----
Yeah, whoever it was that decided this was the syntax
for a list comprehension was just a plain genius. It's
one of those linguistic thingies where you take one
look at it, and you say, "of course".
Wait a second. What's this theory about Guido and his
time machine? I guess you're the genius, and Guido's
only cheating. :-)
C//
Both of those build up a new list of the results, instead of
discarding the values. If the f function takes an integer and
computes a 20-megabyte structure, you've got a problem. This really
calls for a generator comprehension as discussed a few weeks back.
reduce(lambda x,y:(y.f(),0)[1], items, 0)
almost works, but invokes f an extra time at the end.
Someone see how to fix it?
If you know it's coming, throw it away first:
[x.f() and None for x in items]
> This really
> calls for a generator comprehension as discussed a few weeks back.
>
> reduce(lambda x,y:(y.f(),0)[1], items, 0)
>
> almost works, but invokes f an extra time at the end.
>
> Someone see how to fix it?
Expanding the above to:
filter(None,[x.f() and None for x in items])
returns an empty list vs 0 for the reduce.
--
Emile van Sebille
em...@fenx.com
---------
>>> class F:
... def __init__(self,msg):
... self.msg = msg
... def f(self):
... print self.msg
...
>>> a=F('this is a')
>>> b=F('this is b')
>>> c=F('this is c')
>>> items = [a,b,c]
>>> reduce(lambda x,y:y.f() and 0, items, 0)
this is a
this is b
this is c
but I didn't get an extra call trying your version:
>>> reduce(lambda x,y:(y.f(),0)[1], items, 0)
this is a
this is b
this is c
0
you can use the 'and 0' ploy to get a zero length
list comprehension also:
>>> [ 0 for x in items if x.f() and 0]
this is a
this is b
this is c
[]
Regards,
Bengt Richter
> "Paul Rubin"
> > Both of those build up a new list of the results, instead of
> > discarding the values. If the f function takes an integer and
> > computes a 20-megabyte structure, you've got a problem.
>
> If you know it's coming, throw it away first:
>
> [x.f() and None for x in items]
OK, but that buidls a list of None as long as the item list. Not
so bad, since it gets reclaimed right away, but still unsatisfying.
> filter(None,[x.f() and None for x in items])
>
> returns an empty list vs 0 for the reduce.
Again there's this intermediate list that's as long as the original list.
Do you see a way around that?
Thanks
Didn't you? 'items' had three elements, but four values got printed.
> you can use the 'and 0' ploy to get a zero length
> list comprehension also:
>
> >>> [ 0 for x in items if x.f() and 0]
> this is a
> this is b
> this is c
> []
Nice! That's the best solutions so far.
>Donnal Walter <don...@donnal.net> wrote:
>: I know that
>
>: map(f,items)
>
>: is equivalent to:
>
>: for x in items:
>: f(x)
>
>
>map() collects the results of calling f() over all the x in items, so a
>closer translation would be:
>
>###
>results = []
>for x in items:
> results.append(f(x))
>###
I would think that a block of statements as such has no return value
at all. That is, while every function called has a return value, it
always gets thrown away. It *can* return data, but then thats a
special statement. In a lambda expression, everything has to have a
return value, and be it "None". So, in a way, this comment applys to
all statements-mapped-to-lambda (IF, WHILE, PRINT etc.).
The only problem I can see with this is a possible memory thing: If
you call n functions, a lambda expression attempts to generate a list
of n return values, while n statements would just throw away their
return values. If n is very large, this might be a limit. (But then,
tail-recursion in lambdaesque-while will probably run into stack
problems earlier).
> >[x.f() for x in items]
>
>Yeah, whoever it was that decided this was the syntax
>for a list comprehension was just a plain genius. It's
>one of those linguistic thingies where you take one
>look at it, and you say, "of course".
It's from Haskell, I think, which in turn took it from plain old mathematics.
Haskell syntax is : [ f(x,y) | x <- items, y <- moreItems, x+y < 5 ]
Math notation is the same without brackets and with the "belongs to" symbol
(the one you get with $\in$ in TeX). Well, you might have : instead of |, too.
Of course Guido might have travelled back in time and suggested it so that
it was there for Python to borrow afterwards :)
Bye,
Luigi
?
Cheers,
M.
--
Premature optimization is the root of all evil.
-- Donald E. Knuth, Structured Programming with goto Statements
------------------------ (cut here) ------------------------
import sys, os
# create a list of unique functions printing values
functions = [lambda x=i:sys.stdout.write("f(%d) called\n" % x) for i
in range(10)]
print "The easy way:"
for function in functions:
function()
print "The braindead way:"
callem = lambda functions,l=[tempfile.mktemp()]:map(eval,\
('sys.stdout.write(str(l))','l.append(open(l[0],"w"))',
'map(lambda x,l=l:l[1].write("functions[%d]()\\n"%x),'\
'xrange(len(functions)))','l[1].close()','execfile(l[0])',
'os.remove(l[0])'))
callem(functions)
------------------------ (cut here) ------------------------
The code creates a temporary file and then uses execfile() to execute
it. This is not threadsafe ;) I cannot use "exec" because thats a
statement & not allowed in lambda.
Note that I sense a slight problem with the scoping rules in the
callem code: the lambda in line 3 has to pass "l=l", otherwise the
code won't work. I have no idea why, because I was under the
impression that that is not necessary with those new rules. Go figure
it out ;)
if all "items" are the same class, you could get away with this,
map(class_of_x.f, items)
>bo...@oz.net (Bengt Richter) writes:
>> but I didn't get an extra call trying your version:
>>
>> >>> reduce(lambda x,y:(y.f(),0)[1], items, 0)
>> this is a
>> this is b
>> this is c
>> 0
>
>Didn't you? 'items' had three elements, but four values got printed.
True, but the zero was the interpretive loop printing the final value of
the reduce expression, which is not evidence of a y.f() call. All those
were logged by "this is ...".
My version of your reduce evaluated to None, so nothing extra printed,
but that was because the last y.f() call returned None, and the 'and 0'
actually didn't get a chance to do anything. I should have used
'y.f() and None or None' to guarantee a final None to prevent the
final interactive printout, if that was the goal.
>
>> you can use the 'and 0' ploy to get a zero length
>> list comprehension also:
>>
>> >>> [ 0 for x in items if x.f() and 0]
>> this is a
>> this is b
>> this is c
>> []
>
>Nice! That's the best solutions so far.
Actually, I think I like
reduce(lambda x,y: y.f(), items, 0)
best, since we're ignoring the final result anyway.
Regards,
Bengt Richter
There really is no functional equivalent of that, because it's not a functional
concept. If your function doesn't have any side-effects, calling the function
only to throw away its value does nothing but suck up CPU time.
If you're calling the method for its side-effects, I'd write:
for x in items:
x.f()
>I'd prefer
>[x.f() for x in items]
>
>It's not functional syntax, but so what?
Sure it is. It's an expression, works best when x.f() has no side-effects, and
provides nicer syntax for mapping and filtering, two popular functional
concepts. It's also borrowed from haskell, which, although functional, has a
lot of syntax sugar that turns into function application.
Methinks there are two definitions of "functional" at work here:
1) The traditional CS "no side-effects" definition.
2) Something that looks like a function call.
?
--
Grant Edwards grante Yow! Yow! I forgot my
at PAIL!!
visi.com
> >I'd prefer
> >[x.f() for x in items]
> >
> >It's not functional syntax, but so what?
>
> Sure it is. It's an expression, works best when x.f() has no
> side-effects, and provides nicer syntax for mapping and filtering, two
> popular functional concepts. It's also borrowed from haskell, which,
> although functional, has a lot of syntax sugar that turns into function
> application.
To me it's like the difference between using coordinates or avoiding them
in linear algebra. A true functional syntax, to me, would avoid referring
to the individual items in the list and just combine the list with a
function, so "map(f, items)" is purer to me than "[f(x) for x in items]",
because it avoids using any x's. Which in turn is purer than
L = []
for x in items:
L.append(f(x))
But, as I said, for the x.f() case, I prefer the list-comprehension syntax,
because simplicity and ease of understanding are more important than purity.
...
> >>I'd prefer
> >>[x.f() for x in items]
> >>
> >>It's not functional syntax, but so what?
> >
> > Sure it is.
On Mon, 25 Feb 2002, Grant Edwards wrote:
> Methinks there are two definitions of "functional" at work here:
>
> 1) The traditional CS "no side-effects" definition.
> 2) Something that looks like a function call.
>
> ?
"Functional Programming" is a programming style that uses functions
as first class objects, favors declarative over procedural, and avoids
side effects.
"Functional Programming Languages" are languages that support that
style of programming.
"Pure Functional Programming Languages" are languages that support
that style of programming and try to prevent you from programming
in any other style.
It's not so much two definitions as it is a disagreement over whether
"functional" is a binary or an analog adjective. It's the same issue as
with "object oriented": i.e. can Python be considered an Object Oriented
Language if it's missing one of the "required" features ( like
encapsulation, for example) ?
For both Functional and O-O programming, the style evolved first, then
came better language support, and last came the academic purifiers.
List comprehensions are declarative (no loops) and they avoid side effects
(no loop variables or temporaries) -- plus they were originally used
in a pure functional language (Haskell) -- sounds like functional
syntax to me!
-- Steve Majewski
> List comprehensions are declarative (no loops) and they avoid side effects
> (no loop variables or temporaries)
No side effects? Try this:
L = [x for x in range(10)]
print x
filter(lambda x:x.f() and 0, items) ?
It's identical to the the reduce method posted previously, but avoids
the tuple indexing required by reduce's use of a binary operator vs.
filter's unary.
Of course my first preference would be the list comprehension,
discarding the redundant list, and if that was prohibitively expensive
falling back to the original imperative style.
Andrae Muys
Well, that's more of an "accidental" side effect.
Ideally, Guido would use his time machine to go back
and make for-loop control variables local to the
loop, so that the same could then be done for LCs.
Rumour has it that he tried to do just that, but
it turned out that some critical code in the time
machine's control software (which is written in
Python, of course) relies on side effects from
for-loop variables. So when he tried to make the
change, the time machine stopped working, preventing
him from having attempted to make the change in
the first place.
An even less substantiate rumour has it that
he is now working on translating all the time
machine software into Perl (or Ruby, depending
on who you talk to) so that this sort of problem
never happens again. Not that he will ever admit
to this, of course.
--
Greg Ewing, Computer Science Dept, University of Canterbury,
Christchurch, New Zealand
To get my email address, please visit my web page:
http://www.cosc.canterbury.ac.nz/~greg
map(type(x).f, items) solves the problem.
Pozdrawiam,
Baczek
--
Marek Baczyński aka Baczek UIN:57114871 RLU:201791 http://republika.pl/imbaczek
It is better to be a man without a home page than a man with a homepage created
using Microsoft Frontpage.
> Pete Shinners wyprodukowa˝[ao]?:
>
> > Donnal Walter wrote:
> >> But what is the functional equvalent of:
> >>
> >> for x in items:
> >> x.f()
> >
> > if all "items" are the same class, you could get away with this,
> >
> > map(class_of_x.f, items)
>
> map(type(x).f, items) solves the problem.
x looks like an unbound variable to me. map(type(items[0]).f, items) is
close but doesn't work for generators or mixed lists. If you really insist
on map, it looks like the right thing is map(lambda x: x.f(), items).
Yeah, but that's a bug.
<pulls hat down over head and ducks behind the desk>
-- Michael Chermside
As a result, I attached a dozen lines of code to my XML database
management module so that I can now generate sophistocated reports
from an HTML template with embedded string formatting operators (%) .
These refer to an embedded dictionary at the end of the HTML file
something like this:
<html>
<head><title>Prism: Progress Note</title></head>
<body>
<table width="100%%" cellpadding="5"><tr>
<td width="70" valign="top"><p>%(date)s</p></td>
<td>
<p><strong>Assessment and Plan:</strong></p>
<ol>
<li>%(ga)s wk newborn infant %(order)s, birthweight %(bw)s kg,
yesterday %(wt)s kg,<br />
chronologic age %(age)s, post-conceptual age %(pca)s wk. <br />
</li>
<li>Temperature control: %(heat)s
</li>
<li>Respiratory support: %(resp)s <br />
</li>
<li>Nutrition and Fluids:<br /> %(fen)s <br />
</li>
%(pList)s
</ol><br /><br />
<br /><br /><br />_______________________________________<br />
Donnal Walter, M.D., Attending Neonatologist
</td>
</tr></table>
<!-- <vars>{
'date': self.today.GetDate(),
'ga': self.birthGA.Get(),
'order': self.birthorder.Get(),
'bw': self.birthweight.Get(),
'wt': self.weight.Get(),
'age': self.age.Get(),
'pca': self.pca.Get(),
'heat': self.warmer.Get(),
'resp': self.respiratory.Get(),
'fen': (
IF(self.formula.Get(),
('____ cc/kg/day enteral of ' +
self.formula.Get() + '<br />'),
'') +
'____ cc/kg/day total fluids, ____ kcal/kg/day' +
'<br /> ____ cc/kg/hr urine output;' +
IF(self.lytes.Get(),
'<br />Na____, K____, Cl____, CO____,',
'')
),
'pList': CONCAT([('<li>' + x.label.Get() +
IF(len(x.meds),
('<ul>' +
CONCAT([('<li>' + y.label.Get() +
IF(y.dose.Get(),
(', ' +
y.dose.Get() + ' ' +
y.units.Get() + ' (' +
y.scaled.Get() + ' ' +
y.units.Get() + '/kg) ' +
y.route.Get() + ' every ' +
y.interval.Get() + ' hr; '),
'') +
'</li>'
) for y in x.meds]) +
'</ul>' ),
'') +
'</li>'
) for x in self.problems])
}</vars>
-->
</body></html>
Note especially the loops in the definition for pList (problem list).
The code that interprets this template is simply:
def Generate(self, filename):
"""filename = template file"""
IF = lambda a,b,c:(a and [b] or [c])[0]
CONCAT = lambda z:reduce((lambda x,y: x+y), z, ' ')
try: # try this
io = open(filename, 'r') # open read only
t = io.read() # read full text
io.close() # close file
i = string.find(t, '<vars>') # start of vars
j = string.find(t, '</vars>') # end of vars
s = t[:i] + t[j+7:] # remove "vars"
v = eval(t[i+6:j]) # make dictionary
return s % v # return string
except KeyError: # unless key error
return 'Key error in template' # then warning
def Write(self, template, output):
io = open(output, 'w')
io.write(self.Generate(template))
io.close()
Thanks again,
Donnal Walter
Are you sure that you don't prefer the PEP 279 alternatives:
xmap(), xfilter(), xzip() or generator comprehensions?
[ yield f(x) for x in items ]
or
xmap( f, items )
Raymond Hettinger
Actually, Guido would not use the time machine.
He assures me that exposing the looping variable was
done on purpose and that the alternative was considered
and dismissed. The rationale for exposing the loop
variable is to make the list comprehension perform
identically to its for-loop equivalent.
Raymond Hettinger a.k.a. rumour control
It COULD be a feature
despite its creepy-crawly,
six-legged, hive-dwelling,
crumb-eating nature.
Hard to tell.
Raymond Hettinger
@ @
\_/
> "Greg Ewing" <gr...@cosc.canterbury.ac.nz> wrote in message
> news:3C7AFA8B...@cosc.canterbury.ac.nz...
>
> > Well, that's more of an "accidental" side effect.
> > Ideally, Guido would use his time machine to go back
> > and make for-loop control variables local to the
> > loop, so that the same could then be done for LCs.
>
> Actually, Guido would not use the time machine.
> He assures me that exposing the looping variable was
> done on purpose and that the alternative was considered
> and dismissed. The rationale for exposing the loop
> variable is to make the list comprehension perform
> identically to its for-loop equivalent.
I think Greg's talking about the loop variable(s) in the _traditional_
for loop.
Just
Well while I'm drooling with anticipation with the approach of lazy
builtin's and generator comprehensions, they aren't much help here
where the problem was to "call f on x for x in items", compared to
what you suggest which is "call f with x for x in items".
Andrae