Re: [Edu-sig] quantum instance
Arthur wrote: Scott David Daniels wrote: [EMAIL PROTECTED] wrote: I think teaching programming outside a context - as an abstract discipline - is unavoidably problematic in this regard. I would have more sympathy if you would subscribe to the same philosophy for geometry and mathematics. As someone who has concentrated on computer science and The Art of Computer Programming for a huge number of years, I am offended at the denigration of my field of study (or at least what I perceive to be a denigration). OK, here I may have been unclear. TAoCP is a set of books I love, but I was, in fact, referring to the art of computer programming, and engaging in a bit of a pun. It seems to have helped confuse the issue. I also understand most of the best programmers I know are not computer scientists, though many of them read in it from time to time. And I would have more sympathy if you were willing to deal separattely and distinctly with computer science, as science and the Art of Computer Programming as an art. OK, we are getting to a nub here, but we are also moving to my personal biases rather than that of the field itself. I went to the Univ. of Penn., where Mathematics was definitely classified an Art; even Applied Math. I view computer programming as an Art, not engineering nor a science. The art is in the clear expression of a solution to a problem. Much of what you need to know to develop that art involves things like brushwork -- technical skills at which you must become proficient in order to work (the _craft_ part of computer programming), but the art lies not only in a perfected craft, but an ability to see a problem and find a solution that seems obvious once found. But, to confuse the issue a bit, I also find Mathematics and Computer Science equally arts. I personally have very little interest in (but great respect for) the former [Computer Science], and a good deal of personal interest in the latter [Computer Programming]. Maybe its harder for those who started by writing machine code to make the distinction than it is for those of us who only came to the party when and because high level languages were developed. It is indeed stimulating and challenging to attempt to communicate with a complex machine, and do so with elegance. Ah -- is that what computer science is to you, or is it programming? In my view the communication is with the reader of the program (who may be reading for the joy, but more likely is reading in order to alter). But I don't find it difficult at all to maintain that the pursuit is different in nature from the study of mathematics and geometry. Some would argue that mathematics and geometry are there whether we as a race are or are not. Certainly though they are there whether my machine powers up or does not. I am not convinced programming as a stand-alone subject cannot be optimum as an approach. Could you restate this? I presume (but am unsure) this means: I believe teaching programming without computer science is optimal. I believe computer science is a stand alone subject, and that programming is natural in the context of a computer science curriculum. But I do that think someone like yourself is in fact actually studying programming in a particular context. Maybe its most general context. But a quite specific context nonetheless. Hmmm. I think you know me less than you think you do. I think a core computer science question is how efficiently some values can _ever_ be calculated, based on as few assumptions as we can get away with making about the nature of the machines (and languages) doing the computation. These kinds of results should inform how you (or even whether you attempt to) build programs to solve these problems. Perhaps an attempt to liberate programming from the control of computer scientists is bound to annoy a computer scientist, a bit. ;) I suppose you might call me a computer scientist, but if so I am an amateur computer scientist; my CS is from the love of the ideas, not from a compensated position. My pay has come, almost exclusively, from being a programmer. I would say that writing computer programs without an understanding of computer science is certainly possible (and I've worked with lots of people who do so), but to write well, and to write are not the same skill at all. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] quantum instance
Scott David Daniels wrote: Arthur wrote: I am not convinced programming as a stand-alone subject cannot be optimum as an approach. Could you restate this? The art is in the clear expression of a solution to a problem.. and but the art lies not only in a perfected craft, but an ability to see a problem and find a solution that seems obvious once found. What problem? What context for problems? How to we avoid learning to program as a game of make beleive, attacking self- referential problems that have already been solved. How do we break the cycle of the best programmers solving the problem of making the best IDE that can be used by the best programmers - to make better IDEs? Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] quantum instance
Scott David Daniels wrote: I would say that writing computer programs without an understanding of computer science is certainly possible (and I've worked with lots of people who do so), but to write well, and to write are not the same skill at all. Let me sign on to your point of view. I am writing for other human beings. But which other human beings? A little ditty I had written here was judged harshly (and incorrectly, I believe), because it spoke in a vocabulary of finance - to programmers. Can someone whose first identity is as a programmer judge the writing of someone whose is not. Back to where I started to get testy: properties and decorators I honestly believe that if I had seen them in my first Python Triangle class I would have judged myself to be looking at a language that might be swell - for somebody else. But a little too magical, self-referential and self-involved - for my own taste. And would have moved on. Which might have saved the Python community from the annoyances of one annoying guy. But I can imagine someone with my sensibilities - just a lot less annoying - having moved on, and think that would have been a shame. Is that really how we do a Triangle in Python today? Can we accept the less sophisticated appraoches on equal footing? Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
[Edu-sig] Draft math/CS stuff (satacad 6938)
I'd be happy if anyone wants to comment on and/or mess with the code below. It's what I'm working on for my upcoming Saturday Academy class, which uses a combination of Python and POV-Ray to teach geometry. http://www.saturdayacademy.org/classes/ClassDetail.aspx?id=6938 Some of my background info is on file here (another list) i.e. I talk about what's unfinished: http://mail.geneseo.edu/pipermail/math-thinking-l/2005-September/000840.html plus I'm still looking at properties, and continuing some recent threads re pedagogy here on our edu-sig list. Also, math-think-l unindented/trashed the source, perhaps because I submitted in rich text through gmail, whereas a plain text submission might've gotten through unscathed (??). Kirby = class Vector(object): color = 'Red' def __init__(self, xyz): self.xyz = xyz def write(self): basic = cylinder 0,0,0, %s,%s,%s, 0.1 % self.xyz return %s %s % (basic, pigment { color %s } % self.color) def __repr__(self): return Vector %s, %s, %s % self.xyz def __mul__(self, scalar): xyz = tuple([scalar * i for i in self.xyz]) return Vector(xyz) def __add__(self, other): xyz = tuple([ i+j for i,j in zip(self.xyz, other.xyz)]) return Vector(xyz) def _get_xyz(self): return '%s, %s, %s' % self.xyz def _get_length(self): return pow(sum([i**2 for i in xyz]), 0.5) coords = property(_get_xyz) length = property(_get_length) class Edge(object): color = 'Red' def __init__(self, v0, v1): self.v0 = v0 self.v1 = v1 def __repr__(self): return Edge %s, %s % (self.v0.coords, self.v1.coords) def write(self): basic = cylinder %s, %s, 0.1 % (self.v0.coords, self.v1.coords) return %s %s % (basic, pigment { color %s } % self.color) class Polyhedron(object): color = 'Red' def __init__(self, vertsdict, faces): self.verts = vertsdict self.faces = faces self.edges = self._get_edges() def __repr__(self): return Polyhedron: %s edges, %s faces \ % (len(self.edges), len(self.faces)) def _get_edges(self): # stub procedure: take a list of face-tuples and distill # all the unique edges, e.g. ((1,2,3)) = ((1,2),(2,3),(3,1)) # e.g. icosahedron has 20 faces and 30 unique edges # ( = cubocta 24 + tetra's 6 edges to squares per jitterbug) pass def write(self): # stub procedure -- needs to be completed return 'write out edges' def __mul__(self, scalar): newvectors = {} for v in self.verts: newvectors[v] = self.verts[v] * scalar return Polyhedron(newvectors, self.faces) class Header (object): # defaults bgcolor = color Gray50 lightloc = 300, 300, -1000 lightcolor = White @staticmethod def write(): return #include colors.inc background { %(bgcolor)s } light_source{ %(lightloc)s %(lightcolor)s } % Header.__dict__ class Camera (object): # defaults look_at = 0 location = '0, .1, -25' @staticmethod def write(): return camera { location %(location)s look_at %(look_at)s angle 30 } % Camera.__dict__ def buildicosa(): phi = (1 + pow(5,0.5))/2.0 verts = {# 2*phi x 2 rectangle in XZ 1:Vector((-phi, 0, -1)), 2:Vector((-phi, 0, 1)), 3:Vector(( phi, 0, 1)), 4:Vector(( phi, 0, -1)), # 2*phi x 2 rectange in XY 5:Vector(( -1, phi, 0)), 6:Vector(( 1, phi, 0)), 7:Vector(( 1, -phi, 0)), 8:Vector(( -1, -phi, 0)), # 2*phi x 2 rectange in YZ 9:Vector(( 0, 1, phi)), 10:Vector(( 0, -1, phi)), 11:Vector(( 0, -1, -phi)), 12:Vector(( 0, 1, -phi))} faces = ((5,6,9),(5,6,2),(5,12,1),(5,6,1),(5,1,2), (11,1,12),(11,12,4),(11,1,8),(11,4,7),(11,7,8), (4,12,6),(4,6,3),(4,3,7), (3,9,6),(3,6,4), (10,7,8)) #unfinished return verts, faces def main(): icosa = Polyhedron(*buildicosa()) f = file('icosa.pov','w') Camera.location = '0, 2, -20' print f, Header.write() print f, Camera.write() print f, icosa.write() f.close() if __name__ == '__main__': main() ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] quantum instance
Arthur wrote: Back to where I started to get testy: properties and decorators I honestly believe that if I had seen them in my first Python Triangle class I would have judged myself to be looking at a language that might be swell - for somebody else. But a little too magical, self-referential and self-involved - for my own taste. And would have moved on. I understand that properties and decorators look like obscure magic. I ask you to suspend judgment on those (an act of faith), until you understand why such features seriously assist the readability of code and designs. This act of faith can be based on a respect for the obvious effort somebody has gone to in other ways to make Python such a clear and simple language. I don't object to your not wanting to use such constructs, but rather to your desire to remove them from the language (or veto adding them) in order to make it simpler. I'm sure others have said as much about the ridiculous idea of making a value for the square root of minus one, or for the incomprehensibly strained line at infinity. When you ask what these features provide, I try to explain how they make it possible to write some very clear simple code. I think Kirby will attest to the fact that decorators seriously improved the readability of his hypertoons code. Decorators should be used sparingly, if at all. That is not to say they shouldn't exist. The key to understanding when decorators are useful can be summarized as whenever you feel you are writing boilerplate your skin should itch. This doesn't mean that you should not write boilerplate on occasion, but rather that you should be searching for a way around it. I tried to explain to you why I found properties such a useful addition. Their existence allows me to write code without the protective generality of always writing accessors and mutators in case, some two years hence, I need to change more than the single attribute on a mutation, or decide some value that I have been storing is much better left calculated. This was unconvincing to you, but you responded more in the vein of nobody should be allowed to use this, so the code I read is simpler. I am surprised you accept exceptions (a relatively recent development in the design of computer languages). The rule I use in commenting code is that you should not comment use of features of a language in code written in that language. Programmers who read code written in Python are responsible for learning Python, and there is no excuse for code like: a = range(12) # Make a list of integers between 0 and 11 inclusive The comment slows down your reading of the code and distracts you from reading the application itself. The language is the given. When you choose a language, you buy its tradeoffs. If you cannot stand descriptors, insist on python 2.3. When you ask what something is good for, and get given an explanation that turns out to not make your life simpler, don't presume that the examples given are therefore useless. You have not spent a career writing code that must be rewritten constantly (to accommodate changing requirements); properties help in that task, in part because you can avoid using them until necessary, with their existence in your back pocket. Can we accept the less sophisticated approaches on equal footing? We can accept the less sophisticated approach to designing programs as workable. Do you seriously think that when designing a language equal weight should be given to those that understand the implications of a decision and those who go with their gut? It is one thing to make ivory tower decisions, and another to know the impact a decision might have. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] quantum instance
Scott David Daniels wrote: I understand that properties and decorators look like obscure magic. I ask you to suspend judgment on those (an act of faith), until you understand why such features seriously assist the readability of code and designs. This act of faith can be based on a respect for the obvious effort somebody has gone to in other ways to make Python such a clear and simple language. No faith. If that were me I'd be writing protected before my methods knowing there was a damn good reason for it. That I was practicing good objected oriented design. And that I was solving a problem I just didn't happen to know I had, but most assuredly did. If language design decisions were not all about trade-offs, language design would be easy. It would be as silly for me to suggest that properties and decorators do not bring advantages as it would be for you to suggest that those advantages come for free. My argument though is with you, not Guido. It is about use cases for existing features, not about the features themselves. And in the particular case of properties, it was only in going back to Guido's own use case illustration that I begin to develop some comfort with why properties are there - why they are a neat solution to a limited set of problems. I understand them now more in terms of something akin to a GUI event, or a SQL trigger. You have a need to know when something attempts to set or get a particular attribute. The relation to the actual attribute might be tenous. It's an event. It might begin a process that sends an e-mail to Mary. Who knows what. Its all quite practical and tangible stuff, though. It has nothing yet, in my mind, to do with decoupling anything from anything else as a matter of good OOP design. And to the extent you feel properties are well used in that regard, than you are developing your own use cases which may or may not be similar to Guido's ideas and implicit in the design of the language. And I guess I am suggesting you are suggesting too much by suggesting otherwise. Art Am I making any sense whatever? Art But I still don't see the connection to XP programming, API design I don't object to your not wanting to use such constructs, but rather to your desire to remove them from the language (or veto adding them) in order to make it simpler. I'm sure others have said as much about the ridiculous idea of making a value for the square root of minus one, or for the incomprehensibly strained line at infinity. When you ask what these features provide, I try to explain how they make it possible to write some very clear simple code. I think Kirby will attest to the fact that decorators seriously improved the readability of his hypertoons code. Decorators should be used sparingly, if at all. That is not to say they shouldn't exist. The key to understanding when decorators are useful can be summarized as whenever you feel you are writing boilerplate your skin should itch. This doesn't mean that you should not write boilerplate on occasion, but rather that you should be searching for a way around it. I tried to explain to you why I found properties such a useful addition. Their existence allows me to write code without the protective generality of always writing accessors and mutators in case, some two years hence, I need to change more than the single attribute on a mutation, or decide some value that I have been storing is much better left calculated. This was unconvincing to you, but you responded more in the vein of nobody should be allowed to use this, so the code I read is simpler. I am surprised you accept exceptions (a relatively recent development in the design of computer languages). The rule I use in commenting code is that you should not comment use of features of a language in code written in that language. Programmers who read code written in Python are responsible for learning Python, and there is no excuse for code like: a = range(12) # Make a list of integers between 0 and 11 inclusive The comment slows down your reading of the code and distracts you from reading the application itself. The language is the given. When you choose a language, you buy its tradeoffs. If you cannot stand descriptors, insist on python 2.3. When you ask what something is good for, and get given an explanation that turns out to not make your life simpler, don't presume that the examples given are therefore useless. You have not spent a career writing code that must be rewritten constantly (to accommodate changing requirements); properties help in that task, in part because you can avoid using them until necessary, with their existence in your back pocket. Can we accept the less sophisticated approaches on equal footing? We can accept the less sophisticated approach to designing programs as workable. Do you seriously think that when designing a language equal weight should be given to those that understand
Re: [Edu-sig] quantum instance
Arthur, You may be happy to know that hard-core computer scientists cannot agree on the benefits of abstractions such as decorators. Paul Graham attributes power and elegance to the tersest languages[1] [2], claiming that fewer lines of code means fewer bug, less time writing the code, and less time maintaining the code. Meanwhile Richard Gabriel notes[2] that code can share with poetry the aspect of Compression, in which a few words can hold a great deal of meaning, but he is careful to note that this can easily be taken too far, resulting in incomprehensible gibberish (in poetry or in code). Perhaps this comes down to the fact that both men are old hands at Lisp, but while Graham literally wrote the book on Common Lisp[3], Gabriel wrote A Critique of Common Lisp. Graham used a simplistic program to demonstrate succinctness, a straw man I could argue against, but it demonstrates what I'm talking about, using Python's standard foil: Perl. The goal is to create a function which generates accumulators: Given a number n, it will return a new function which takes another number i, and returns n incremented by i, storing the accumulating result. Graham's canonical example is in Common Lisp, and is indeed quite succinct. (defun foo (n) (lambda (i) (incf n i))) And in Perl you have sub foo { my ($n) = @_; sub {$n += shift} } Which is succinct and perhaps readable to someone thoroughly familiar with Perl, but does look like line noise to me. Perhaps the most succinct you can get this in Python is the following: def foo(n): def bar(i, l=[n]): l[0] += i return l[0] return bar Although this is quite a bit longer than the Lisp version, it is nearly as unreadable as the Perl code. In part this is because Python distinguishes between expressions and statements, so we cannot return l[0] += i. Also, Python does not allow us to assign to local integers, so we hack around this by putting the integer n in a mutable container l = [n]. And lambdas don't allow statements (or is it expressions?) so that keeps it from getting succinct as well. But of course, this is not the canonical Python. Canonical Python would create a class: class foo: def __init__(self, n): self.n = n def __call__(self, i): self.n += i return self.n As you can see, this is not much longer, and (in my eyes at least), vastly more readable. No hacks with lists, it clearly shows that we're accumulating the value. If I were to use this in any real system, I would change self.n to self.accumulator or some such, and make it even longer, because readability counts more than succinctness, despite what Graham claims[5]. If you're still reading this far you may have noted that I haven't actually talked about decorators at all. In my code, I have come to places where there are aspects which cut across classes and methods in a way that's not always intuitive or easy to capture in standard object-oriented code. In Java and some other languages they are implementing Aspect-Oriented Programming (AOP), where you create cutpoints where code will be injected for different aspects which are defined elsewhere. Generating this code is called code weaving or aspect weaving and the result is not intended to be read or modified by humans. Debugging this type of code must take the patience of a saint, since all your line numbers and references would have disappeared in the warp and weft. With decorators I get an 80/20 solution to aspects which cover all of the most common (and dare I say, important) uses of AOP, without compile-time weaving, or losing line numbering or stack tracing or any of my standard editing, reading, or debugging toolkit. For me, this is a big win, and I'm happy to have decorators in my toolbox. I'm also quite happy to have generators, list comprehensions, properties, and descriptors, because these all fill needs for times I have bumped up against a wall of complexity and my code has grown too big, too multi-branched to fit comfortably in my head. Since I do a lot of hobby coding in my limited spare time, on a lot of different project, being able to fit the code in my head is essential. I need to be able to come to a project I left off with months ago and quickly grok what it does and why. That said, I don't make daily use of decorators, descriptors, properties, or even generators. Just as a carpenter's toolbox may contain hammers and screwdrivers he uses everyday, and also more specialized planes or chisels he uses more rarely (but still values having the right tool for the job when he needs it), these are my more specialized tools. I do use list comprehensions daily, they have become one of my favored hammers, but I do try to take care to use them in a way which enlightens the code rather than obfuscates it, which they can certainly