Python syntax in Lisp and Scheme

R

Raffael Cavallaro

Ken Shan said:
But in the style of programming that you advocate, as I understand
it, one does not need to give a name to function application from the
problem domain before using it.

No, one doesn't, as long as that function application is the one place
where the implementation of that bit of functionality needs to be
expressed.

However, if one is using that bit of functionality elsewhere, then it
only constitutes information overload to re-express the implementation
of that functionality yet again in that location. In such a case, that
function application should be named in the one place it is necessary
to express its implementation, and the named version used elsewhere.

Again, it comes down to uniqueness and necessity of exposition. If it
is only going to be expressed once, and there is no loss of clarity,
then use an anonymous function. In this sense anonymous functions are
no different than using the built-ins or primitives of the language.
If this is the place where this bit of functionality needs to be
defined, then, by all means, use anonymous functions to express that
implementation if it is easier.

But if that is not the one and only place where that bit of
functionality is used, then name it. If that is not the one and only
place where that functionality needs to be defined, then don't repeat
the implementation in a half dozen places. Implement it once, name it,
and use the name elsewhere.
 
R

Raffael Cavallaro

In the context in which the offsets are added, it isn't necessary to
know that the offsets are added using map, as opposed, for example, to
an interative construct, such as loop.

Sorry for the typo - that should be "iterative" of course.
 
K

Ken Shan

Raffael Cavallaro said:
No, one doesn't, as long as that function application is the one place
where the implementation of that bit of functionality needs to be
expressed.

The implementation of function application is definitely something
that doesn't need to be expressed in the vast majority of programs.
Moreover, function application is used in many places, far from just
one place. So according to you, I need to find a name for function
application, and not just any name -- it needs to be a name from the
problem domain. But what is a name for function application from the
cash register problem domain?
 
A

Alex Shinn

I have no problem with a HOF, as long as the HOF corresponds to
something in the language of the problem domain. But it doesn't here. I
think it is telling that your example is taken from the problem domain
of computer science (memoization of functions), not that of the domain.

Actually, my problem domain more often than not *is* computer science,
but you could also stick strictly to human language or whatever suits
your fancy.
If we were writing a program that simulated people running and swimming,
it's very doubtful that "quickly" would mean "memoize." "Quickly" would
mean, "with-increased-framerate," or something similar.

I don't see how a framerate is less computer-specific than memoization.
If you want to stay close to the original human language then it would
simply mean the act of running faster than usual.
(Note that with-increased-framerate would almost certainly be a
macro).

Not necessarily. In Scheme with- forms are almost never macros, and are
almost always passed anonymous functions as arguments.
In domains outside of functional programming and mathematics, the
concepts of the problem domain don't usually map to applicable HOFs.
People fall in love with HOFs because they are great tools for lower
level implementation. But I don't think they usually map well to the
concepts of problem domains other than mathematics and computer science.
Named functions and macros let us capture the power of HOFs inside a
vocabulary _and_ syntax that matches the problem domain.

You're switching to macros and HOFs when we were talking about anonymous
functions. If you are seriously arguing against the use of HOFs in
general then I think you have a lot to learn. Learn a Lisp (Scheme is
nice and clean) or one of the more functional languages like Haskell.
If you brought macros into the discussion with the idea that any direct
application of an anonymous function should be hidden with a macro then
I question whether your goal is really to achieve more legible code or
is just some irrational bias against anonymous functions?

If you want to program in logic as close to the problem domain as
possible, try a logic programming language like Prolog or CLIPS. You
may be disappointed because even in these languages you have to refer to
low-level details at times. Also you will find that an extremely useful
feature is not only anonymous functions but anonymous facts and rules.
If you want to wait until you can program explicitly in the
highest-level human language then I think you may be even more
disappointed. Firstly because as already mentioned human language makes
heavy use of anonymous functions and unnamed concepts in general. When
possible we combine existing ideas and use their compound forms directly
in speech without giving them a new name. Secondly because human
language is not well suited to exact specifications, which is why when
we try to nail down rules as specifically as possible we end up with
language like legalese.

If you want to tell computers what to do in natural human language,
trusting them to learn what you mean when you're ambiguous (through a
process of correcting them when they guess wrong) then that is an
admirable dream. But it's not programming.
 
R

Raffael Cavallaro

Ken Shan said:
So according to you, I need to find a name for function
application, and not just any name -- it needs to be a name from the
problem domain.

From the problem domain _at_that_level_. If, at that level, we're
dealing with array bounds checking (assuming, for the moment that
we're using a language that doesn't have that built in), then function
names like check-index, report-invalid-index-error, etc. are names
from the problem domain at that level.

The problem I see with the use of the typical anonymous functional
style is twofold:

1. The same functional idiom is repeated, but not abstracted (i.e.,
not named). This leads to unnecessary "programmer inlining," that is,
writing out the implementation everywhere it is used, rather than
naming it once, and using the name everywhere else.

