Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Dr. Dobb's Python-URL! - weekly Python news and links (Dec 7)

1 view
Skip to first unread message

Cameron Laird

unread,
Dec 7, 2005, 4:08:05 PM12/7/05
to
QOTW: "... and to my utter surprise it worked." - Andrew Nagel on
his move from wxPython to programming Tkinter in desperation

"Python has more web application frameworks than keywords." - Skip
Montanaro (but probably others going back years)


Frithiof Andreas Jensen writes frankly on use of SNMP and netconf:
http://groups.google.com/group/comp.lang.python/msg/662032bf92670fd7

Perhaps your application needs something like "ping". Several
distinct ways to achieve that exist:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/ced60d60b5942f1f/

You're going to hear about reddit.com, and about how it's been
REimplemented in Python. Here's a fraction of the commentary:
http://reddit.com/blog/2005/12/night-of-living-python.html
http://www.aaronsw.com/weblog/rewritingreddit

Long discussions about Python documentation lead to no conclusion
this commentator knows how to summarize:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/767470cb3cbc24d5/
http://groups.google.com/group/comp.lang.python/browse_thread/thread/94e2e5244a90a274/

aum's pygene genetic-algorithm solver "includes full api
documentation, and an implementation of the travelling
salesman problem ...":
http://groups.google.com/group/comp.lang.python/browse_thread/thread/9901fe0f886893d6/

Jibes against the lambda-clingers lead eventually to serious
questions of style in regard to variable namespacing,
lifespan, cleanup, and so on:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/ad0e15cb6b8f2c32/

To say anything useful about IDEs apart from that one needs to
try each on for personal fit seems *very* difficult:
http://groups.google.com/group/comp.lang.python/browse_thread/thread/eca26b6e6617a591/


========================================================================
Everything Python-related you want is probably one or two clicks away in
these pages:

Python.org's Python Language Website is the traditional
center of Pythonia
http://www.python.org
Notice especially the master FAQ
http://www.python.org/doc/FAQ.html

PythonWare complements the digest you're reading with the
marvelous daily python url
http://www.pythonware.com/daily
Mygale is a news-gathering webcrawler that specializes in (new)
World-Wide Web articles related to Python.
http://www.awaretek.com/nowak/mygale.html
While cosmetically similar, Mygale and the Daily Python-URL
are utterly different in their technologies and generally in
their results.

For far, FAR more Python reading than any one mind should
absorb, much of it quite interesting, several pages index
much of the universe of Pybloggers.
http://lowlife.jp/cgi-bin/moin.cgi/PythonProgrammersWeblog
http://www.planetpython.org/
http://mechanicalcat.net/pyblagg.html

comp.lang.python.announce announces new Python software. Be
sure to scan this newsgroup weekly.
http://groups.google.com/groups?oi=djq&as_ugroup=comp.lang.python.announce

Steve Bethard, Tim Lesher, and Tony Meyer continue the marvelous
tradition early borne by Andrew Kuchling, Michael Hudson and Brett
Cannon of intelligently summarizing action on the python-dev mailing
list once every other week.
http://www.python.org/dev/summary/

The Python Package Index catalogues packages.
http://www.python.org/pypi/

The somewhat older Vaults of Parnassus ambitiously collects references
to all sorts of Python resources.
http://www.vex.net/~x/parnassus/

Much of Python's real work takes place on Special-Interest Group
mailing lists
http://www.python.org/sigs/

Python Success Stories--from air-traffic control to on-line
match-making--can inspire you or decision-makers to whom you're
subject with a vision of what the language makes practical.
http://www.pythonology.com/success

The Python Software Foundation (PSF) has replaced the Python
Consortium as an independent nexus of activity. It has official
responsibility for Python's development and maintenance.
http://www.python.org/psf/
Among the ways you can support PSF is with a donation.
http://www.python.org/psf/donate.html

Kurt B. Kaiser publishes a weekly report on faults and patches.
http://www.google.com/groups?as_usubject=weekly%20python%20patch

Cetus collects Python hyperlinks.
http://www.cetus-links.org/oo_python.html

Python FAQTS
http://python.faqts.com/

The Cookbook is a collaborative effort to capture useful and
interesting recipes.
http://aspn.activestate.com/ASPN/Cookbook/Python

