J
Joe Marshall
David Rush said:Actually I've noticed that I usually cut myself when I *switch* from
a dull knife to a sharp one.
Grasp the sharp knife by the *handle* when switching.
David Rush said:Actually I've noticed that I usually cut myself when I *switch* from
a dull knife to a sharp one.
:> I can't see why a LISP programmer would even want to write a macro.
: That's because you are approaching this with a fundamentally flawed
: assumption. Macros are mainly not used to make the syntax prettier
: (though they can be used for that). They are mainly used to add features
: to the language that cannot be added as functions.
Really? Turing-completeness and all that... I presume you mean "cannot
so easily be added as functions", but even that would surprise me.
(Unless you mean cannot be added _to_Lisp_ as functions, because I don't
know as much as I'd like to about Lisp's capabilities and limitations.)
David Rush said:Actually I've noticed that I usually cut myself when I *switch* from
a dull knife to a sharp one.
David Rush said:I would say that one of the reasons why I program in Scheme is
*because* I value simplicity and uniformity. The way that Python has
been described in this discussion make me think that I would really
*hate* Python for it's unecessary complications if I went back to it.
You left out the with-collector part.
But it's true that my examples are less convincing given the existence of
yield (which I had forgotten about). But the point is that in pre-yield
Python you were stuck until the langauge designers got around to adding
it.
I'll try to come up with a more convincing short example if I find some
free time today.
Alex said:[...] Fortunately, in either case, the rich
and stong suite of unit tests that surely accompanies such a
"mission-critical application" will easily detect the nefarious
deed and thus easily defang the nanoviruses' (nanovirii's? nanovirorum...?)
menace, [...]
Erann said:[...] But the point is that in pre-yield
Python you were stuck until the langauge designers got around to adding
it.
I'll try to come up with a more convincing short example if I find some
free time today.
You mean like an object olazy with olazy.x and olazy.y, where x mightIMHO, these discussions are less usefull when not accompanied by
specific examples. What are these macros good for? Some examples
where you might have difficulties with using ordinary functions:
1.) Inventing new control structures (implement lazy data structures,
You mean like case or such? It can be done, but Python could use a wayimplement declarative control structures, etc.)
You can generate code many ways in Python. What use case are you thinking of?=> This one is rarely needed in everyday application programming and
can easily be misused.
2.) Serve as abbreviation of repeating code. Ever used a code
generator? Discovered there was a bug in the generated code? Had
to fix it at a zillion places?
=> Macros serve as extremely flexible code generators, and there
is only one place to fix a bug.
=> Many Design Patterns can be implemented as macros, allowing you
to have them explicitly in your code. This makes for better
documentation and maintainability.
You can do this also.3.) Invent pleasant syntax in limited domains.
=> Some people don't like Lips' prefix syntax. It's changeable if you
have macros.
=> This feature can also be misused.
This also, but Python has so many possible compile times ;-)4.) Do computations at compile time instead of at runtime.
=> Have heard about template metaprogramming in the C++ world?
People do a lot to get fast performance by shifting computation
to compile time. Macros do this effortlessly.
Python is pretty sharp ;-)These are four specific examples which are not easy to do without
macros. In all cases, implementing them classically will lead to code
duplication with all the known maintainability issues. In some cases
misuse will lead to unreadable or buggy code. Thus, macros are
powerful tools for the hand of professionals. You have to know if you
want a sharp knife (which may hurt you when misused) or a less sharper
one (where it takes more effort to cut with).
a = 2
a = 1 + 1
a = math.sqrt(4)
a = int((sys.maxint+1) ** (1/31))
...all mean the same thing.
Alex said:[...] Fortunately, in either case, the rich
and stong suite of unit tests that surely accompanies such a
"mission-critical application" will easily detect the nefarious
deed and thus easily defang the nanoviruses' (nanovirii's?
nanovirorum...?) menace, [...]
Hans said:Hmm, if I recall correctly, in Latin the plural of 'virus' is 'virus'.
(I like to write 'virii' myself, knowing that it's wrong, but it
looks cute.
<my-first-name.my-last-name-0610030955090001@k-137-79-50-101.jpl.nasa.go
v>,
The net effect is a filter, but again, you need to stop thinking about the
"what" and start thinking about the "how", otherwise, as I said, there's
no reason to use anything other than machine language.
Answer 1: literal translation into Python. The closest analogue of
with-collector etc would be Python's simple generators (yield keyword)
and do-with-file-lines is expressed in python with a for loop. So:
def lines_with_some_property(some_file_name):
for l in some_file_name:
if some_property(l):
yield l
Your only use of macros in this example is to handle the with-collector
syntax, which is handled in a clean macro-free way by Python's "yield".
So this is unconvincing as a demonstration of why macros are a necessary
part of a good programming language.
Of course, with-collector could be embedded in a larger piece of code,
while using yield forces lines_with_some_property to be a separate
function, but modularity is good...
Answer 2: poetic translation into Python. If I think about "how" I want
to express this sort of filtering, I end up with something much less
like the imperative-style code above and much more like:
[l for l in some_file_name if some_property(l)]
I have no problem with the assertion that macros are an important part
of Lisp, but you seem to be arguing more generally that the lack of
macros makes other languages like Python inferior because the literal
translations of certain macro-based code are impossible or more
cumbersome. For the present example, even that argument fails, but more
generally you'll have to also convince me that even a freer poetic
translation doesn't work.
Andrew
(e-mail address removed)
David said:I don't know a lot about Python, so here is a question. Is something
along the following lines possible in Python?
(with-collectors (collect-pos collect-neg)
(do-file-lines (l some-file-name)
(if (some-property l)
(collect-pos l)
(collect-neg l))))
I actually needed something like this in some of my code...
Not using simple generators afaik. The easiest way would probably be to
append into two lists:
collect_pos = []
collect_neg = []
for l in some_file_name:
if some_property(l):
collect_pos.append(l)
else:
collect_neg.append(l)
If you needed to do this a lot of times you could encapsulate it into a
function of some sort:
def posneg(filter,iter):
results = ([],[])
for x in iter:
results[not filter(x)].append(x)
return results
collect_pos,collect_neg = posneg(some_property, some_file_name)
(function evenp)> (predicate-collect '(-5 -4 -3 -2 -1 0 1 2 3 4 5)
You mean like an object olazy with olazy.x and olazy.y, where x might
be an integer 123 and y might be the text of the latest bug python report
on sourceforge? Not so hard with properties (you'd proabably want to cache
the latest for y and not re-check for some reasonable interval, but that
doesn't change client code (unless you later decide you want the value to
be a tuple of (timestamp, text), etc.)
You mean like case or such?
You can generate code many ways in Python. What use case are you thinking of?
You can do this also.
This also, but Python has so many possible compile times ;-)
Python is pretty sharp ;-)
I think we need some realistic use cases for your "specific" [categories of]
examples in order to compare how problems would be approached.
David said:<my-first-name.my-last-name-0610030955090001@k-137-79-50-101.jpl.nasa.go
v>,
Answer 1: literal translation into Python. The closest analogue of
with-collector etc would be Python's simple generators (yield keyword)
and do-with-file-lines is expressed in python with a for loop. So:
def lines_with_some_property(some_file_name):
for l in some_file_name:
if some_property(l):
yield l
Your only use of macros in this example is to handle the with-collector
syntax, which is handled in a clean macro-free way by Python's "yield".
So this is unconvincing as a demonstration of why macros are a necessary
part of a good programming language.
Of course, with-collector could be embedded in a larger piece of code,
while using yield forces lines_with_some_property to be a separate
function, but modularity is good...
Answer 2: poetic translation into Python. If I think about "how" I want
to express this sort of filtering, I end up with something much less
like the imperative-style code above and much more like:
[l for l in some_file_name if some_property(l)]
I have no problem with the assertion that macros are an important part
of Lisp, but you seem to be arguing more generally that the lack of
macros makes other languages like Python inferior because the literal
translations of certain macro-based code are impossible or more
cumbersome. For the present example, even that argument fails, but more
generally you'll have to also convince me that even a freer poetic
translation doesn't work.
[snip]Bengt Richter said:Just thought of this: a generator list comprehension, so your could write [snip]
Has someone proposed this already? I seems a natural, unless
I am blindly optimistic, which is quite possible ;-)
^^^^^^^^^^^^^^David said:I don't know a lot about Python, so here is a question. Is something
along the following lines possible in Python?
(with-collectors (collect-pos collect-neg)
(do-file-lines (l some-file-name)
(if (some-property l)
(collect-pos l)
(collect-neg l))))
I actually needed something like this in some of my code...
Not using simple generators afaik. The easiest way would probably be to
append into two lists:
collect_pos = []
collect_neg = []
for l in some_file_name:
Pascal Costanza said:...but this means that
collect = []
for l in some_file_name
if some_property:
collect.append(l)
...is another solution for the single collector case. Now we have two
ways to do it. Isn't this supposed to be a bad sign in the context of
Python? I am confused...
Pascal Costanza said:I don't know a lot about Python, so here is a question. Is something
along the following lines possible in Python?
(with-collectors (collect-pos collect-neg)
(do-file-lines (l some-file-name)
(if (some-property l)
(collect-pos l)
(collect-neg l))))
I actually needed something like this in some of my code...
Not using simple generators afaik. The easiest way would probably be to
append into two lists:
collect_pos = []
collect_neg = []
for l in some_file_name:
if some_property(l):
collect_pos.append(l)
else:
collect_neg.append(l)
If you needed to do this a lot of times you could encapsulate it into a
function of some sort:
def posneg(filter,iter):
results = ([],[])
for x in iter:
results[not filter(x)].append(x)
return results
Um, about choosing names ...
collect_pos,collect_neg = posneg(some_property, some_file_name)
... for q in [(x,test(x),i) for i,x in enumerate(seq)]>>> seq = range(10)
>>> test = lambda x: x%3==0
>>> pos,neg = [(p,n) for p,n in[map(list,['']*2)]
[1, 2, 4, 5, 7, 8]>>> pos [0, 3, 6, 9]
>>> neg
Pascal Costanza said:What about dealing with an arbitrary number of filters?
An example:
(function evenp)
(lambda (n) (< n 0))
(lambda (n) (> n 3)))
(-4 -2 0 2 4)
(-5 -3 -1)
(5)
(1 3)
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.