2. The anonymous functional idioms map well to domains such as
arithmetic, mathematics, and functional programming itself. These same
idioms don't map so well to other domains. The more abstract the
program becomes (that is, the closer it moves to the problem domain,
and the farther it moves from the low level arithmetic and functional
abstractions) the less the anonymous functional idioms will correspond
to the existing concepts and vocabulary of the problem domain.
 
K

Ken Shan

Raffael Cavallaro said:
From the problem domain _at_that_level_. If, at that level, we're
dealing with array bounds checking (assuming, for the moment that
we're using a language that doesn't have that built in), then function
names like check-index, report-invalid-index-error, etc. are names
from the problem domain at that level.

I'm not sure if I understand your notion of problem-domain levels. For
instance, in a preceding example

amount_due = sum(item_prices) * (1 + tax_rate)

is the problem domain possibly "functions and their arguments", or is
the problem domain possibly "customer billing"? If the former, would
you rewrite the above expression with names in the problem domain, as in

amount_due = apply(*, apply(sum, item_prices), apply(+, 1, tax_rate)

or

amount_due = apply(apply, *,
apply(apply, sum, item_prices),
apply(apply, +, 1, tax_rate))

or

amount_due = apply(apply, apply, *,
apply(apply, apply, sum, item_prices),
apply(apply, apply, +, 1, tax_rate))

(when do I stop?)? If the latter, how would you recommend that I
(re)write the code... certainly, since the use of function application
is so pervasive in the above code, a human-readable name in the problem
domain is in order?
 
C

Christos TZOTZIOY Georgiou

Indeed. Had the first lisp been programmed on a 680x0, we would have
d0 and d1 instead of car and cdr, or worse, had it been done on 8086,
we would have ax and bx...

Perhaps on 680x0 they would be ca0 and cd0, or ca0r and cd0r. AFAIK car
stands for contents of address register and cdr for contents of contents
of data register. So, picking register 0 out of 8 (7 if you exclude a7
/ sp) address registers and register 0 out of 8 data registers is just a
choice on this hypothetical subject.

However, I have a suspicion that the "correct" names would be ca0r and
c(a0)r ...
 
D

David Rush

I've just about decided to killfile this whole thread, but I can't
let this one go by. Two unsubstantiated assertions do not make a bad
programming practice, no matter how hard you try.

The problem I see with the use of the typical anonymous functional
style is twofold:

How much programming have *you* done with anonymous functions? Or is this
complaint based on your esthetic reactions to a series of contrived
examples in usenet posts?
1. The same functional idiom is repeated, but not abstracted (i.e.,
not named). This leads to unnecessary "programmer inlining," that is,
writing out the implementation everywhere it is used, rather than
naming it once, and using the name everywhere else.

Not by this heavy user of anonymous functions. In fact one of the main
uses I have for anonymous functions is to *avoid* code duplication by
parameterizing over entire categories of functions.

Cut & Paste programming is bad practice in any language. IME, functional
programmers do it *less* often than those from other communities.
2. The anonymous functional idioms map well to domains such as
arithmetic, mathematics, and functional programming itself. These same
idioms don't map so well to other domains. The more abstract the
program becomes (that is, the closer it moves to the problem domain,
and the farther it moves from the low level arithmetic and functional
abstractions) the less the anonymous functional idioms will correspond
to the existing concepts and vocabulary of the problem domain.

Again, I disagree heartily. I use HO&AFs to enable greater levels of
abstraction since they allow me to abstract *outer* components of
functions while I pass in the site-specific portions. Control-structure-
like
functions are only a fairly trivial example of this kind of thing, but
I have in a mail-processing application 2 functions IF-FROM-LINE (used in
mbox file processing) and RFC822-COLLAPSE-HEADER (used in RFC822 header
processing) which both implement algorithms which are parameterized
by functions. This is vaguely similiar in spirit to the visitor pattern
from OO land, but much more flexible. Both of these functions are used
in multiple contexts where the anonymous functions contextualize the
operations performed under specific conditions in their implemented
algorithms. These operations have (so far) been strictly one-off animals.
In the event that I ever feel a need to re-use one of them I will simply
lift the anonymous function from its original source location, give it
a top-level name et voila - instant reuse.

david rush
 
R

Raffael Cavallaro

David Rush said:
I have in a mail-processing application 2 functions IF-FROM-LINE (used in
mbox file processing) and RFC822-COLLAPSE-HEADER (used in RFC822 header
processing) which both implement algorithms which are parameterized
by functions. This is vaguely similiar in spirit to the visitor pattern
from OO land, but much more flexible. Both of these functions are used
in multiple contexts where the anonymous functions contextualize the
operations performed under specific conditions in their implemented
algorithms. These operations have (so far) been strictly one-off animals.

I think you are in violent agreement with me.


1. If-from-line is a _named_ function, not an anonymous function. My
only objection was to _anonymous_ functions replacing named
abstractions, not to functional programming itself.
In the event that I ever feel a need to re-use one of them I will simply
lift the anonymous function from its original source location, give it
a top-level name et voila - instant reuse.

2. Which is precisely what I suggested in all of my previous posts.
I.e., if the anonymous function is used more than once, name it, and use
the name.
 
R

Rob Warnock

+---------------
| AFAIK car stands for contents of address register and
| cdr for contents of contents of data register.
+---------------

From the IBM 704 CPU instruction format:
CAR == "Contents of Address [part of] Register".
CDR == "Contents of Decrement [part of] Register".
See <URL:http://www.catb.org/~esr/jargon/html/C/cdr.html>.

Note that the PDP-10 AOBJP/AOBJN/BLKI/BLKO/PUSH/PUSHJ/POP/POPJ
instructions used a similar format, but with the "decrement" part
being a negative count in the upper half of the word (which was
*incremented* in parallel with the address in the lower half
[or in the case of POP & POPJ only, decremented in parallel with
the address]).


-Rob
 
R

Roy Smith

Note that the PDP-10 AOBJP/AOBJN/BLKI/BLKO/PUSH/PUSHJ/POP/POPJ
instructions used a similar format.

I havn't thought about that stuff for many years. Now you've made my
brain hurt again.
 
D

David Eppstein

It's certainly true that mathematicians do not _write_
proofs in formal languages. But all the proofs that I'm
aware of _could_ be formalized quite easily. Are you
aware of any counterexamples to this? Things that
mathematicians accept as correct proofs which are
not clearly formalizable in, say, ZFC?

I am not claiming that it is a counterexample, but I've always met
with some difficulties imagining how the usual proof of Euler's
theorem about the number of corners, sides and faces of a polihedron
(correct terminology, BTW?) could be formalized. Also, however that
could be done, I feel an unsatisfactory feeling about how complex it
would be if compared to the conceptual simplicity of the proof itself.[/QUOTE]

Which one do you think is the usual proof?
http://www.ics.uci.edu/~eppstein/junkyard/euler/

Anyway, this exact example was the basis for a whole book about what is
involved in going from informal proof idea to formal proof:
http://www.ics.uci.edu/~eppstein/junkyard/euler/refs.html#Lak
 
G

Greg Ewing (using news.cis.dfn.de)

Jacek said:
Yes, you use flet (or labels) if you want a local function definition,
and defun if you want a global one. Lisp caters for both
possibilities. Does Python ?

If you mean the ability to have a nested function definition
that actually defines a top-level function, then yes, it
does...

Python 2.2 (#1, Jul 11 2002, 14:19:37)
[GCC 3.0.4] on linux2
Type "help", "copyright", "credits" or "license" for more information..... global g
.... def g():
.... print "Urk!"
....Traceback (most recent call last):

Although I'm having a hard time imagining why you'd
actually *want* to do such a thing!
 
M

Michele Dondi

Which one do you think is the usual proof?
http://www.ics.uci.edu/~eppstein/junkyard/euler/

Uhmmm, let me see... 13! (no, not the factorial of 13)
Anyway, this exact example was the basis for a whole book about what is
involved in going from informal proof idea to formal proof:
http://www.ics.uci.edu/~eppstein/junkyard/euler/refs.html#Lak

D'Oh! Unfortunate choice of mine...


Michele
--
Comments should say _why_ something is being done.
Oh? My comments always say what _really_ should have happened. :)
- Tore Aursand on comp.lang.perl.misc
 
R

Raffael Cavallaro

Ken Shan said:
I'm not sure if I understand your notion of problem-domain levels. For
instance, in a preceding example

amount_due = sum(item_prices) * (1 + tax_rate)

is the problem domain possibly "functions and their arguments", or is
the problem domain possibly "customer billing"?

How about simple arithmetic, which is built into most computer languages.

However, if you do this often enough in your code (i.e., compute a
total, then add the tax), you migh want to have a named function, say
"total-with-tax," instead of just reimplimenting it every time you use
it. It's simply a matter of how much of what you're doing is specific to
the larger problem, how much is just arithmetic, using built-ins, and,
probably most importantly, how often you'll be repeting yourself in
exactly the same way.



[snip]
(when do I stop?)?

When you reach the built-ins of the language, of course. No need to
define a method called "add" in a language that has + as a built in
function (unless you're going to overload addition to do something that
the built-in function doesn't do yet.)

But the very telling larger picture issue is that there is such a
reluctance to name bits of code that are going to be used more than once.
 
S

Sampo Smolander

In comp.lang.scheme Andrew Dalke said:
Pascal Costanza:
Okay, I gave alternatives of "." and ">" instead of "car" and "cdr"
"." for "here" and ">" for "the rest; over there". These are equally
composable.
. == car
cadr == >.
caddr == >>.
cddr == >>

One can also go like:

1st == car
rst == cdr
1rst == cadr
1rrst == caddr
rrst == cddr

The benefit being, it's less messy to quote these in Usenet :)
 
R

Raffael Cavallaro

Alex Shinn said:
If you are seriously arguing against the use of HOFs in
general then I think you have a lot to learn.

No, I'm not arguing against HOFs in general. I'm arguing against the
repeated use of the _same_ anonymous function throughout code. These
should clearly be named funtions instead.

But I've apparently touched a nerve, because so many FPers seem to
equate eschewing repetition of the same anonymous functional idoim in
numerous places throughout ones code, with an attack on HOF use itself.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top