Among several Python-oriented RSS/RDF feeds available are
http://www.python.org/channews.rdf
http://bootleg-rss.g-blog.net/pythonware_com_daily.pcgi
http://python.de/backend.php
For more, see
http://www.syndic8.com/feedlist.php?ShowMatch=python&ShowStatus=all
The old Python "To-Do List" now lives principally in a
SourceForge reincarnation.
http://sourceforge.net/tracker/?atid=355470&group_id=5470&func=browse
http://python.sourceforge.net/peps/pep-0042.html

The online Python Journal is posted at pythonjournal.cognizor.com.
edi...@pythonjournal.com and edi...@pythonjournal.cognizor.com
welcome submission of material that helps people's understanding
of Python use, and offer Web presentation of your work.

del.icio.us presents an intriguing approach to reference commentary.
It already aggregates quite a bit of Python intelligence.
http://del.icio.us/tag/python

*Py: the Journal of the Python Language*
http://www.pyzine.com

Archive probing tricks of the trade:
http://groups.google.com/groups?oi=djq&as_ugroup=comp.lang.python&num=100
http://groups.google.com/groups?meta=site%3Dgroups%26group%3Dcomp.lang.python.*

Previous - (U)se the (R)esource, (L)uke! - messages are listed here:
http://www.ddj.com/topic/python/ (requires subscription)
http://groups-beta.google.com/groups?q=python-url+group:comp.lang.python*&start=0&scoring=d&
http://purl.org/thecliff/python/url.html (dormant)
or
http://groups.google.com/groups?oi=djq&as_q=+Python-URL!&as_ugroup=comp.lang.python
There is *not* an RSS for "Python-URL!"--at least not yet. Arguments
for and against are occasionally entertained.


Suggestions/corrections for next week's posting are always welcome.
E-mail to <Pytho...@phaseit.net> should get through.

To receive a new issue of this posting in e-mail each Monday morning
(approximately), ask <cla...@phaseit.net> to subscribe. Mention
"Python-URL!".


-- The Python-URL! Team--

Dr. Dobb's Journal (http://www.ddj.com) is pleased to participate in and
sponsor the "Python-URL!" project.

Cameron Laird

unread,
Dec 7, 2005, 3:55:03 PM12/7/05
to python-...@python.org

David Isaac

unread,
Dec 8, 2005, 10:25:29 PM12/8/05
to

"Cameron Laird" <pytho...@phaseit.net> wrote in message
news:dn7ibf$id0$1...@lairds.us...

> Jibes against the lambda-clingers lead eventually to serious
> questions of style in regard to variable namespacing,
> lifespan, cleanup, and so on:
>
http://groups.google.com/group/comp.lang.python/browse_thread/thread/ad0e15cb6b8f2c32/


#evaluate polynomial (coefs) at x using Horner's ruledef horner(coefs,x):
return reduce(lambda a1,a2: a1*x+a2,coefs)'Nuf said.Alan Isaac


Cameron Laird

unread,
Dec 9, 2005, 11:08:02 AM12/9/05
to
In article <JO6mf.116$sF2.31@trnddc02>,

No.

That is, this follow-up does *not* say enough for me to have confidence
of its intent. Leaving aside such formalities as the relation between
"Alan Isaac" and "David Isaac", I *think* you're supporting a claim
about the value of lambda with a specific example. Do I have that
right? Are you saying that your definition of horner() would suffer
greatly without lambda?

Cameron Laird

unread,
Dec 9, 2005, 1:08:02 PM12/9/05
to
In article <mailman.1852.1134050506.1...@python.org>,
I reported:
.
.
.

>"Python has more web application frameworks than keywords." - Skip
>Montanaro (but probably others going back years)
.
.
.
Incorrect. Thanks to Fredrik Lundh, who rather miraculously intuited
that this was a mechanical error, and that my real intention was to
highlight what Harald Armin Massa (and others, most likely) had earlier
quipped:
http://article.gmane.org/gmane.comp.python.general/435579
http://online.effbot.org/2004_06_01_archive.htm#europython-1

sk...@pobox.com

unread,
Dec 9, 2005, 1:48:11 PM12/9/05
to Cameron Laird, pytho...@python.org

Cameron> In article <mailman.1852.1134050506.1...@python.org>,
Cameron> I reported:

>> "Python has more web application frameworks than keywords." - Skip
>> Montanaro (but probably others going back years)

Cameron> Incorrect. Thanks to Fredrik Lundh ...

Yeah, I wondered about that. I was only parroting what I'd seen in Harald's
post. I just couldn't remember who'd said it.

Skip

David Isaac

unread,
Dec 9, 2005, 6:19:27 PM12/9/05
to
>>> Jibes against the lambda-clingers lead eventually to serious
>>> questions of style in regard to variable namespacing,
>>> lifespan, cleanup, and so on:
>>>
http://groups.google.com/group/comp.lang.python/browse_thread/thread/ad0e15cb6b8f2c32/

Alan Isaac <ais...@verizon.net> wrote:
>> #evaluate polynomial (coefs) at x using Horner's rule
>> def horner(coefs,x): return reduce(lambda a1,a2: a1*x+a2,coefs)

"Cameron Laird" <pytho...@phaseit.net> wrote in message
news:dn7ibf$id0$1...@lairds.us...


> I *think* you're supporting a claim
> about the value of lambda with a specific example. Do I have that
> right? Are you saying that your definition of horner() would suffer
> greatly without lambda?

It is a simple example of how lambda and reduce can be very expressive.
Anyone who understands Horner's rule can see at a glance that this code
implements it. Anyone who has bothered to learn what lambda and reduce
do can see at a glance what the algorithm is.

It just cannot get simpler or more expressive.

Suffer greatly? Surely not. For "suffer greatly" you would probably need
to turn to people who do a lot of event-driven GUI programming.
But suffer, yes. Simplicity and expressiveness are valuable.
That is the point.

Cheers,
Alan Isaac

Peter Otten

unread,
Dec 10, 2005, 4:27:09 AM12/10/05
to
Alan aka David Isaac wrote:

>>> #evaluate polynomial (coefs) at x using Horner's rule
>>> def horner(coefs,x): return reduce(lambda a1,a2: a1*x+a2,coefs)

> It just cannot get simpler or more expressive.

But is it correct?

>>> a0, a1, a2 = 1, 2, 3
>>> x = 2
>>> a0 + x*(a1 + x*(a2))
17
>>> def horner(coefs, x): return reduce(lambda a1, a2: a1*x + a2, coefs)
...
>>> horner([a0, a1, a2], x)
11

Are we merely employing different conventions for the order of coefficients
or is that simple and expressive lambda/reduce stuff obscuring an error?

Peter

bon...@gmail.com

unread,
Dec 10, 2005, 4:34:34 AM12/10/05
to
I think horner needs the coefs be "reversed", comparing with how we
like to express polynomial in general, that is how I read those math
formulas about horner anyway.

Fredrik Lundh

unread,
Dec 10, 2005, 6:43:20 AM12/10/05
to pytho...@python.org
skip wrote:

> >> "Python has more web application frameworks than keywords." - Skip
> >> Montanaro (but probably others going back years)
>

> Cameron> Incorrect. Thanks to Fredrik Lundh ...
>
> Yeah, I wondered about that. I was only parroting what I'd seen in Harald's
> post. I just couldn't remember who'd said it.

the oldest reference I have is from june 2004:

http://online.effbot.org/2004_06_01_archive.htm#europython-1

cheers /F

Chris Mellon

unread,
Dec 10, 2005, 8:06:37 AM12/10/05
to pytho...@python.org

As someone who does a tremendous amount of event-driven GUI
programming, I'd like to take a moment to speak out against people
using us as a testament to the virtues of lamda. Event handlers are
the most important part of event-driven code, and making them real
functions with real names is crucial to maintainable code. The only
reason to ever use a lamdba in Python is because you don't want to
give a function a name, and that is just not a compelling use case for
GUI events.

> Cheers,
> Alan Isaac
>
>
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>

David Isaac

unread,
Dec 12, 2005, 12:45:57 AM12/12/05
to

> Alan Isaac wrote:
> >>> #evaluate polynomial (coefs) at x using Horner's rule
> >>> def horner(coefs,x): return reduce(lambda a1,a2: a1*x+a2,coefs)
> > It just cannot get simpler or more expressive.


"Peter Otten" <__pet...@web.de> wrote in message
news:dne702$j1q$02$1...@news.t-online.com...
> But is it correct?

Yes.

> Are we merely employing different conventions for the order of
coefficients
> or is that simple and expressive lambda/reduce stuff obscuring an error?

It is too simple and expressive to obscure an error. ;-)
This is particularly important since coefficient order is not standardized
across uses.

Cheers,
Alan Isaac


David Isaac

unread,
Dec 12, 2005, 1:02:47 AM12/12/05
to

"Chris Mellon" <ark...@gmail.com> wrote in message
news:mailman.1945.1134220...@python.org...

> As someone who does a tremendous amount of event-driven GUI
> programming, I'd like to take a moment to speak out against people
> using us as a testament to the virtues of lamda. Event handlers are
> the most important part of event-driven code, and making them real
> functions with real names is crucial to maintainable code. The only
> reason to ever use a lamdba in Python is because you don't want to
> give a function a name, and that is just not a compelling use case for
> GUI events.

Obviously opinions differ. See the discussion at
http://www.artima.com/forums/flat.jsp?forum=106&thread=98196&start=30&msRange=15
I find many of the pleas for lambda persuasive as well.
For the contribution of lambda to maintainability,
see e.g. Gary Robinson's comment at that link.

Alan Isaac


Paul Rubin

unread,
Dec 12, 2005, 1:52:17 AM12/12/05
to
Chris Mellon <ark...@gmail.com> writes:
> As someone who does a tremendous amount of event-driven GUI
> programming, I'd like to take a moment to speak out against people
> using us as a testament to the virtues of lamda. Event handlers are
> the most important part of event-driven code, and making them real
> functions with real names is crucial to maintainable code. The only
> reason to ever use a lamdba in Python is because you don't want to
> give a function a name, and that is just not a compelling use case for
> GUI events.

I thought stuff like the following was idiomatic in GUI programming.
Do you really want separate names for all those callbacks?

# generate calculator keypad buttons
Button(label='7', command=lambda: user_pressed(7)).grid(column=1, row=1)
Button(label='8', command=lambda: user_pressed(8)).grid(column=2, row=1)
Button(label='9', command=lambda: user_pressed(9)).grid(column=3, row=1)

Button(label='4', command=lambda: user_pressed(4)).grid(column=1, row=2)
Button(label='5', command=lambda: user_pressed(5)).grid(column=2, row=2)
Button(label='6', command=lambda: user_pressed(6)).grid(column=3, row=2)
...

Steven Bethard

unread,
Dec 12, 2005, 2:46:28 AM12/12/05
to

While I don't spend much time on GUIs, code like that would scream
"refactor" to me, e.g. something like:

class UserPressedButton(Button):
def __init__(self, i):
def command():
return user_pressed(i)
Button.__init__(self, label=str(i), command=command)

Button(7).grid(column=1, row=1)
Button(8).grid(column=2, row=1)
Button(9).grid(column=3, row=1)

Button(4).grid(column=1, row=2)
Button(5).grid(column=2, row=2)
Button(6).grid(column=3, row=2)

STeVe

Fredrik Lundh

unread,
Dec 12, 2005, 3:15:38 AM12/12/05
to pytho...@python.org
Steven Bethard wrote:

> > I thought stuff like the following was idiomatic in GUI programming.
> > Do you really want separate names for all those callbacks?
> >
> > # generate calculator keypad buttons
> > Button(label='7', command=lambda: user_pressed(7)).grid(column=1, row=1)
> > Button(label='8', command=lambda: user_pressed(8)).grid(column=2, row=1)
> > Button(label='9', command=lambda: user_pressed(9)).grid(column=3, row=1)
> >
> > Button(label='4', command=lambda: user_pressed(4)).grid(column=1, row=2)
> > Button(label='5', command=lambda: user_pressed(5)).grid(column=2, row=2)
> > Button(label='6', command=lambda: user_pressed(6)).grid(column=3, row=2)
> > ...
>
> While I don't spend much time on GUIs, code like that would scream
> "refactor" to me, e.g. something like:
>
> class UserPressedButton(Button):
> def __init__(self, i):
> def command():
> return user_pressed(i)
> Button.__init__(self, label=str(i), command=command)
>
> Button(7).grid(column=1, row=1)
> Button(8).grid(column=2, row=1)
> Button(9).grid(column=3, row=1)
>
> Button(4).grid(column=1, row=2)
> Button(5).grid(column=2, row=2)
> Button(6).grid(column=3, row=2)

a temporary factory function should be sufficient:

def digit(label, x, y):
def callback():
# print "BUTTON PRESS", label # debug!
user_pressed(int(label))
Button(label=label, command=callback).grid(column=x, row=y)

# create numeric pad
digit("7", 1, 1); digit("8", 2, 1); digit("9", 3, 1)
digit("4", 1, 2); digit("5", 2, 2); digit("6", 3, 2)
digit("1", 1, 3); digit("2", 2, 3); digit("3", 3, 3)

are people still missing that local functions are inexpensive in Python ?

</F>

bon...@gmail.com

unread,
Dec 12, 2005, 3:39:08 AM12/12/05
to
Well, that depends. This kind of coding many times are result of quick
copy and paste. Whether it worths to abstract things out really depends
on the life span. If it ends up never got touch again, the advntage of
lambda is that I can just have it as is, it works, is clear to
understand and everything is in place. I thought that is one of the
advantage of python or quick prototyping.

This also is not a very good example as it shows some form of
repetitiveness that is "screaming for refactoring". Many times, these
fields are similar but have no common functionalities.

Paul Rubin

unread,
Dec 12, 2005, 3:48:33 AM12/12/05
to
"Fredrik Lundh" <fre...@pythonware.com> writes:
> a temporary factory function should be sufficient:
>
> def digit(label, x, y):
> def callback():
> # print "BUTTON PRESS", label # debug!
> user_pressed(int(label))
> Button(label=label, command=callback).grid(column=x, row=y)

Looking at the calculator program I wrote a while back (one of my
first Python programs, written just to play with tkinter), I see that
I actually did something like that for the buttons. However, it also
contained (in the other order):

unops = {'sqrt': math.sqrt,
'sin': math.sin,
'cos': math.cos,
'tan': math.tan,
'ln': math.log,
'log': lambda x: math.log(x)/math.log(10),
'clr x': lambda x: 0
}

binops = {'+': (lambda x,y: x+y),
'-': (lambda x,y: x-y),
'*': (lambda x,y: x*y),
'/': (lambda x,y: x/y),
'**': (lambda x,y: x**y)
}

How would you refactor that, with no lambda?

Paul Rubin

unread,
Dec 12, 2005, 3:51:10 AM12/12/05
to
Paul Rubin <http://phr...@NOSPAM.invalid> writes:
> binops = {'+': (lambda x,y: x+y),
> '-': (lambda x,y: x-y),
> '*': (lambda x,y: x*y),
> '/': (lambda x,y: x/y),
> '**': (lambda x,y: x**y)
> }
> How would you refactor that, with no lambda?

Ok, with operator.add and so forth. I don't remember if I knew about
those at the time. You can easily see though, how additional such
simple functions might be wanted, that aren't in the operator module.

bon...@gmail.com

unread,
Dec 12, 2005, 3:59:38 AM12/12/05
to

Or, why would you want to refactor that ? The lambdas were used as the
quickest and the most straight forward way to have the solution back
then I believe. Refactoring is an aftermath(performance, frequent
change to the same module for feature changes etc.).
Without lambda, even the first version would force the programmer to
think more about how to factor it and it seems in this case, not
necessary and waste of precious programmer time.

Paul Rubin

unread,
Dec 12, 2005, 4:28:42 AM12/12/05
to
bon...@gmail.com writes:
> > How would you refactor that, with no lambda?
> Or, why would you want to refactor that ?

I like it the way it was written. I'm not the one saying lambda is bogus.

Bengt Richter

unread,
Dec 12, 2005, 6:13:29 AM12/12/05
to

OTOH, (untested)

for label, x, y in ((str(d+1), d%3+1, 3-d//3) for d in xrange(9)):
Button(label=label, command=lambda d=int(label):user_pressed(d)).grid(column=x, row=y)

or

for tup in ((str(d+1), d%3+1,3-d//3) for d in xrange(9)): digit(*tup)

tweak 'til correct ;-)

Regards,
Bengt Richter

Paul Rubin

unread,
Dec 12, 2005, 6:37:41 AM12/12/05
to
bo...@oz.net (Bengt Richter) writes:
>
> for tup in ((str(d+1), d%3+1,3-d//3) for d in xrange(9)): digit(*tup)
>
> tweak 'til correct ;-)

GMTA. See:

http://www.nightsong.com/phr/python/calc.py

written a couple years ago. It uses:

for i in xrange(1,10):
add_button(5+2-(i-1)/3, (i-1)%3, str(i))

Christopher Subich

unread,
Dec 13, 2005, 10:11:33 AM12/13/05
to
Chris Mellon wrote:
> functions with real names is crucial to maintainable code. The only
> reason to ever use a lamdba in Python is because you don't want to
> give a function a name, and that is just not a compelling use case for
> GUI events.

Ah, but that neglects the sheer utility of delayed-evaluation
expressions. Consider the key= parameter to list.sort, et. al:

complicated_list.sort(key=lambda x: x[3])

Decorate-sort-undecorate is another way of doing this, but it's also
boilerplate, involves list copies that have nothing to do with the flow
of the program itself, and can possibly error (if done naively: key is
comparable, but complex_list[i][0] isn't comparable, such as sorting a
list of complex numbers by the real part, if two or more items have the
same real).

The key= parameter was implemented just to make this sort of thing
clearer and easier (and, in an odd way, actually more semantically
explicit). The utility of a full function for the key= is nice and
necessary, but simultaneously a lot of the uses are going to be for
one-off expressions (like item[3]). There, the idea of a named function
seems conceptual overkill.

The most significant problem with Python's lambda is that it's billed as
an anonymous function, when it's really an encapsulated expression. My
preferred solution is to replace lambda with something along the lines
of an 'expression comprehension,' with similar syntax to list and
generator comprehensions as-is:

lambda param1, param2: stuff_with(param2,param1) would become

<(param1, param2): stuff_with(param2, param1)>
or, to become even more similar to comprehension syntax:
<stuff_with(param2, param1) with (param1, param2)>

The only real problem, parsing-wise, with this syntax is that it can
sometimes conflict with the << or >> operators if used without
whitespace near comparisons.

The scope of what can be contained in the expression comprehension
(lambda currently) is exactly the same as what can be contained in a
list/generator comprehension, so why not capitalize on the parallelism?

Marc 'BlackJack' Rintsch

unread,
Dec 14, 2005, 7:03:10 PM12/14/05
to
In <dnmobd$5a0$1...@rumours.uwaterloo.ca>, Christopher Subich wrote:

> Chris Mellon wrote:
>> functions with real names is crucial to maintainable code. The only
>> reason to ever use a lamdba in Python is because you don't want to
>> give a function a name, and that is just not a compelling use case for
>> GUI events.
>
> Ah, but that neglects the sheer utility of delayed-evaluation
> expressions. Consider the key= parameter to list.sort, et. al:
>
> complicated_list.sort(key=lambda x: x[3])

This can be written as::

from operator import itemgetter
complicated_list.sort(key=itemgetter(3))

Ciao,
Marc 'BlackJack' Rintsch

bon...@gmail.com

unread,
Dec 14, 2005, 9:56:56 PM12/14/05
to
Though I find the lambda form easier for me to understand but
itemgetter should be the preferred way as it should have some
performance advantage and sort are those kind of functions that need
it, in general.

Cameron Laird

unread,
Dec 16, 2005, 2:08:02 PM12/16/05
to
In article <mailman.1984.1134375...@python.org>,
Fredrik Lundh <fre...@pythonware.com> wrote:
.
.
.

> # create numeric pad
> digit("7", 1, 1); digit("8", 2, 1); digit("9", 3, 1)
> digit("4", 1, 2); digit("5", 2, 2); digit("6", 3, 2)
> digit("1", 1, 3); digit("2", 2, 3); digit("3", 3, 3)
.
.
.
I confess that this sort of thing often tempts me to

for (numeral, row, column) in [
(7, 1, 1), (8, 2, 1), (9, 3, 1),
(4, 1, 2), (5, 2, 2), (6, 3, 2),
(1, 1, 3), (2, 2, 3), (3, 3, 3)]:
digit(str(numeral), row, column)

0 new messages