Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-05 Thread Nathan Rice
Re-trolling.

On Wed, Apr 4, 2012 at 1:49 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 As part of my troll-outreach effort, I will indulge here.  I was
 specifically thinking about some earlier claims that programming
 languages as they currently exist are somehow inherently superior to a
 formalized natural language in expressive power.

 I would argue that they are, but only for the very limited purpose for
 which they are written. With the possible exception of Inform 7, most
 programming languages are useless at describing (say) human interactions.

I was thinking about this statement this morning.  Compression is just
the process of finding a more efficient encoding for information.  I
suppose you could say then that language developers could
theoretically be trying to compress natural language representations
of information.  The problem then is that everyone is doing a horrible
job, because they are approaching the subject in an ad hoc manner.
There are multiple branches of mathematics and computer science that
deal with this exact subject in a rigorous way.  The trick is to find
an encoding that has low space complexity, and for which the
transformation to knowledge is efficient, for human beings.

Lets assume that the input to be encoded are logical
(proposition/predicate) statements. The first thing that came to mind
when thinking this way is radix trees and directed acyclic word graphs
(a form of DFA).  These structures are fairly easy to work out on
paper given a set of inputs, and it is fairly easy to reconstruct a
set of inputs from the structure.  Perhaps, we could use natural
language statements, and some very minimal extended syntax to indicate
a data structure (which fans out to a set of statements).  As a quick
example to see what I mean (mimicking some python syntax for
similarity):

in the context of chess:

a color is either white or black

the board:
is a cartesian grid having dimension (8, 8)
has squares, representing points on the grid

a square:
has a color
contains a piece or is empty

a piece:
has a color
is located in a square or has been captured

a { king, queen, rook, bishop, knight, pawn } is a type of piece

It should be clear that this is a directed acyclic phrase graph, and
if you select a phrase fragment, then one phrase fragment from each
child level until reaching a leaf, the concatenation of the phrase
fragments forms a logical phrase.  Note that the set braces are
shorthand for multiple statements.  This was really easy to write, and
I bet even non programmers would have little or no trouble
understanding what was going on.  Additionally, I could make a full
statement elsewhere, and if we have an algorithm to transform to a
canonical phrase structure and merge synonyms, it could be inserted in
the phrase graph, just as neatly as if I had written it there in the
first place.  The sexy thing about that, is that lets you take two
sets of propositional statements, and perform set theoretic operations
on them (union, complement, etc), and get a phrase graph structure out
at the end which looks just like a nice neat little program.  You
could even get really crazy, if you could define equivalence relations
(other than the natural relation) for the union (Set1.A ~ Set2.B) as
that would let you compose the graphs in arbitrarily many ways.  If
you're dealing processes, you would also want to be able to specify
temporal equivalence (Process1.T1 ~ Process2.T6).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-04 Thread Nathan Rice
On Wed, Apr 4, 2012 at 1:49 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 On Tue, 03 Apr 2012 13:17:18 -0400, Nathan Rice wrote:

 I have never met a programmer that was not completely into computers.
 That leaves a lot unspecified though.

 You haven't looked hard enough. There are *thousands* of VB, Java, etc.
 code monkeys who got into programming for the money only and who have
 zero inclination to expand their skills or knowledge beyond that
 necessary to keep their job.

Every programmer that I've ever met who got into it for the money has
washed out within about five years.  Sometimes they make a lateral
move to project management, other times they end up as requirements
analysts, and occasionally they become technical sales staff.  The
story is always the same - they do technical mediocre work, but get
along well with their peers, so they are transitioned to a role that
requires more people skills.

I've never met someone who had both poor people skills and mediocre
technical skills who actually kept their job.

 Go to programming blogs, and you will find many examples of some
 allegedly professional programmer selecting an arbitrary blog post to ask
 Pls sombody write me this code, where this code is either an utterly
 trivial question or a six month project.

Honestly, I have seen that, but usually when I inspect closer it is an
Indian ODesk or Rent-a-coder worker who oversold himself and is trying
to cover his ass.

 As part of my troll-outreach effort, I will indulge here.  I was
 specifically thinking about some earlier claims that programming
 languages as they currently exist are somehow inherently superior to a
 formalized natural language in expressive power.

 I would argue that they are, but only for the very limited purpose for
 which they are written. With the possible exception of Inform 7, most
 programming languages are useless at describing (say) human interactions.

 Human languages are optimised for many things, but careful, step-by-step
 algorithms are not one of them. This is why mathematicians use a
 specialist language for their problem domain, as do programmers. Human
 language is awfully imprecise and often ambiguous, it encourages implicit
 reasoning, and requires a lot of domain knowledge:

You have to be careful when you bring mathematical notation into the
picture.  Remember that mathematics has developed over thousands of
years, with developments shared in many languages.  Greek letters
serve the same purpose in math that latin and greek names serve in
biology - they are neutral and avoid confusion with common names in
living languages.  Not everything about mathematical notation is
good, and in some cases it suffers the same issues that programming
does.  Mathematicians have a tendency to be very terse, and although
some greek letters and symbols have standard meaning, many authors run
roughshod over them.  Logic is somewhat better than math in this
regard, logicians respect their notation and rarely deviate from the
standard meaning of symbols.  Things ARE getting better, but for the
most part it is still kind of a mess.

Also, I should clarify that I consider part of mathematical notation
to be natural language, namely +/-/*, and rational numbers.  People
discover these things on their own, mathematics just provides rigor.
 It is considered bad form to use them in prose, but that is just an
arbitrary style restriction; children intermix mathematical symbols
and language all the time, as to older students taking notes in a
variety of subjects.

    Joe snatched the hammer from Fred. Hey, he said, what are
    you doing? Don't you know that he'll hit the roof if he catches
    you with that?

Are you trying to get me to write obfuscated code?  You can write
ambiguous garbage in any language.

 The crux of my view is that programming languages exist in part because
 computers in general are not smart enough to converse with humans on
 their own level, so we have to talk to them like autistic 5 year-olds.
 That was fine when we didn't have any other options, but all the pieces
 exist now to let computers talk to us very close to our own level, and
 represent information at the same way we do.

 I think you're dreaming. We (that is to say, human beings in general, not
 you and I specifically) cannot even talk to each other accurately,
 precisely and unambiguously all the time. Natural language simply isn't
 designed for that -- hence we have specialist languages like legal
 jargon, mathematics, and programming languages, for specialist purposes.

Legalese is English with a ton of new words.  Mathematics is older
than most languages in current use and has a lot of baggage that is
(very) slowly being dealt with.

Programming really can't take the relaxed attitude about cleaning up
notation and vocabulary that we see in math.  Mathematicians spend a
lot of time thinking, and the transcription of their thoughts is a
relatively minor portion

Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-04 Thread Nathan Rice
 Long personal note ahead.
 tl;dr version: Computers are such a large shift for human civilization
 that generally we dont get what that shift is about or towards.

Another option: since *computers* are such a general device, there
isn't just one notion.

 In the long run I expect computing science to transcend its parent
 disciplines, mathematics and logic, by effectively realizing a
 significant part of Leibniz's Dream of providing symbolic calculation
 as an alternative to human reasoning. (Please note the difference
 between mimicking and providing an alternative to: alternatives
 are allowed to be better.)

A thinking machine.  +1.

 Needless to say, this vision of what computing science is about is not
 universally applauded. On the contrary, it has met widespread --and
 sometimes even violent-- opposition from all sorts of directions. I
 mention as examples

 (0) the mathematical guild, which would rather continue to believe
 that the Dream of Leibniz is an unrealistic illusion

Mathematics is not a closet guild, it is large and contentious.  Ideas
live and die in mathematics based on their fundamental truth.  If
there is some bold, sweeping statement it *MIGHT* be possible to prove
or disprove, mathematicians will be all over it.  just look at
Fermat's last theorem and the Poincare conjecture if you want proof of
this.

 (1) the business community, which, having been sold to the idea that
 computers would make life easier, is mentally unprepared to accept
 that they only solve the easier problems at the price of creating much
 harder one

Most business people I know secretly love when they can sell a
solution to one problem that creates new problems (and thus
opportunities for new products!).  The business term for this is an
Upsell or Value-add.

 (2) the subculture of the compulsive programmer, whose ethics
 prescribe that one silly idea and a month of frantic coding should
 suffice to make him a life-long millionaire

I love hacker culture, but it has been infected by the idea of
entrepreneurship as a good in and of itself.  Being a creator is a
beautiful thing, go forth and make *art*.  Improve the human
condition.  Make the world a better place.  STFU about venture capital
and stage 2 funding and minimum viable products; that sort of talk is
a sure sign that you haven't created anything of actual value.

 (3) computer engineering, which would rather continue to act as if it
 is all only a matter of higher bit rates and more flops per second

These guys are doing something that I find very uninteresting, but is
absolutely necessary.  Bravo I say.

 (4) the military, who are now totally absorbed in the business of
 using computers to mutate billion-dollar budgets into the illusion of
 automatic safety

Nations will always try and be imperialist.  At least drones and robot
soldiers mean less human suffering.

 (5) all soft sciences for which computing now acts as some sort of
 interdisciplinary haven

Digital humanities (outside of a VERY small set of projects) is a
joke.  Multimedia history presentations (and what not) are the domain
of edutainment companies, not academia.

 (6) the educational business that feels that, if it has to teach
 formal mathematics to CS students, it may as well close its schools.

I feel quite the opposite actually.  At the really top notch computer
science schools, there is a clear mathematical bent (though it is
interdisciplinary).  Places like MIT, Stanford, Berkeley, CMU,
Cambridge, etc make a STRONG effort to separate the
mathematical/theory of computation side and engineering side.  At your
average state college, the computer science department is just a
hodgepodge, and you tend to see more graphics, applied computation
and embedded/DSP type people.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-04 Thread Nathan Rice
 The building cabinets problem is interesting:

  1. To actually build a cabinet, there's a lot of domain knowledge
 that's probably implicit in most circumstances.  A carpenter might
 tell another carpenter which hinge to use, but they won't have to talk
 about why doors need hinges or how to do the assembly.
  2. It's quite common for humans to use computer programs as part of
 the design process.
  3. Often, the output of a CAD program (at the file level) is some
 sort of vector representation that only describes the end product
 (basic dimensions, etc.).

 I wonder if there are mini-languages out there that allow you to
 describe cabinets in a very descriptive way, where the description
 easily translates to the actual steps of building the cabinet, not
 just the final dimensions.

I think if you were to describe the parts of the cabinet that needed
to be assembled separately (and thus could be viewed as separate
entities in some sense) and showed the cabinet as the composition of
those parts, you would be on the right track.  Being a mediocre
carpenter, I can't really say anything conclusively here though :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-03 Thread Nathan Rice
On Tue, Apr 3, 2012 at 1:40 AM, alex23 wuwe...@gmail.com wrote:
 On Apr 3, 2:55 pm, Nathan Rice nathan.alexander.r...@gmail.com
 wrote:
 I don't care what people do related to legacy systems.

 And that's what earns you the label 'architecture astronaut'. Legacy
 systems are _part_ of the problem; it's very easy to  hold to a purist
 approach when you ignore the bulk of the domain that causes the
 issues. There's _never_ going to be an InfoTech3k where we just stop
 supporting older code.

There are people who are paid pretty well to support crappy old COBOL
apps, but I am not among them (nor are you, with very high
likelihood), so your we is misplaced.  For all intents and purposes
that software exists in an alternate reality.

Remember the tutorial on global vs local optimization I made
previously?  Let me distill it... If you are unwilling to endure pain
to move towards a better world you will always be trapped in a
sub-optimal situation.

 I do care about programmers that are too lazy to
 learn, and would be happy to ignore the fact that programming is hard
 for most people to learn, so they can continue not learning.  Those
 programmers are scumbags.

 Wait, what?

 Programmers are both too lazy to learn and yet somehow happy that
 the skills they've acquired are too hard for most people to learn?
 So how did they learn them?

 And they're also somehow lazy because they have to learn multiple
 languages to be effective,  rather than one mythical ur-language?

 In my 20 years as a software developer, I have _never_ encountered
 anyone trying to deliberately expand the knowledge gap. This isn't a
 priesthood.

Did you miss the part where I said that most people who learn to
program are fascinated by computers and highly motivated to do so?
I've never met a BROgrammer, those people go into sales.  It isn't
because there aren't smart BROmosapiens (sadly, there are), they just
couldn't give two shits about computers so programming seems like a
colossal waste of time to them.

It isn't about people scheming to dis-empower then plebs rather it
is about people who don't want to move outside their comfort zone.
You can talk about people learning multiple languages all you want,
but for the most part they will be 10 descendants of ALGOL, with minor
variations.  Very few people are willing to tackle something like
Haskell or ML if they weren't taught functional programming in
university, though there are a few that view it as an endurance trial
or mountain to climb.  Those people get a pass on most of what I've
said thus far.

 Just don't let me hear you complaining because some syntax is not C
 like enough for you.  Whenever I hear that I want to strangle the
 self-serving 'tard that wrote it.  When I see people defending C
 like syntax as optimal or somehow much more expressive, that makes me
 doubly irritated.  These are the people who are selfishly defending
 the status quo because they're invested.

 Syntax is never the issue, it's the deeper semantics. Is the scoping
 of one C-like language the same as C? How does it differ? Why does it
 differ? Is the difference a fundamental implementation issue that you
 really need to know before you actually grok the language? Are
 functions first-class objects? Are they actual objects or some kind of
 magical stub? Can you extend those objects with properties? etc etc

Syntax and semantics are both a big mess right now.  That is why I
always address them both.

 Every language tackles _so many_ things differently. It's not lazy to
 say that you prefer something to resemble/be based on a language you
 have experience with, that's human nature. If you're insistent that
 your non-typical syntax is so much better, the onus is on you to prove
 it, not to insist that the lack of uptake is 'laziness'.

The winds of change generally blow for programming when generations of
older programmers leave the workforce.  Alan Kay was a smart man,
viewing programming as an educational tool and designing for youth is
absolutely the right way to do things.  If you try to retrain older
programmers, you are basically telling them they have to change
decades of learning for a moderate (but not huge) productivity
increase, so that programming is accessible to a much wider group of
people.  Much like with the terminal to GUI transition, you will have
people attacking declarative natural language programming as a stupid
practice for noobs, and the end of computing (even though it will
allow people with much less experience to be more productive than
them).

 And one again: code is _communication_. Not having to understand new
 optimal patterns for every single language is a Good Thing.

Code is a horrible medium for communication.  If it weren't, I
wouldn't be trolling this thread.

 Don't try to delude people that our modern
 ALGOL derivatives are the best possible way to model knowledge
 (including process knowledge) to a computer, because that is a lie.

 Um, okay, I'll stop doing

Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-03 Thread Nathan Rice
On Tue, Apr 3, 2012 at 9:51 AM, rusi rustompm...@gmail.com wrote:
 On Apr 3, 5:39 pm, Nathan Rice nathan.alexander.r...@gmail.com
 wrote:

 Don't think underlying, instead think canonical.

 Ultimately, the answers to your questions exist in the world for you
 to see.  How does a surgeon describe a surgical procedure?  How does a
 chef describe a recipe?  How does a carpenter describe the process of
 building cabinets?  Aside from specific words, they all use natural
 language, and it works just fine.

 A carpenter describes his carpentry-process in English
 A CSist describes his programming-process in English (at least all my
 CS books are in English)

 A carpenter uses his tools -- screwdriver, saw, planer --to do
 carpentry
 A programmer uses his tools to to programming -- one of which is
 called 'programming language'

 Doing programming without programming languages is like using toenails
 to tighten screws

I would argue that the computer is the tool, not the language.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-03 Thread Nathan Rice
On Tue, Apr 3, 2012 at 11:01 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Tue, Apr 3, 2012 at 6:39 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 Did you miss the part where I said that most people who learn to
 program are fascinated by computers and highly motivated to do so?
 I've never met a BROgrammer, those people go into sales.  It isn't
 because there aren't smart BROmosapiens (sadly, there are), they just
 couldn't give two shits about computers so programming seems like a
 colossal waste of time to them.

 I have never met the brogrammer stereotype.  I have also never met the
 non-brogrammer stereotype of nerdy solitude (well, maybe once).
 That's all these things are -- stereotypes.  Real programmers are much
 more complex.

I have never met a programmer that was not completely into computers.
That leaves a lot unspecified though.

 Computers require you to state the exact words you're searching for as
 well.  Try looking again, and this time allow for sub-categories and
 synonyms, along with some variation in word order.

 Lazy troll.  You made the claim.  The onus is on you to provide the evidence.

I reserve the right to be lazy :)

As part of my troll-outreach effort, I will indulge here.  I was
specifically thinking about some earlier claims that programming
languages as they currently exist are somehow inherently superior to a
formalized natural language in expressive power.

I think part of this comes from the misconception that terse is better
(e.g. Paul Graham's thoughts on car/cdr), which doesn't take into
account that your brain compresses frequently occurring English words
VERY efficiently, so they actually take up less cognitive bandwidth
than a much shorter non-word.  This behavior extends to the phrase
level as well; longer phrases that are meaningful in their own right
take up less bandwidth than short nonsensical word combinations.

On the semantic side, most people already understand branched
processes and procedures with conditional actions pretty well.  People
program other people to perform tasks constantly, and have been
doing so for the entirety of our existence.  The problem occurs when
programming language specific semantic artifacts must be considered.
These artifacts are for the most part somewhat arbitrary, or you would
see them frequently in other areas, and they wouldn't confuse people
so much.  I think the majority of these relate to how the computer
operates internally - this is the stuff that really turns most people
off to programming.

The crux of my view is that programming languages exist in part
because computers in general are not smart enough to converse with
humans on their own level, so we have to talk to them like autistic 5
year-olds.  That was fine when we didn't have any other options, but
all the pieces exist now to let computers talk to us very close to our
own level, and represent information at the same way we do.  Projects
like IBM's Watson, Siri, Wolfram Alpha and Cyc demonstrate pretty
clearly to me that we are capable of taking the next step, and the
resurgence of the technology sector along with the shortage of
qualified developers indicates to me that we need to move now.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-03 Thread Nathan Rice
  A carpenter uses his tools -- screwdriver, saw, planer --to do
  carpentry
  A programmer uses his tools to to programming -- one of which is
  called 'programming language'

  Doing programming without programming languages is like using toenails
  to tighten screws

 I would argue that the computer is the tool, not the language.

 Computer science is as much about computers as astronomy is about
 telescopes -- E W Dijkstra

 Here are some other attempted corrections of the misnomer computer
 science:
 http://en.wikipedia.org/wiki/Computer_science#Name_of_the_field

I view computer science as applied mathematics, when it deserves
that moniker.  When it doesn't, it is merely engineering.

Ironically, telescopes are a tool that astronomers use to view the stars.


On Tue, Apr 3, 2012 at 1:25 PM, rusi rustompm...@gmail.com wrote:
 All this futuristic grandiloquence:

 On Apr 3, 10:17 pm, Nathan Rice nathan.alexander.r...@gmail.com
 wrote:
 The crux of my view is that programming languages exist in part
 because computers in general are not smart enough to converse with
 humans on their own level, so we have to talk to them like autistic 5
 year-olds.  That was fine when we didn't have any other options, but
 all the pieces exist now to let computers talk to us very close to our
 own level, and represent information at the same way we do.  Projects
 like IBM's Watson, Siri, Wolfram Alpha and Cyc demonstrate pretty
 clearly to me that we are capable of taking the next step, and the
 resurgence of the technology sector along with the shortage of
 qualified developers indicates to me that we need to move now.

 needs to be juxtaposed with this antiquated view

 I would argue that the computer is the tool, not the language.


 ... a view that could not be held by an educated person after the
 1960s -- ie when it became amply clear to all that the essential and
 hard issues in CS are about software and not hardware

I'll go ahead and forgive the club handed fallacies, so we can have a
nice discussion of your primary point.  What a civil troll I am :)

Lets start with some analogies.  In cooking, chefs use recipes to
produce a meal; the recipe is not a tool.  In architecture, a builder
uses a blueprint to produce a building; the blueprint is not a tool.
In manufacturing, expensive machines use plans to produce physical
goods; the plans are not the tool.

You could say the compiler is a tool, or a development environment is
a tool.  The programming language is a mechanism for communication.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-03 Thread Nathan Rice
On Tue, Apr 3, 2012 at 4:20 PM, Terry Reedy tjre...@udel.edu wrote:
 On 4/3/2012 8:39 AM, Nathan Rice wrote:

 Ultimately, the answers to your questions exist in the world for you
 to see.  How does a surgeon describe a surgical procedure?  How does a
 chef describe a recipe?  How does a carpenter describe the process of
 building cabinets?  Aside from specific words, they all use natural
 language, and it works just fine.


 Not really. Surgeon's learn by *watching* a surgeon who knows the operation
 and next (hopefully) doing a particular surgery under supervision of such a
 surgeon, who watches and talks, and may even grab the instruments and
 re-show. They then really learn by doing the procedure on multiple people.
 They often kill a few on the way to mastery.

Well, there is declarative knowledge and procedural knowledge.  In all
these cases, only the procedural knowledge is absolutely necessary,
but the declarative knowledge is usually a prerequisite to learning
the procedure in any sort of reasonable manner.

 I first learned basic carpentry and other skills by watching my father. I
 don't remember that he ever said anything about how to hold the tools.

 I similarly learned basic cooking by watching my mom. My knowledge of how to
 crack open an egg properly and separate the yolk from the rest is a wordless
 memory movie.

A picture is worth a thousand words :)

If you would like, I don't have any problem incorporating visual
programming and programming by demonstration.  I didn't go in that
direction because I have enough to defend as it is.  I like to look at
it from the perspective of teaching/communicating, rather than
operating a simple machine.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-04-02 Thread Nathan Rice
On Sun, Apr 1, 2012 at 11:18 PM, alex23 wuwe...@gmail.com wrote:
 On Mar 30, 3:37 pm, Nathan Rice nathan.alexander.r...@gmail.com
 wrote:
 We live in a world where the tools that are used are based on
 tradition (read that as backwards compatibility if it makes you feel
 better) and as a mechanism for deriving personal identity.  The world
 is backwards and retarded in many, many ways, this problem is
 interesting to me because it actually cuts across a much larger tract
 than is immediately obvious.

 Do you produce commercial code in a team? Because going by your
 absolutist bullshit here, it certainly doesn't sound like it.

Think of me like the Wolf, the cleaner in pulp fiction that Marcellis
Wallis calls in to take care of the mess when Jules accidentally blows
a kid's brains out in the back of a car.  I get called in when my
skills are needed, and when the mess has been handled and things are
back to normal I take my leave.

 When I join an organisation that requires language A as all of its
 systems are written in it, is that 'tradition' or 'personal identity'?
 How is 'compatibility' - either with existing systems or existing
 *developers* - a backwards and retarded approach to complex
 problems?

I don't care what people do related to legacy systems.  There will
always be a COBOL.  I do care about programmers that are too lazy to
learn, and would be happy to ignore the fact that programming is hard
for most people to learn, so they can continue not learning.  Those
programmers are scumbags.

Just don't let me hear you complaining because some syntax is not C
like enough for you.  Whenever I hear that I want to strangle the
self-serving 'tard that wrote it.  When I see people defending C
like syntax as optimal or somehow much more expressive, that makes me
doubly irritated.  These are the people who are selfishly defending
the status quo because they're invested.  If you're going to be
selfish and inconsiderate at least be honest about it, rather than
pretending that one of the earliest languages somehow got almost
everything right and should be the basis for new languages till the
end of time.  This goes for most of the ALGOL derived languages.  I
don't have a problem if you know your language well and are happy
using it, that's great.  Don't try to delude people that our modern
ALGOL derivatives are the best possible way to model knowledge
(including process knowledge) to a computer, because that is a lie.

 If I've chosen language A because some aspect of its syntax maps
 better onto my mind (or for _whatever_ reason that makes individuals
 prefer one language to another), and you've chosen language B: who
 gets to decide which is the 'superior' language, which is the 'better'
 mapping etc?

You should be able to live in your reality if you want, as long that
doesn't impinge on others.  Of course, if you disagree on basic
grammar, then I would have to ask you, do you disagree about English
grammar, or have you accepted it so that you can communicate with
people?  This is why I advocate following English grammar closely for
syntax - people have accepted it and don't make a big deal, and it is
the way we represent information already.

 You're arguing for a top-down centralised approach to language
 development that just will _never_ exist, simply because it cannot. If
 you don't accept that, I believe there's a fascinating fork called
 Python 4000 where your ideas would be readily adopted.

You completely missed my point.  In fact, my argument is for a bottom
up approach, with a meeting point which is much closer than the
machine code which is currently used.  However you want to represent
it, the knowledge is the same, and that is what matters.  We need to
get past the idea of different, incompatible languages, and settle on
a common knowledge representation format that underlies all languages,
and is compatible.  If you want to make an alex23 DSL where up is down
and inside is upside down, go for it, just as long as it is
represented in a sensible set of semantic primes that I can transform
to whatever reality I want.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-31 Thread Nathan Rice
On Sat, Mar 31, 2012 at 2:15 AM, Lie Ryan lie.1...@gmail.com wrote:
 On 03/21/2012 03:55 AM, Nathan Rice wrote:

 snip

 I think you've just described that greedy algorithm can't always find the
 globally optimal solution.

Right.  Using gradient descent on an algebraic surface is probably the
most natural example of why this is the case, since balls rolling down
a surface from a starting point to the bottom of a bowl is an exact
analogy.

On Sat, Mar 31, 2012 at 4:05 AM, Chris Angelico ros...@gmail.com wrote:
 On Sat, Mar 31, 2012 at 10:01 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 It seems to me that Indented blocks of text are used pretty frequently
 to denote definition bodies, section subordinate paragraphs and
 asides.  The use of the colon seems pretty natural too.  Parentheses
 are fairly natural for small asides.  The notion of character
 delimiters for large sections of text is actually pretty unnatural
 with the exception of  quotes.

 Perhaps in formal written English, but not in spoken, and often not in
 casual writing either. Play around with my actual example, an if
 clause, and see where the punctuation goes in English - and how easily
 you can construct ambiguous sentences.

Sure

an event has occurred recently if it occurred in the last time step.

if xyz has occurred recently, that implies abc will occur in the next time step.

when event abc occurs, all unbound floops become bound, and at most
three newly bound floops are eaten by blargs.

blargs that have not eaten in the last 3 time steps eat before blargs
that have eaten in those time steps.

Notice I don't talk about HOW anything is done, just the logic of what
is happening.  The computer should be capable of making an inventory
of exactly what it will need to do given the statements I have made,
and choose the best data structures and algorithms for the job.  If we
are in undecidable/halting problem territory (indefinite recursion)
then the computer should at least be nice enough to tell you it is
confused and would like some help.

 I don't like declarations, my personal preference is to have typed
 signatures, and implicit declaration with type inference elsewhere.  I
 view it as a matter of personal preference though, the result should
 be the same, and it should be possible to view the code either way.

 I'm not sure what you mean by typed signatures, can you elaborate please?

Just like the standard way in the Haskell community.  To demonstrate
using Python annotations...

def myfunc(Sequence : a, Integral : b, Map : c) - Sequence:
...

Given starting types and ending types, you can correctly infer some
VERY complex internal types. Haskell will let you omit signature types
as well, but that is really a bad idea because they add readability
and you will have to add them often anyhow if you are dealing with
complex types.  Better to be consistent...

As a funny aside, people usually provide input type and return type
annotations to python functions, as part of the docstring (for
sphinx).

To be honest, I like having types baked into my code, though not
nominal types (the sort that is an A because it was declared as an A
or a subclass of A), but rather structural types (i.e. Abstract base
classes, or Java interfaces, if you didn't have to add the implements
...).  I don't like having to verbosely tell the computer about the
types of everything I'm going to use, I only care that it gives me the
output I want if I give it some agreed upon input.  It should be smart
enough to check the little things.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-30 Thread Nathan Rice
 Mathematics is all about abstraction.  There are theories and structures
 in mathematics that have probably gone over a hundred years before being
 applied.  As an analogy, just because a spear isn't useful while farming
 doesn't mean it won't save your life when you venture into the woods and
 come upon a bear.

 A spear is a concrete application of the principle of leverage, not an
 abstraction. I also point out leverage was discovered experimentally long
 before anyone had an abstraction for it.

And an analogy is a device to demonstrate the fundamental character of
an argument in a different context.

 In any case, so what? Who is saying that mathematics is useless? Not me,
 and not Joel Spolksy. You are hunting strawmen with your non-abstract
 spear.

I don't think it is a strawman.  He decries things that aren't
immediately useful.  That describes almost all pure math.  If he had
excluded things that have some characteristic of truth, and just
talked about overly general systems, I might agree with him.

 Spolsky has written at least three times about Architecture Astronauts,
 and made it abundantly clear that the problem with them is that they
 don't solve problems, they invent overarching abstractions that don't do
 anything useful or important, and hype them everywhere.

I believe in the idea of things should be as simple as possible, but
not simpler.  Programming as it currently exists is absolutely
convoluted.  I am called on to help people learn to program from time
to time, and I can tell you that we still have a LONG way to go before
programming approaches a global optimum in either the semantic or
syntactic space.  Never mind configuring a build or anything else
related to projects.  The whole setup really is horrible, and I'm
convinced that most of the people who are capable of changing this are
more concerned about their personal investment in the way things are
than helping others.  There are a few exceptions like Alan Kay, but
mostly people want to graft shortcuts on to what already exists.

 You keep reading this as an assault on abstract mathematics, science and
 knowledge for its on sake. It isn't any of these things.

I never said it was an attack on science.  Scientists don't really do
abstraction, they explain observations.  Mathematicians are the ones
who discover truth that may be completely disconnected from reality.

 If I'm paid to solve a problem, and instead I build an abstraction that
 doesn't help solve the problem, then I'm guilty of doing architecture
 astronauting.

If I ignore everything Joel wrote and just use that definition, I
agree with you.

 He is basically saying they are too clever for their own good, as a
 result of being fixated upon purely intellectual constructs.

 Yes, and he is right to do so, because that is the characteristic of the
 Architecture Astronaut: being so fixated on over-arching abstract
 concepts that, far from those abstractions making it easier to solve the
 problems they are being paid to solve, they actually make them harder.

 Good abstractions enable problems to be solved. Bad abstractions don't.

 If I ask you to build me a website, I probably don't want a website-
 builder, I certainly don't want a website-builder-generator, and I
 absolutely do not want you to generalise the concept of a compiler and
 create a whole new abstract language for describing meta-compilers so
 that I can create a brand new programming language for generating meta-
 compilers that build compilers that will build factories for building
 website generators so I can make my own website in just three easy steps
 (the simplest one of which is about twice as difficult as just building
 the website would have been).

Again, I follow the principle of everything should be as simple as
possible, but no simpler.  I have in the past built website builders
rather than build websites (and done a similar thing in other cases),
but not because I am trying to discover some fundamental truth of
website building, because that would be bullshit.  I did it because
building websites (or whatever else it was) is a boring, tedious
problem, and a website builder, while being more work, is an engaging
problem that requires thought.  I enjoy challenging myself.

 If you are being paid to build abstractions in the ivory tower, on the
 chance that one in a thousand abstractions turns out to be a game
 changer, or just because of a love of pure knowledge, that's great. I
 love abstract mathematics too. I read maths in my free time, you won't
 find me saying that it is bad or useless or harmful. But does it solve
 real problems?

You forget that even abstractions that never directly get turned into
something real are almost invariably part of the intellectual
discourse that leads to real things.

 Well, of course it does, and often in a most surprising places. But
 that's because out of the hundred thousand abstractions, we see the
 hundred that actually solve concrete problems. The 

Re: Python is readable

2012-03-30 Thread Nathan Rice
On Fri, Mar 30, 2012 at 12:20 PM, Chris Angelico ros...@gmail.com wrote:
 On Sat, Mar 31, 2012 at 12:46 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 I believe in the idea of things should be as simple as possible, but
 not simpler.  Programming as it currently exists is absolutely
 convoluted.  I am called on to help people learn to program from time
 to time, and I can tell you that we still have a LONG way to go before
 programming approaches a global optimum in either the semantic or
 syntactic space.

 Aside from messes of installing and setting up language
 interpreters/compilers, which are averted by simply having several
 pre-installed (I think my Linux boxes come with some Python 2 version,
 Perl, bash, and a few others), that isn't really the case. Starting a
 Python script is easy. Programming gets convoluted only when, and to
 the extent that, the task does.

It is true that program complexity is correlated with problem
complexity, language and environment complexity is undeniable.  If you
want to prove this to yourself, find someone who is intelligent and
has some basic level of computer literacy, sit them down at a computer
and ask them to solve simple problems using programs.  You could even
be nice by opening the editor first.  Don't help them, just watch them
crash and burn.  Then sit them in front of code that already works,
and ask them to modify it to do something slightly different, and
again just watch them crash and burn in all but the simplest of cases.
 It is painful - most of the time they just give up.  These same
people almost universally can describe the exact process of steps
verbally or in writing to do what is required without any trouble;
there might be some neglected edge cases, but if you describe the
failed result, often times they will realize their mistake and be able
to fix it quickly.

Jeff Atwood had an article about programming sheep and non programming
goats, and while he views it as a statement about people's failings, I
view it as a statement about the failings of programming.  Human
computer interaction is really important, and the whole prefab GUI
concept doesn't scale along any axis; people need to be able to
interact with their computers in a flexible manner.  In the beginning,
we had no choice but to bend our communication to the the machine, but
we're moving past that now.  The machine should respect the
communication of humans.  We shouldn't decry natural language because
of ambiguity; If we're ambiguous, the machine should let us know and
ask for clarification.  If we phrase things in a really awkward way,
the machine should tell us so, and suggest a more understandable
rendition (just like word processors do now).  If the machine does
something we didn't want based on our instructions, we should be able
to state additional requirements in a declarative manner.  Restricted
natural languages are an active area of current research, and they
clearly demonstrate that you can have an expressive formal language
that is also valid English.

Make no mistake about it, programming is a form of computer human
interaction (I figured that would be an accepted mantra here).  Think
of it as modeling knowledge and systems instead of pushing bits
around.  You are describing things to the computer.  To move from the
syntactic domain to my point about programming languages, imagine if
one person describes physics to a computer in French, and another
person describes chemistry to a computer in English.  The creators of
the computer made different languages act as disjoint knowledge
domains.  The computer is incapable of making any inferences in
physics which are informed by chemistry, and vice versa, unless
someone comes along and re-describes one of the disciplines in the
other language.  Worse still, if someone that only speaks Mandarin
comes along, the computer won't be able to tell him anything about
either domain.  Now imagine the creators of the computer decided that
an acceptable solution was to have people print out statements from
one domain in a given language, take it to another computer that scans
the printout, translates it to a different language, and prints out
the translated copy, then have that person take the translated copy
back to the original computer, and scan it again in order to ask a
cross cutting question. I hope from that perspective the paucity of
our current methods will be more apparent.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-30 Thread Nathan Rice
 This is more a matter of being unable to express themselves
 appropriately. If I allowed them to write an exact process of steps to
 do what's required, those steps would either be grossly insufficient
 for the task, or would BE pseudo-code. There are plenty of people who
 cannot write those sorts of instructions at all. They're called
 non-programmers. Anyone who doesn't code but can express a task in
 such clear steps as you describe is what I would call a non-coding
 programmer - and such people are VERY easily elevated to full
 programmer status. I've worked with several like that, and the border
 between that kind of clear, concise, simple instruction list and
 actual Python or REXX code is so small as to be almost nonexistent.
 It's not the programming languages' fault. It's a particular jump in
 thinking that must be overcome before a person can use them.

Your statement that the difference between Python or REXX and
pseudo-code is almost non existent is completely false.  While people
reading Python might be able to guess with higher accuracy what a
program does than some other programming languages, there is still a
set of VERY specific set of glyphs, words and phrase structures it
requires.

Pretty much anyone can follow a recipe to make a meal (and there are a
lot other examples of this), and conversely given the knowledge of how
to make some dish, pretty much everyone could describe the process as
a recipe.  The same person will fail miserably when trying to create
working code that is MUCH simpler from a conceptual standpoint.  Non
coders are not stupid, they just don't appreciate the multitude of
random distinctions and computer specific abstractions programming
foists on them for the purpose of writing EFFICIENT code.  I'm talking
about like multiple int/number types, umpteen different kinds of
sequences, tons of different data structures that are used for
basically the same things under different circumstances, indices
starting at 0 (which makes amazing sense if you think like a machine,
and very little if you think like a human), the difference between
logical and bitwise operators (union and intersection would be better
names for the latter), string encoding, etc.  When you combine these
with having to communicate in a new (very arbitrary, sometimes
nonsensical) vocabulary that doesn't recognize synonyms, using an
extremely restricted phrase structure and an environment with very
limited interactivity, it should become clear that the people who
learn to program are invariably fascinated by computers and very
motivated to do so.

I'm going to assume that you didn't mean that non coders are
incapable of instructing others (even though your statement implies it
directly).  I think the ability of non coders to describe procedures
would surprise you.  Things I hear over and over from non coders all
tie into people being frustrated that computers don't grasp
similarity, and don't try to figure out what they want at all; most
people provide instructions in an interactive manner.  The computer is
too stupid to interact with humans, so you have to tell it what to do,
then try to run it, watch it fail, then go back and modify your
program, which is highly unnatural.

I think you'd find that these non coders would do very well if given
the ability to provide instructions in a natural, interactive way.
They are not failing us, we are failing them.

 Etcetera, etcetera. Everyone who's made the jump will see the benefit
 of the side they're on; most who haven't won't. Same with
 non-programmers to programmers. Why should I write like that when I
 could just write English? Simple: Because dedicated programming
 languages are far more expressive for the job.

Really?  Or could it be that algorithms for natural language
processing that don't fail miserably is a very recent development,
restricted natural languages more recent still, and pretty much all
commonly used programming languages are all ~20+ years old?  Could it
also be that most programmers don't see a lot of incentives to make
things accessible, since they're already invested in the status quo,
and they might lose some personal value if programming stopped being
an arcane practice?

Creating a programming language is a time consuming and laborious
process, the fact that people are doing it constantly is a clear
indication that what we have is insufficient.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-30 Thread Nathan Rice
On Fri, Mar 30, 2012 at 4:20 PM, Chris Angelico ros...@gmail.com wrote:
 On Sat, Mar 31, 2012 at 6:55 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 I think you'd find that these non coders would do very well if given
 the ability to provide instructions in a natural, interactive way.
 They are not failing us, we are failing them.

 The nearest thing to natural-language command of a computer is voice
 navigation, which is another science that's plenty old and yet still
 current (I first met it back in 1996 and it wasn't new then). You tell
 the computer what you want it to do, and it does it. Theoretically.
 The vocabulary's a lot smaller than all of English, of course, but
 that's not a problem. The problem is that it's really REALLY slow to
 try to get anything done in English, compared to a dedicated
 domain-specific language (in the case of typical OS voice navigation,
 the nearest equivalent would probably be a shell script).

I'm sure a ford truck would smoke a twin engine cessna if you compare
their speed on the ground.  Let the cessna fly and the ford doesn't
have a snowball's chance.

If you're navigating by going cee dee space slash somefolder slash
some other folder slash some third folder slash semicolon emacs
somename dash some other name dash something dot something else dot
one the analogy would be a boss telling his secretary to reserve him
a flight by saying visit site xyz, click on this heading, scroll
halfway down, open this menu, select this destination, ... instead of
book me a flight to San Jose on the afternoon of the 23rd, and don't
spend more than $500.

 Totally. That's why we're all still programming in assembly language
 and doing our own memory management, because we would lose a lot of
 personal value if programming stopped being so difficult. If it
 weren't for all these silly new-fangled languages with their automatic
 garbage collection and higher order function handling, we would all be
 commanding much higher salaries.

Did you miss the fact that a 50 year old programming language (which
still closely resembles its original form) is basically tied for the
title of currently most popular, and the 3 languages following it are
both nominal and spiritual successors, with incremental improvements
in features but sharing a large portion of the design.  Programming
language designers purposefully try to make their language C-like,
because not being C-like disqualifies a language from consideration
for a HUGE portion of programmers, who cower at the naked feeling they
get imagining a world without curly braces.  Fear of change and the
unknown are brutal, and humans are cowardly creatures that will grasp
at whatever excuses they can find not to acknowledge their weaknesses.

I also mentioned previously, most developers are just trying to graft
shortcut after shortcut on to what is comfortable and familiar because
we're inherently lazy.

Additionally, I'm quite certain that when we finally do have a method
for programming/interacting with computers in a natural way, many
people invested in previous methods will make snarky comments about
how lame and stupid people using the new methods are, just like we saw
with command line/keyboard elitists who make fun of people who prefer
a mouse/gui, even though in most cases research showed that the people
using the mouse/gui actually got work done faster.  You can even look
at some comments on this thread for evidence of this.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-30 Thread Nathan Rice
On Fri, Mar 30, 2012 at 5:45 PM, Chris Angelico ros...@gmail.com wrote:
 On Sat, Mar 31, 2012 at 7:58 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 Programming
 language designers purposefully try to make their language C-like,
 because not being C-like disqualifies a language from consideration
 for a HUGE portion of programmers, who cower at the naked feeling they
 get imagining a world without curly braces.  Fear of change and the
 unknown are brutal, and humans are cowardly creatures that will grasp
 at whatever excuses they can find not to acknowledge their weaknesses.

 Braces are clear delimiters. English doesn't have them, and suffers
 for it. (Python's indentation is, too, but English doesn't have that
 either.) It's a lot harder to mark the end of an if block in English
 than in pretty much any programming language.

It seems to me that Indented blocks of text are used pretty frequently
to denote definition bodies, section subordinate paragraphs and
asides.  The use of the colon seems pretty natural too.  Parentheses
are fairly natural for small asides.  The notion of character
delimiters for large sections of text is actually pretty unnatural
with the exception of  quotes.

 And be careful of what has to be given up to gain your conveniences.
 I've used languages that demand variable declarations and ones that
 don't, and I'm very much a fan of the former. There are many benefits
 to being explicit about that.

I don't like declarations, my personal preference is to have typed
signatures, and implicit declaration with type inference elsewhere.  I
view it as a matter of personal preference though, the result should
be the same, and it should be possible to view the code either way.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-03-29 Thread Nathan Rice
On Wed, Mar 28, 2012 at 9:33 PM, Chris Angelico ros...@gmail.com wrote:
 On Thu, Mar 29, 2012 at 11:59 AM, Rodrick Brown rodrick.br...@gmail.com 
 wrote:
 The best skill any developer can have is the ability to pickup languages 
 very quickly and know what tools work well for which task.

 Definitely. Not just languages but all tools. The larger your toolkit
 and the better you know it, the more easily you'll be able to grasp
 the tool you need.

The thing that bothers me is that people spend time and mental energy
on a wide variety of syntax when the semantics are ~90% identical in
most cases (up to organization).

We would be better off if all the time that was spent on learning
syntax, memorizing library organization and becoming proficient with
new tools was spent learning the mathematics, logic and engineering
sciences.  Those solve problems, languages are just representations.

Unfortunately, programming languages seem to have become a way to
differentiate yourself and establish sub-cultural membership.  All the
cool kids are using XYZ, people who use LMN are dorks!  Who cares
about sharing or compatibility!

Human nature is depressingly self-defeating.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-03-29 Thread Nathan Rice
On Thu, Mar 29, 2012 at 10:03 AM, Chris Angelico ros...@gmail.com wrote:
 On Fri, Mar 30, 2012 at 12:44 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 We would be better off if all the time that was spent on learning
 syntax, memorizing library organization and becoming proficient with
 new tools was spent learning the mathematics, logic and engineering
 sciences.  Those solve problems, languages are just representations.

 Different languages are good at different things. REXX is an efficient
 text parser and command executor. Pike allows live updates of running
 code. Python promotes rapid development and simplicity. PHP makes it
 easy to add small amounts of scripting to otherwise-static HTML pages.
 C gives you all the power of assembly language with all the
 readability of... assembly language. SQL describes a database request.

Here's a thought experiment.  Imagine that you have a project tree on
your file system which includes files written in many different
programming languages.  Imagine that the files can be assumed to be
contiguous for our purposes, so you could view all the files in the
project as one long chunk of data.  The directory and file names could
be interpreted as statements in this data, analogous to in the
context of somedirectory or in the context of somefile with
sometype.  Any project configuration files could be viewed as
declarative statements about contexts, such as in xyz context, ignore
those or in abc context, any that is actually a this.  Imagine the
compiler or interpreter is actually part of your program (which is
reasonable since it doesn't do anything by itself).  Imagine the build
management tool is also part of your program in pretty much the same
manner.  Imagine that your program actually generates another program
that will generate the program the machine runs.  I hope you can
follow me here, and further I hope you can see that this is a
completely valid description of what is actually going on (from a
different perspective).

In the context of the above thought experiment, it should be clear
that we currently have something that is a structural analog of a
single programming metalanguage (or rather, one per computer
architecture), with many domain specific languages constructed above
that to simplify tasks in various contexts.  The model I previously
proposed is not fantasy, it exists, just not in a form usable by human
beings.  Are machine instructions the richest possible metalanguage?
I really doubt it.

Lets try another thought experiment... Imagine that instead of having
machine instructions as the common metalanguage, we pushed the point
of abstraction closer to something programmers can reasonably work
with: abstract syntax trees.  Imagine all programming languages share
a common abstract syntax tree format, with nodes generated using a
small set of human intelligible semantic primes.  Then, a domain
specific language is basically a context with a set of logical
implications.  By associating a branch of the tree to one (or the
union of several) context, you provide a transformation path to
machine instructions via logical implication.  If implications of a
union context for the nodes in the branch are not compatible, this
manifests elegantly in the form of a logical contradiction.

What does pushing the abstraction point that far up provide?  For one,
you can now reason across language boundaries.  A compiler can tell me
if my prolog code and my python code will behave properly together.
Another benefit is that you make explicit the fact that your parser,
interpreter, build tools, etc are actually part of your program, from
the perspective that your program is actually another program that
generates programs in machine instructions.  By unifying your build
chain, it makes deductive inference spanning steps and tools possible,
and eliminates some needless repetition.  This also greatly simplifies
code reuse, since you only need to generate a syntax tree of the
proper format and associate the correct context to it.  It also
simplifies learning languages, since people only need to understand
the semantic primes in order to read anything.

Of course, this describes Lisp to some degree, so I still need to
provide some answers.  What is wrong with Lisp?  I would say that the
base syntax being horrible is probably the biggest issue.  Beyond
that, transformations on lists of data are natural in Lisp, but graph
transformations are not, making some things awkward.  Additionally,
because Lisp tries to nudge you towards programming in a functional
style, it can be un-intuitive to learn.  Programming is knowledge
representation, and state is a natural concept that many people desire
to model, so making it a second class citizen is a mistake.  If I were
to re-imagine Lisp for this purpose, I would embrace state and an
explicit notion of temporal order.  Rather than pretending it didn't
exist, I would focus on logical and mathematical machinery necessary

Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-03-29 Thread Nathan Rice
On Thu, Mar 29, 2012 at 2:53 PM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 Agreed with your entire first chunk 100%. Woohoo! High five. :)

Damn, then I'm not trolling hard enough ಠ_ಠ

 On Thu, Mar 29, 2012 at 1:48 PM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 transformations on lists of data are natural in Lisp, but graph
 transformations are not, making some things awkward.

 Eh, earlier you make some argument towards lisp being a universal
 metalanguage. If it can simulate prolog, it can certainly grow a graph
 manipulation form. You'd just need to code it up as a macro or
 function :p

Well, a lisp-like language.  I would also argue that if you are using
macros to do anything, the thing you are trying to do should classify
as not natural in lisp :)

I'm really thinking here more in terms of a general graph reactive
system here, matching patterns in an input graph and modifying the
graph in response.  There are a lot of systems that can be modeled as
a graph that don't admit a nested list (tree) description.  By having
references to outside the nesting structure you've just admitted that
you need a graph rather than a list, so why not be honest about it and
work in that context from the get-go.

 Additionally,
 because Lisp tries to nudge you towards programming in a functional
 style, it can be un-intuitive to learn.

 I think you're thinking of Scheme here. Common Lisp isn't any more
 functional than Python, AFAIK (other than having syntactic heritage
 from the lambda calculus?)

 Common-Lisp does very much embrace state as you later describe, Scheme
 much less so (in that it makes mutating operations more obvious and
 more ugly. Many schemes even outlaw some entirely. And quoted lists
 default to immutable (rgh)).

I find it interesting that John McCarthy invented both Lisp and the
situation calculus.

As for set/setq, sure, you can play with state, but it is verbose, and
there is no inherent notion of temporal locality.  Your program's
execution order forms a nice lattice when run on hardware, that should
be explicit in software.  If I were to do something crazy like take
the union of two processes that can potentially interact, with an
equivalence relation between some time t1 in the first process and a
time t2 in the second (so that you can derive a single partial order),
the computer should be able to tell if I am going to shoot myself in
the foot, and ideally suggest the correct course of action.

 Well, what sort of language differences make for English vs Mandarin?
 Relational algebraic-style programming is useful, but definitely a
 large language barrier to people that don't know any SQL. I think this
 is reasonable. (It would not matter even if you gave SQL python-like
 syntax, the mode of thinking is different, and for a good reason.)

I don't think they have to be.  You can view functions as names for
temporally ordered sequence of declarative implication statements.
Databases just leave out the logic (this is hyperbole, I know), so you
have to do it in client code.  I don't feel that a database
necessarily has to be a separate entity, that is just an artifact of
the localized, specialized view of computation.  As stronger
abstractions are developed and concurrent, distributed computation is
rigorously systematized, I think we'll go full circle.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-29 Thread Nathan Rice
On Thu, Mar 29, 2012 at 9:44 AM, Albert van der Horst
alb...@spenarnc.xs4all.nl wrote:
 In article mailman.896.1332440814.3037.python-l...@python.org,
 Nathan Rice  nathan.alexander.r...@gmail.com wrote:

 http://www.joelonsoftware.com/articles/fog18.html

I read that article a long time ago, it was bullshit then, it is
bullshit now.  The only thing he gets right is that the Shannon
information of a uniquely specified program is proportional to the
code that would be required to generate it.  Never mind that if a

 Thank you for drawing my attention to that article.
 It attacks the humbug software architects.
 Are you one of them?
 I really liked that article.

I read the first paragraph, remembered that I had read it previously
and stopped.  I accidentally remembered something from another Joel
article as being part of that article (read it at
http://www.joelonsoftware.com/items/2007/12/03.html).  I don't really
have anything to say on Joel's opinions about why people can or should
code, their his and he is entitled to them.  I feel they are overly
reductionist (this isn't a black/white thing) and have a bit of
luddite character to them.  I will bet you everything I own the only
reason Joel is alive today because of some mathematical abstraction he
would be all too happy to discount as meaningless (because, to him, it
is).  Of course, I will give Joel one point: too many things related
to programming are 100% hype, without any real substance; if his
article had been about bullshit software hype and he hadn't fired the
broadsides at the very notion of abstraction, I wouldn't have anything
to say.

Anyhow, if you ugh rock good caveman smash gazelle put in mouth make
stomach pain go away meaning, here it is:  Programs are knowledge.
The reverse is not true, because programming is an infantile area of
human creation, mere feet from the primordial tide pool from whence it
spawned.  We have a very good example of what a close to optimal
outcome is: human beings - programs that write themselves, all
knowledge forming programs, strong general artificial intelligence.
When all knowledge is also programs, we will have successfully freed
ourselves from necessary intellectual drudgery (the unnecessary kind
will still exist).  We will be able to tell computers what we want on
our terms, and they will go and do it, checking in with us from time
to time if they aren't sure what we really meant in the given context.
 If we have developed advanced robotics, we will simultaneously be
freed from most manual labor.  The only thing left for Joel to do will
be to lounge about, being creative while eating mangos that were
picked, packed, shipped and unloaded by robots, ordered by his
computer assistant because it knows that he likes them, then
delivered, prepared and served by more robots.

The roadblocks in the path include the ability to deal with
uncertainty, understand natural languages and the higher order
characteristics of information.  Baby steps to deal with these
roadblocks are to explicitly forbid uncertainty, simplify the language
used, and explicitly state higher order properties of information.
The natural evolution of the process is to find ways to deal with
ambiguity, correctly parse more complex language and automatically
deduce higher order characteristics of information.

Clearly, human intelligence demonstrates that this is not an
impossible pipe dream.  You may not be interested in working towards
making this a reality, but I can pretty much guarantee on the scale of
human achievement, it is near the top.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-03-29 Thread Nathan Rice
On Thu, Mar 29, 2012 at 7:37 PM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 On Thu, Mar 29, 2012 at 3:50 PM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 Well, a lisp-like language.  I would also argue that if you are using
 macros to do anything, the thing you are trying to do should classify
 as not natural in lisp :)

 You would run into disagreement. Some people feel that the lisp
 philosophy is precisely that of extending the language to do anything
 you want, in the most natural way.

That is some people's lisp philosophy, though I wouldn't say that is a
universal.  Just like I might say my take on python's philosophy is
keep it simple, stupid but others could disagree.

 At least, I disagree, but my lisp thoughts are the result of
 indoctrination of the Racket crowd. I don't know how well they
 represent the larger lisp community. But you should definitely take
 what I say from the viewpoint of the sort of person that believes that
 the whole purpose of lisps is to embed new syntax and new DSLs via
 macros. Without macros, there's no point of having this despicable
 syntax (barring maybe pedagogy and other minor issues).

Heh, I think you can have a homoiconic language without nasty syntax,
but I won't get into that right now.

 I'm really thinking here more in terms of a general graph reactive
 system here, matching patterns in an input graph and modifying the
 graph in response.  There are a lot of systems that can be modeled as
 a graph that don't admit a nested list (tree) description.  By having
 references to outside the nesting structure you've just admitted that
 you need a graph rather than a list, so why not be honest about it and
 work in that context from the get-go.

 I don't see any issue in defining a library for working with graphs.
 If it's useful enough, it could be added to the standard library.
 There's nothing all that weird about it.

Graphs are the more general and expressive data structure, I think if
anything you should special case the less general form.

 Also, most representations of graphs are precisely via a tree-like
 non-recursive structure. For example, as a matrix, or adjacency list,
 etc. We think of them as deep structures, but implement them as flat,
 shallow structures. Specialized syntax (e.g. from macros) can
 definitely bridge the gap and let you manipulate them in the obvious
 way, while admitting the usual implementation.

We do a lot of things because they are efficient.  That is why
gaussian distributions are everywhere in statistics, people
approximate nonlinear functions with sums of kernels, etc.  It
shouldn't be the end goal though, unless it really is the most
expressive way of dealing with things.  My personal opinion is that
graphs are more expressive, and I think it would be a good idea to
move towards modeling knowledge and systems with graphical structures.

 I don't think they have to be.  You can view functions as names for
 temporally ordered sequence of declarative implication statements.
 Databases just leave out the logic (this is hyperbole, I know), so you
 have to do it in client code.  I don't feel that a database
 necessarily has to be a separate entity, that is just an artifact of
 the localized, specialized view of computation.  As stronger
 abstractions are developed and concurrent, distributed computation is
 rigorously systematized, I think we'll go full circle.

 Maybe I'm too tired, but this went straight over my head, sorry.
 Perhaps you could be a bit more explicit about what you mean by the
 implications/logic?

Well,  the curry howard correspondance says that every function can be
seen as a named implication of outputs given inputs, with the code for
that function being a representation of its proof.  Since pretty much
every function is a composition of many smaller functions, this holds
down to the lowest level.  Even imperative statements can be viewed as
functions in this light, if you assume discrete time, and view every
function or statement as taking the state of the world at T as an
implicit input and  returning as an implicit output the state of the
world at T+1.  Thus, every function (and indeed pretty much all code)
can be viewed as a named collection of implication statements in a
particular context :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-29 Thread Nathan Rice
 He did no such thing. I challenge you to find me one place where Joel has
 *ever* claimed that the very notion of abstraction is meaningless or
 without use.

When great thinkers think about problems, they start to see patterns.
They look at the problem of people sending each other word-processor
files, and then they look at the problem of people sending each other
spreadsheets, and they realize that there's a general pattern: sending
files. That's one level of abstraction already. Then they go up one
more level: people send files, but web browsers also send requests
for web pages. And when you think about it, calling a method on an
object is like sending a message to an object! It's the same thing
again! Those are all sending operations, so our clever thinker invents
a new, higher, broader abstraction called messaging, but now it's
getting really vague and nobody really knows what they're talking
about any more. Blah.

When you go too far up, abstraction-wise, you run out of oxygen.
Sometimes smart thinkers just don't know when to stop, and they create
these absurd, all-encompassing, high-level pictures of the universe
that are all good and fine, but don't actually mean anything at all.

To me, this directly indicates he views higher order abstractions
skeptically, and assumes because he does not see meaning in them, they
don't hold any meaning.  Despite Joel's beliefs, new advances in
science are in many ways the result of advances in mathematics brought
on by very deep abstraction.  Just as an example, Von Neumann's
treatment of quantum mechanics with linear operators in Hilbert spaces
utilizes very abstract mathematics, and without it we wouldn't have
modern electronics.

I'm 100% behind ranting on software hype.  Myopically bashing the type
of thinking that resulted in the computer the basher is writing on,
not so much.  If he had said if you're getting very high up, find
very smart people and talk to them to make sure you're not in wing nut
territory I could have given him a pass.

I really wish people wouldn't try to put Joel up on a pedestal.  The
majority of his writings either seem like sensationalist spins on
tautological statements, self aggrandizement or luddite trolling.  At
least Stephen Wolfram has cool shit to back up his ego, Fog Creek
makes decent but overpriced debuggers/version control/issue
trackers... From my perspective, Stack Overflow is the first really
interesting thing Joel had his hand in, and I suspect Jeff Atwood was
probably the reason for it, since SO doesn't look like anything Fog
Creek ever produced prior to that.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-29 Thread Nathan Rice
 He did no such thing. I challenge you to find me one place where Joel
 has *ever* claimed that the very notion of abstraction is meaningless
 or without use.
 [snip quote]
 To me, this directly indicates he views higher order abstractions
 skeptically,

 Yes he does, and so we all should, but that's not the claim you made. You
 stated that he fired the broadsides at the very notion of abstraction.
 He did no such thing. He fired a broadside at (1) software hype based on
 (2) hyper-abstractions which either don't solve any problems that people
 care about, or don't solve them any better than more concrete solutions.

Mathematics is all about abstraction.  There are theories and
structures in mathematics that have probably gone over a hundred years
before being applied.  As an analogy, just because a spear isn't
useful while farming doesn't mean it won't save your life when you
venture into the woods and come upon a bear.

 and assumes because he does not see meaning in them, they
 don't hold any meaning.

 You are making assumptions about his mindset that not only aren't
 justified by his comments, but are *contradicted* by his comments. He
 repeatedly describes the people coming up with these hyper-abstractions
 as great thinkers, clever thinkers, etc. who are seeing patterns in
 what people do. He's not saying that they're dummies. He's saying that
 they're seeing patterns that don't mean anything, not that the patterns
 aren't there.

He is basically saying they are too clever for their own good, as a
result of being fixated upon purely intellectual constructs.  If math
was a failed discipline I might be willing to entertain that notion,
but quite the opposite, it is certainly the most successful area of
study.


 Despite Joel's beliefs, new advances in science
 are in many ways the result of advances in mathematics brought on by
 very deep abstraction.  Just as an example, Von Neumann's treatment of
 quantum mechanics with linear operators in Hilbert spaces utilizes very
 abstract mathematics, and without it we wouldn't have modern
 electronics.

 I doubt that very much. The first patent for the transistor was made in
 1925, a year before von Neumann even *started* working on quantum
 mechanics.

The electronic properties of silicon (among other compounds) is an
obvious example of where quantum theory provides for us.  We might
have basic circuits, but we wouldn't have semiconductors.

 In general, theory *follows* practice, not the other way around: parts of
 quantum mechanics theory followed discoveries made using the transistor:

You do need data points to identify an explanatory mathematical structure.

 The Romans had perfectly functioning concrete without any abstract
 understanding of chemistry. If we didn't have QM, we'd still have
 advanced electronics. Perhaps not *exactly* the electronics we have now,
 but we'd have something. We just wouldn't understand *why* it works, and
 so be less capable of *predicting* useful approaches and more dependent
 on trial-and-error. Medicine and pharmaceuticals continue to be
 discovered even when we can't predict the properties of molecules.

The stochastic method, while useful, is many orders of magnitude less
efficient than analytically closed solutions.  Not having access to
closed form solutions would have put us back hundreds of years at
least.

 My aunt makes the best damn lasagna you've ever tasted without any
 overarching abstract theory of human taste. And if you think that quantum
 mechanics is more difficult than understanding human perceptions of
 taste, you are badly mistaken.

Taste is subjective, and your aunt probably started from a good recipe
and tweaked it for local palates.  That recipe could easily be over a
hundred years old.  An overarching mathematical theory of human
taste/mouth perception, if such a silly thing were to exist, would be
able to generate new recipes that were perfect for a given person's
tastes very quickly.

Additionally, just to troll this point some more (fun times!), I would
argue that there is an implicit theory of human taste (chefs refer to
it indirectly as gastronomy) that is very poorly organized and lacks
any sort of scientific rigor.  Nonetheless, enough empirical
observations about pairings of flavors, aromas and textures have been
made to guide the creation of new recipes.  Gastronomy doesn't need to
be organized or rigorous because fundamentally it isn't very
important.

 In any case, Spolsky is not making a general attack on abstract science.
 Your hyperbole is completely unjustified.

The mathematics of the 20th century, (from the early 30s onward) tend
to get VERY abstract, in just the way Joel decries.  Category theory,
model theory, modern algebraic geometry, topos theory, algebraic graph
theory, abstract algebras and topological complexes are all very
difficult to understand because they seem so incredibly abstract, yet
most of them already have important applications.  I'm 100% positive
if you 

Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-03-29 Thread Nathan Rice
 Here's a thought experiment.  Imagine that you have a project tree on
 your file system which includes files written in many different
 programming languages.  Imagine that the files can be assumed to be
 contiguous for our purposes, so you could view all the files in the
 project as one long chunk of data.  The directory and file names could
 be interpreted as statements in this data, analogous to in the context
 of somedirectory or in the context of somefile with sometype.  Any
 project configuration files could be viewed as declarative statements
 about contexts, such as in xyz context, ignore those or in abc
 context, any that is actually a this.  Imagine the compiler or
 interpreter is actually part of your program (which is reasonable since
 it doesn't do anything by itself).  Imagine the build management tool is
 also part of your program in pretty much the same manner.  Imagine that
 your program actually generates another program that will generate the
 program the machine runs.  I hope you can follow me here, and further I
 hope you can see that this is a completely valid description of what is
 actually going on (from a different perspective).
 [...]
 What does pushing the abstraction point that far up provide?

 I see why you are so hostile towards Joel Spolsky's criticism of
 Architecture Astronauts: you are one of them. Sorry Nathan, I don't know
 how you breathe that high up.

 For what it's worth, your image of everything from the compiler on up is
 part of your program describes both Forth and Hypercard to some degree,
 both of which I have used and like very much. I still think you're
 sucking vacuum :(

We live in a world where the tools that are used are based on
tradition (read that as backwards compatibility if it makes you feel
better) and as a mechanism for deriving personal identity.  The world
is backwards and retarded in many, many ways, this problem is
interesting to me because it actually cuts across a much larger tract
than is immediately obvious.

People throughout history have had the mistaken impression that the
world as it existed for them was the pinnacle of human development.
Clearly all of those people were tragically deluded, and I suspect
that is the case here as well.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Number of languages known [was Re: Python is readable] - somewhat OT

2012-03-23 Thread Nathan Rice
Logo.  It's turtles all the way down.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Stream programming

2012-03-23 Thread Nathan Rice
 I will use = to mean is equivalent to. That's not part of the DSL.
 A flow has one or more streams:
  1 stream:
    [1,2,3]
  2 streams:
    [1,3,5] | [2,4,6]
 Two flows can be concatenated:
  [1,2,3] + [4,5,6] = [1,2,3,4,5,6]
  [0] + ([1,2] | [3,4]) + [10] = [0,1,2,10] | [0,3,4,10]
  ([1,2] | [10,20]) + ([3,4] | [30,40]) = [1,2,3,4] | [10,20,30,40]

Algebraically, your concatenation rules don't really make sense - your
flows are both distributive and non distributive.  You also make the
implicit assumption of an order over streams in a flow, but disregard
the implications of that assumption in some cases.  I understand what
you're trying to communicate, so I think you need to be a little more
strict and explicit in your definitions.

 A flow can be transformed:
  [1,2] - f = [f(1),f(2)]
  ([1,2] | [3,4]) - f = [f(1,3),f(2,4)]
  ([1,2] | [3,4]) - [f] = [f(1),f(2)] | [f(3),f(4)]
  ([1,2] | [3,4]) - [f,g] = [f(1),f(2)] | [g(3),g(4)]
  [1,2] - [f,g] = [f(1),f(2)] | [g(1),g(2)]

Given the examples you pose here, it is clear that you are assuming
that the streams are synchronized in discrete time.  Since you do not
provide any mechanism for temporal alignment of streams you are also
assuming every stream will have an element at every time point, the
streams start at the same time and are of the same length.  Is this
what you want?  These seem like pretty rough simplifying assumptions.

 Some functions are special and almost any function can be made special:
  [1,2,3,4,5] - filter(isprime) = [2,3,5]
  [[],(1,2),[3,4,5]] - flatten = [1,2,3,4,5]
 Note that 'filter' is not really necessary, thanks to 'flatten'.

This implies that your transformations again produce flows.  You
should explicitly state this.

 Flows can be named, remembered and used
  as a value:
    [1,2,3,4,5] - 'flow' + val('flow') = [1,2,3,4,5]*2

Is this a flow with two identical streams, or a flow with one long
stream formed by concatenation?

  as a transformation chain:
    [1,2,3] - skipfirst - 'again' | [4,5,6] - func('again')
      = [2,3] | [5,6]
  Recursion is also possible and stops when a function is applied to an empty
 sequence.
 Flows can be saved (push) and restored (pop) :
  [1,2,3,4] - push - by(2) - 'double' - pop | val('double')
      = [1,2,3,4] | [2,4,6,8]
 There are easier ways to achieve the same result, of course:
  [1,2,3,4] - [id, by(2)]

You are grasping at an algebra here, a sort of calculus of temporal
observations.  You need to step back and make it rigorous before you
worry about issues such as a readable syntax.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Stream programming

2012-03-23 Thread Nathan Rice
  I will use = to mean is equivalent to. That's not part of the DSL.
  A flow has one or more streams:
   1 stream:
     [1,2,3]
   2 streams:
     [1,3,5] | [2,4,6]
  Two flows can be concatenated:
   [1,2,3] + [4,5,6]=  [1,2,3,4,5,6]
   [0] + ([1,2] | [3,4]) + [10]=  [0,1,2,10] | [0,3,4,10]
   ([1,2] | [10,20]) + ([3,4] | [30,40])=  [1,2,3,4] | [10,20,30,40]


 Algebraically, your concatenation rules don't really make sense - your
 flows are both distributive and non distributive.  You also make the
 implicit assumption of an order over streams in a flow, but disregard
 the implications of that assumption in some cases.  I understand what
 you're trying to communicate, so I think you need to be a little more
 strict and explicit in your definitions.

 When concatenating, either there are the same number of streams, or one
 of them is a single stream which is duplicated.

 Therefore, in this example:

    [0] + ([1, 2] | [3, 4])

 you're concatenating a single stream with a pair, so the single stream
 is duplicated:

    ([0] | [0]) + ([1, 2] | [3, 4])

 and then they can be concatenated:

    ([0, 1, 2] | [0, 3, 4])

 However, this:

    ([0, 1] | [2, 3]) + ([4, 5] | [6, 7] | [8, 9])

 won't work.

I understand how he wants the system to work in this case; my point
was that it isn't consistent.

He stated flows can be concatenated, so [0] is just a flow of a single
stream.  Because he clearly intends that streams in a flow are
ordered, that indicates that he wants some sort of algebraic module.
He could get close if he can extend a stream to meet the requirements
of a ring, then a flow would be a module over the ring of streams.
The problem he is going to run into is that operations on streams as
he defines them are not commutative.  Identity elements for the two
binary operations are also not immediately obvious to me.

He could just be smart and use the pi calculus, it is rigorously
developed and can model his desired behavior, if he reformulates it
slightly.

Another option is just to give up on being rigorous.  Given the
abstract treatment he attempted I would be disappointed, but if his
only goal is to get practice writing code and he isn't interested in
exploring the conceptual space of the problem domain it would be the
right decision.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Stream programming

2012-03-23 Thread Nathan Rice
  I understand what
 you're trying to communicate, so I think you need to be a little more
 strict and explicit in your definitions.


 No, I don't think you understand what I meant.

I don't agree. Sorry.

 Yes. I thought that streams as an alternative to functional programming were
 widely known.

Streams aren't really a paradigm of computation.  They're a semantic
element of a computational system which cuts across paradigms.  If you
want to retract that and say you were talking about dataflow
programming (which is much larger than streams, and actually has a
cohesive definition), I won't hold it against you.  Ultimately though,
functional programming and dataflow programming are closely linked,
the main difference being the use of queues based rather than stacks.

 Isn't that obvious? BTW, those are not rigorous definitions. I thought I was 
 talking to people who regularly works with streams.

That is the GPU mailing list, down the hall on the left.

 Instead of talking of what I wasn't trying to do and, indeed, I didn't do,
 you should try to understand what I wanted to do and, in fact, I did.
 I'm afraid your cup is too full to understand simple things as the one I
 wrote in my OP.

Clearly, because I didn't explicitly include the possibility that you
are just writing throwaway code with no attempt at development of
ideas for the purpose of practicing writing code in the paragraph
after the one you quoted.

If your goal is to learn to code, instead of posting a message stating
that you have a superior way to compose code, you might want to try to
solve a problem and ask others their opinion of the structure and
techniques in your code.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-22 Thread Nathan Rice
 If I'm reading you correctly, you're expressing frustration with the
 state of language syntax unification in 2012.  You mention language in a
 broad sense (not just programming languages, but also English, math,
 logic, etc.), but even in the narrow context of programming languages,
 the current state of the world is pretty chaotic.

 And this is a good thing. Programming languages are chaotic because the
 universe of programming problems is chaotic, and the strategies available
 to solve those problems are many and varied.

 Different programming languages are good for different things because
 they have been designed to work in different problem/solution spaces.
 Although I dislike C with a passion, I do recognise that it is good for
 when the programmer needs fine control over the smallest details. It is,
 after all, a high-level assembler. Likewise for Forth, which lets you
 modify the compiler and language as you go.

There is a concept in statistical/mathematical modeling called minimum
message length (a close analog is minimum description length), which
asserts that the optimum model for some set of information is the one
that minimizes the sum of the length of the model and the length of
the set described by that model.  Clearly no model is going to be
optimal for every set of information.  What I was alluding to in the
post that Steve Howell replied to was that we need to have a
programming language that is a model of models, then include a second
order model as part of the program.  Having one core language with
many DSLs that can interoperate is infinitely better than having many
languages that cannot.  A language designed in such a way would also
prevent issues like the Python 2 - 3 fiasco, because two versions of
a DSL can be separate, and code can reference them independently while
being able to interoperate.

 Some languages are optimized for the compiler, some for the writer, and
 some for the reader. So are optimized for numeric work, others for
 database access. Some are Jack-Of-All-Trades. Each language encourages
 its own idioms and ways of thinking about programming.

The difference between compiler optimized and writer optimized
languages is how many assertions they require about the thing being
modeled to be a valid program, given its deductive rules.  Ideally,
the number of assertions should be flexible, and the
interpreter/compiler should try and figure out the best way to
implement it given the information it has.

 When it comes to programming, I say, let a thousand voices shout out.
 Instead of imagining a single language so wonderful that every other
 language is overshadowed and forgotten, imagine that the single language
 is the next Java, or C, or even for that matter Python, but whatever it
 is, it's not ideal for the problems you care about, or the way you think
 about them. Not so attractive now, is it?

I agree about letting a thousand voices shout out, in the context of
an embedding language that guarantees code interoperability.
Additionally, the size of optimal DSLs for different areas is actually
quite small, yet having separate languages for each DSL requires the
user to re-learn common patterns such as collection manipulation, IO,
etc.  Pretty horrible all around.

 The optimistic view is that there will be some kind of inflection point
 around 2020 or so.  I could imagine a perfect storm of good things
 happening, like convergence on a single browser platform,

 You call that a perfect storm of good things. I call that sort of
 intellectual and software monoculture a nightmare.

The cores of English and math are pretty much singularly represented.
At more nuanced or abstract levels, there is divergence in order to
simplify the process of describing complicated things.  How would you
like it if linear algebra or algebraic geometry re-invented addition,
multiplication, etc with completely different syntax and semantics
(I'm ignoring non-commutativity of vector space multiplication)

 I want a dozen browsers, not one of which is so common that web designers
 can design for it and ignore the rest, not one browser so common that
 nobody dares try anything new.

How about one browser that is infinitely configurable?  That way if
someone tries something new, you can try it as well without precluding
anything else you already do.

The CLI/JVM provide some flexibility, but they are not the correct
path.  They model the executable machine representations of language,
rather than modeling the meta structure of language.  This means that
you still lack flexibility and dynamism.  At least things are moving
in the right direction.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-22 Thread Nathan Rice
On Thu, Mar 22, 2012 at 9:17 AM, Chris Angelico ros...@gmail.com wrote:
 On Thu, Mar 22, 2012 at 11:47 PM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 Having one core language with
 many DSLs that can interoperate is infinitely better than having many
 languages that cannot.  A language designed in such a way would also
 prevent issues like the Python 2 - 3 fiasco, because two versions of
 a DSL can be separate, and code can reference them independently while
 being able to interoperate.

 This is either utterly impossible, or already available, depending on
 your point of view.

Of course it is already available.  It is called the laws of physics.
Everything we know of inter-operates in the context of physical
reality perfectly.

 To have an infinitely-configurable program, you must make its
 configuration equivalent to writing code. There is already an
 infinitely-configurable program in Unix: gcc config.c; ./a.out takes
 a simple-format text file called config.c and processes it.

It is true that infinite configuration requires that the configuration
be specified in the language of the program.  What's the problem?

 You want infinite DSLs? Behold!

 $ ./module1 | ./module2 | ./module3 | ./module4

 Each one has a shebang that tells you what they are (Python 2, Python
 3, something else entirely). There's a very strict interoperability
 protocol between the modules - they pass information around through
 stdout and stdin. You can write any module in any language, and you
 can rewrite module1 for Python 3 without affecting any other or the
 invocation sequence.

It has always been possible to get from one point in space to another
point in space in finite time.  Was the invention of the automobile
was redundant and unimportant?  Obviously not, the characteristics of
the process matter.

For example, your ability to reason about the behavior of the system
you posited as a whole is limited.  Are there parts of the different
modules that can execute concurrently?  Is the output of module1
guaranteed to be acceptable as the input for module2?  Is part of
module3 redundant (and thus avoidable) given some conditions in
module1?  If you make a change in module2 what effect does that have
on module3 and module4?  What if you need to go back and forth between
module2 and module3 until some criterion is met before you transition
to module4?  What if you sometimes want to run module2b instead of
module2?

 Problems always come when you want to share data between dissimilar
 modules. There's no single perfect data-transfer protocol that works
 across all languages. What does it mean to call a function? If you
 truly want this level of flexibility, the best thing to do is to
 separate sections cleanly. In fact, the pipe system I show above could
 be used that way, although it's stupidly ugly. Everything going on
 stdout/stdin has a two-word dispatch envelope with a from and a to,
 and each module reads a line, and if it's not addressed to it, passes
 it on to stdout. Responses get sent out with their from and to
 reversed. All you need is for the last module's stdout to be linked
 back into the first module's stdin (not sure if you can do that or not
 - it has the feeling of plugging a power strip into itself), and it'll
 work perfectly. Add a bit of boilerplate so that the application
 developers don't see what's happening underneath, and you could
 pretend that dissimilar languages are able to call into each other.
 Doesn't mean it's efficient though!

What is a function?  You could say that it is a sequence of logical
statements that relates some assertion with another.  You can make a
big deal about call by name versus call by value, but it only really
matters on a conceptual level when dealing with infinite objects that
do not have an analytic closure.  You can make a big deal about data
format, but scientists have been communicating using different unit
systems for hundreds of years, I don't see assertions of relationship
between structures as different from unit conversions from imperial to
metric; it's all data.  There are of course a few snags such as
cardinality of the set represented by the integer data type in one
case versus another, but that is a low level detail that would be a
problem if DSLs were embedded in an expressive modelling language.
Data structures ultimately boil down to assertions, assertions about
those assertions and relations between assertions.

 TLDR version: Infinite flexibility means you're doing nothing.

I could address that from a number of ways.  First off, anything that
is Turing complete is basically infinitely flexible but the
difference in expressiveness (as measured by the combined length of
the program and its input required to generate some output) varies
over orders of magnitudes.  So, we're actually discussing infinitely
expressive though in fact we don't need to appeal to infinity here,
so that is a strawman.  The reason for that is the system in which

Re: Python is readable

2012-03-22 Thread Nathan Rice
 There is a concept in statistical/mathematical modeling called minimum
 message length (a close analog is minimum description length), which
 asserts that the optimum model for some set of information is the one
 that minimizes the sum of the length of the model and the length of the
 set described by that model.

 (1) Optimum in what sense?

Oh, I don't know, the information theoretic one?  Of course, if you're
part of the department of redundancy department, that might seem to
appear to look like a poor, weak, sub-optimal criterion for the
purposes of evaluation of optimality, goodness and positive quality.

If you're getting hung up on the fact that there are deep ties to data
compression in this language, let me help you out.  Imagine that
instead of having a simple Boolean algebra of two values, the possible
values ranged over a set of elementary concepts.  You are then trying
to come up with a set of compound concepts and a permutation of those
concepts that can describe

 (2) What does this have to do with designing programming languages?

A program is a representation of knowledge (i.e. a model) which a
machine has the ability to interpret.  Let me know if you can't
understand this, I'll break it down further for you.

 This discussion sounds to me like the apocryphal story about the
 spherical cow.

 http://en.wikipedia.org/wiki/Spherical_cow

When you take the baton, you're supposed to keep running along the
path in the same direction as the person who handed it to you.

 Clearly no model is going to be optimal
 for every set of information.  What I was alluding to in the post that
 Steve Howell replied to was that we need to have a programming language
 that is a model of models, then include a second order model as part of
 the program.  Having one core language with many DSLs that can
 interoperate is infinitely better than having many languages that
 cannot.

 Some people, when confronted with a problem, think I know, I'll use a
 DSL. Now they have two problems.

Sure.  When confronted with the problem of finding the area under a
curve, using integral calculus is going to make things worse...  I
should just manually sum the infantesimals, from now until the end of
time.

 And some people think I know, I'll use a meta-language with an infinite
 number of infinitely variable DSLs. Now they have an infinite number of
 problems.

I'll agree with you, if we change that statement to say an infinite
number of possible problems, all isomorphic to each other.

 A language designed in such a way would also prevent issues
 like the Python 2 - 3 fiasco,

 What fiasco?

The extremely slow uptake?  I don't really care one way or another but
a lot of the devs have lamented the issue.

 You've just lost an awful lot of credibility with me.

I didn't lose anything, technically you lost some of your belief in my
credibility.

So, tautologically, you are the one that lost in this situation.

 I'm just surprised you didn't manage to fit quantum mechanics and the
 interconnectedness of all things into it :)

Math/Logic are encompassing.  I could draw analogies to quantum theory
if you really wanted (category theory is great for this sort of
thing).  As for the interconnectedness of all things, that is quack
language, I do science.

 TL;DR there are a huge number of incompatible programming languages
 because people are modeling a permutation rather than the input to a
 permutation generating function.

 No offence Nathan, but I think you need to come back down to earth for
 air before you black out:

 http://www.joelonsoftware.com/articles/fog18.html

I read that article a long time ago, it was bullshit then, it is
bullshit now.  The only thing he gets right is that the Shannon
information of a uniquely specified program is proportional to the
code that would be required to generate it.  Never mind that if a
program meets a specification, you shouldn't care about any of the
values used for unspecified parts of the program.  If you care about
the values, they should be specified.  So, if Joel had said that the
program was uniquely specified, or that none of the things that
weren't specified require values in the programming language, he might
have been kinda, sorta right.  Of course, nobody cares enough to
specify every last bit of minutiae in a program, and specifications
change, so it is pretty much impossible to imagine either case ever
actually occurring.

 Or at least before *I* black out. Even if somebody manages to write your
 meta-language, you're going to run into the problem of who is going to be
 able to use it. The typical developer knows three, maybe four languages
 moderately well, if you include SQL and regexes as languages, and might
 have a nodding acquaintance with one or two more.

Please don't black out Steven.  I'm trying to encourage thought in
interesting directions; you can't think when you're unconscious.

Lets draw the analogy to mathematicians.  If a mathematician wants to

Re: Python is readable

2012-03-22 Thread Nathan Rice
 For example, your ability to reason about the behavior of the system
 you posited as a whole is limited.  Are there parts of the different
 modules that can execute concurrently?  Is the output of module1
 guaranteed to be acceptable as the input for module2?  Is part of
 module3 redundant (and thus avoidable) given some conditions in
 module1?  If you make a change in module2 what effect does that have
 on module3 and module4?  What if you need to go back and forth between
 module2 and module3 until some criterion is met before you transition
 to module4?  What if you sometimes want to run module2b instead of
 module2?

 Pipes allow different modules to execute concurrently (except on DOS
 and maybe Windows, haven't checked). Nothing in ANY language
 guarantees acceptable input, but protocolling would do that for you.
 If part of module3 is redundant, you don't call it. If you make a
 change to one that affects others, then you fix the others, same as in
 any other coding system (or non-coding system - if you upgrade your
 hardware from an 8086 with 1MB of memory to a modern box with 4GB,
 you'll have to rewrite your code to take advantage of it). The
 (somewhat stupid) protocol I suggested allows you to go between 2 and
 3 before going to 4. If you want module2b, you add it to the chain and
 call on it.

 Yep, Unix solved all your problems back in the 1970s.

Pipes do not provide any fine grained control over the concurrent
behavior.  If you want to change the order of calls, suddenly you have
to write a bash script (with its own set of issues), etc.

Unix solved these problems in much the same way that the evolution of
appendages solved the problem of changing location from one point to
another before the automobile.  The process matters.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-22 Thread Nathan Rice
 Do you think we'll always have a huge number of incompatible
 programming languages?  I agree with you that it's a fact of life in
 2012, but will it be a fact of life in 2062?

 It will be a fact of life wherever Godels theorem is; which put
 simplistically is: consistency and completeness cannot coexist.  This
 is the 'logic-generator' for the mess in programming languages.
 Put in more general terms:
 Completeness is an 'adding' process
 Consistency is a 'subtracting' process
 Running the two together, convergence is hopeless.

This isn't exactly correct.  The incompleteness theorem basically
shows that in a sufficiently expressive system, there are statements
in the system that cannot be proven given the language of that system.
 We live with this already given the fact that the incompleteness
theorem is closely related to Turing's halting problem.  That doesn't
indicate anything about the convergence of programming languages.  It
does say that we will need some form of unit testing or restricted
subset simulation system as an adjunct to formal verification in most
cases, until the end of time.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-21 Thread Nathan Rice
MOAR TROLLING...

 In my opinion, people who make statements such as #1/2 are imperative,
 #3 is OO are missing pretty much the entire point of what OO is.

 OO is much more about semantics and the way code is structured. The
 difference between #1/2 (especially #1, of course) and #3 is
 surface-level syntax only.

The idea of actions as concrete attributes of entities is probably the
worst bit of object oriented programming, except perhaps inheritance.
Events occur in the context of multiple entities, but they are
conceptually distinct and should not be subordinated.  Furthermore, if
you have an explicit self or this context, your ability to override
elements of an event is limited to things which are directly
encapsulated in that context.  Additionally, dynamic dispatch induces
overhead and the possibility of action at a distance.  Reflective
template meta-programming and explicit attribute delegation are VASTLY
superior.

To rant about inheritance, outside of mathematics platonic ideals are
bullshit.  Natural kinds are the closest we might actually be able to
come to ideals, and philosophers still debate whether atomic elements
and subatomic particles should have this designation. On the macro
scale, classes or types are dynamic, fuzzy unions of structure,
context and intent.  Making any sort of invariant categorical
statement about real things is just begging to be proven wrong.
Programmers would be much better off if we made assertions about
relationships and structure with an explicit, contextual reference.  I
think this would simplify code reuse, since you would be able to
compare contexts to know if program elements were compatible and
programs could be assembled by the union or intersection of sets of
assertions.

 About the strongest statement you can make along those lines is that #3
 will allow you to do dynamic dispatch on the type of 'stack' while #1/2
 won't, but even that isn't true of course. For instance, CLOS will let
 you write '(push stack item)' (which is the direct analogy in that
 language to #1) and do even more powerful dynamic dispatch than what a
 language like C++, Java, or Python will let you do.


 In the grand scheme of things, of course code structure and semantics
 are more important the surface-level syntax.

 If you take it as a given that structure/semantics are sound (big
 assumption, I know), then the next issue with regards to readability
 is the syntax itself.

Sadly, defining sound (i.e. valid) language semantics is not terribly
difficult; Turing complete systems occur spontaneously with surprising
frequency in nature.  The problem is that fundamentally, languages
model the conceptual space at large, but language designers choose a
semantic vocabulary that models their minuscule subset of that space.
This semantic vocabulary is by its nature static, while the conceptual
space is dynamic.  We aren't going to get semantics really right until
we model the dynamical meta structure of the concept space, and put
abstract structure, context and intent at the fore.

As for syntax, we have a lot of real domain specific languages, such
as English, math and logic. They are vetted, understood and useful
outside the context of programming.  We should approach the discussion
of language syntax from the perspective of trying to define a unified
syntactical structure for real these DSLs.Ideally it would allow
representation of things in a familiar way where possible, while
providing an elegant mechanism for descriptions that cut across
domains and eliminating redundancy/ambiguity.  This is clearly
possible, though a truly successful attempt would probably be a work
of art for the ages.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-20 Thread Nathan Rice
Just to troll the discussion a little bit more...

On Sun, Mar 18, 2012 at 6:02 PM, Chris Angelico ros...@gmail.com wrote:
 On Mon, Mar 19, 2012 at 8:30 AM, John Ladasky lada...@my-deja.com wrote:
 What I would say is that, when PROGRAMMERS look at Python code for the
 first time, they will understand what it does more readily than they
 would understand other unfamiliar programming languages.  That has
 value.

 This is something that's never truly defined. Everyone talks of how
 this language or that language is readable, but if you mean that you
 can look at a line of code and know what *that line* does, then Python
 suffers badly and assembly language wins out; but if you mean that you
 should be able to glance over an entire function and comprehend its
 algorithm, then I have yet to see any language in which it's not
 plainly easy to write bad code. Even with good code, anything more
 than trivial can't be eyeballed in that way - if you could, what would
 docstrings be for?

I agree, docstrings/code comments are a pretty obvious indication that
code (as it exists currently) fails as a human communication medium.
I suppose that I could make an exception for elaboration on statement
with subtle implications.  This seems like something people should
think more about fixing.

 Really, the metric MUST be Python programmers. Intuitiveness is of
 value, but readability among experienced programmers is far more
 useful. If I write a whole lot of code today, and next year I'm dead
 and someone else has replaced me, I frankly don't mind if he has to
 learn the language before he can grok my code. I _do_ mind if, even
 after he's learned the language, he can't figure out what my code's
 doing; and that's where Python's placed itself at about the right
 level - not so high that it's all in airy-fairy conceptual work, but
 not so low that it gets bogged down. There's a handful of other
 languages that are similarly placed, and they're the languages that I
 would call readable.

In mathematics, when you perform global optimization you must be
willing to make moves in the solution space that may result in a
temporary reduction of your optimality condition.  If you just perform
naive gradient decent, only looking to the change that will induce the
greatest immediate improvement in optimality, you will usually end up
orbiting around a solution which is not globally optimal.  I mention
this because any readability or usability information gained using
trained programmers is simultaneously measuring the readability or
usability and its conformance to the programmer's cognitive model of
programming.  The result is local optimization around the
current-paradigm minimum.  This is why we have so many nearly
identical curly brace C-like languages.

In my opinion, language readability and usability should be determined
based on the following tests:

- Given users with no programming experience:
-- What is the probability that they can correctly guess the result of
a program, and how long does it take?
-- What is the probability that they can take a program and correctly
modify it to change its output to another specified output, or modify
it to support another input representation, and how long does it take?

- Given users with no programming experience who are provided with a
controlled training period:
-- What is the probability that they can produce a program that
correctly implements a simple, completely described algorithm for
solving a puzzle or winning a game, and how long does it take?

- Given users with previous (but not extensive) programming experience
who are provided with a controlled training period:
-- What is the probability that they can produce a program that
correctly implements a simple, partially described algorithm for
solving a puzzle or winning a game, and how long does it take?
-- What is the probability that they can produce a program that
correctly implements a complex, completely described algorithm for
solving a puzzle or winning a game, and how long does it take?

It would probably also be worth examining user behavior relating to
code organization and composition under a variety of circumstances.
It seems likely that if proper organization and composition are
intuitive, productivity would scale well with program size.

 Here's an analogy: One statement (aka line of code, etc) corresponds
 to one sentence in English. Massive one-liners are like some of the
 sentences in Paul's epistles; assembly language is like The cat sat
 on the mat. Both are valid; both are hard to read.

This is one of my gripes with the dogmatic application of the break
it into multiple statements mantra of Python.  Not only are you
forced to use generators to maintain semantic equivalence in many
cases, in some cases a partial statement fragment doesn't have any
intuitive meaning.  The result is that readers are forced to hold the
value of intermediate_variable in their head while reading another
statement, then 

Re: Python is readable

2012-03-20 Thread Nathan Rice
 This is one of my gripes with the dogmatic application of the break it
 into multiple statements mantra of Python.

 I must admit I don't recognise that one, unless you're talking about not
 everything needs to be a one liner.
 ...
 Perhaps you could give some examples (actual or contrived) of stuff where
 breaking it into multiple statements is a bad thing?

One example is performing a series of transformations on a collection
of data, with the intent of finding an element of that collection that
satisfies a particular criterion.  If you separate out the individual
transformations, you need to understand generators or you will waste
space and perform many unnecessary calculations.  If you only ever do
a single transformation with a clear conceptual meaning, you could
create a master transformation function, but what if you have a
large number of potential permutations of that function?  What if you
are composing three or four functions, each of which is conditional on
the data?  If you extract things from a statement and assign them
somewhat arbitrary names, you've just traded horizontal bloat for
vertical bloat (with a net increase in volume), while forcing a reader
to scan back and forth to different statements to understand what is
happening.

To steal a line from Einstein, Make things as simple as possible, but
not simpler

 I agree, docstrings/code comments are a pretty obvious indication that
 code (as it exists currently) fails as a human communication medium.


 The fact that scientific journal articles start with a documentation string
 called an abstract does not indicate that scientific English fails as a
 human communication medium. Function docstrings say what the function does
 and how to use it without reading the code. They can be pulled out and
 displayed elsewhere. They also guide the reading of the code. Abstracts
 serve the same functions.

A paper, with topic introduction, methods exposition, data/results
description and discussion is a poor analog to a function.  I would
compare the abstract of a scientific paper to the overview section of
a program's documentation.  The great majority of the docstrings I see
are basically signature rehashes with added type information and
assertions, followed by a single sentence English gloss-over.  If the
code were sufficiently intuitive and expressive, that would be
redundant.  Of course, there will always be morbidly obese functions
and coders that like to wax philosophical or give history lessons in
comments.

Also, because of Sphinx, it is very common in the Python community
weave documents and code together in a way that is convenient for
authors but irritating for readers.  I personally would prefer not to
have to scroll past 100 lines of a tutorial with examples, tests and
what not in order to go from one function to another.  It would be
really awesome if everyone used links to that material in docstrings,
and the default sphinx theme created an inline collapsible iframe that
included that material for the HTML version.  Don't get me wrong, I
adore Sphinx, the problem here is people who are lazy or don't know
the right way to structure docs.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-20 Thread Nathan Rice
 The fact that scientific journal articles start with a documentation
 string
 called an abstract does not indicate that scientific English fails as a
 human communication medium. Function docstrings say what the function
 does
 and how to use it without reading the code. They can be pulled out and
 displayed elsewhere. They also guide the reading of the code. Abstracts
 serve the same functions.


 A paper, with topic introduction, methods exposition, data/results
 description and discussion is a poor analog to a function.  I would
 compare the abstract of a scientific paper to the overview section of
 a program's documentation.  The great majority of the docstrings I see
 are basically signature rehashes with added type information and
 assertions, followed by a single sentence English gloss-over.  If the
 code were sufficiently intuitive and expressive, that would be
 redundant.  Of course, there will always be morbidly obese functions
 and coders that like to wax philosophical or give history lessons in
 comments.


 Both abstracts and doc strings are designed to be and are read independently
 of the stuff they summarize. Perhaps you do not use help(obj) as often as
 some other people do.

I find help() to be mostly useless because of the clutter induced by
double under methods.  I use IPython, and I typically will either use
tab name completion with the ? feature or %edit obj if I really
need to dig around.  I teach Python to groups from time to time as
part of my job, and I usually only mention help() as something of an
afterthought, since typically people react to the output like a deer
in headlights.  Some sort of semantic function and class search from
the interpreter would probably win a lot of fans, but I don't know
that it is possible without a standard annotation format and the
addition of a namespace cache to pyc files.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python is readable

2012-03-20 Thread Nathan Rice
 One example is performing a series of transformations on a collection of
 data, with the intent of finding an element of that collection that
 satisfies a particular criterion.  If you separate out the individual
 transformations, you need to understand generators or you will waste
 space and perform many unnecessary calculations.  If you only ever do a
 single transformation with a clear conceptual meaning, you could create
 a master transformation function, but what if you have a large number
 of potential permutations of that function?

 I'm sorry, that is far too abstract for me. Do you have a *concrete*
 example, even an trivial one?

How about a hypothetical log analyzer that parses a log file that is
aggregated from multiple event sources with disparate record
structures.  You will need to perform a series of transformations on
the data to convert record elements from text to specific formats, and
your function for identifying alarm records is also dependent on
record structure (and possibly system state, imagining an intrusion
detection system).  Of course you could go through a lot of trouble to
dispatch and detect alarms over 6-7 statements, however given the
description for each log record you receive, convert text elements to
native data types based on the value of the first three fields of the
record, then trigger an alert if that record meets defined
requirements and assuming you have maps from record values to
conversion functions for record elements, and a map from record types
to alert criteria functions for record types already constructed, it
seems like a one liner to me.


 What if you are composing
 three or four functions, each of which is conditional on the data?  If
 you extract things from a statement and assign them somewhat arbitrary
 names, you've just traded horizontal bloat for vertical bloat (with a
 net increase in volume), while forcing a reader to scan back and forth
 to different statements to understand what is happening.

 First off, vertical bloat is easier to cope with than horizontal bloat,
 at least for people used to reading left-to-right rather than vertically.
 There are few anti-patterns worse that horizontal scrolling, especially
 for text.

I agree that if a line goes into horizontal scroll buffer, you have a
problem.  Of course, I often rail on parenthesized
function-taking-arguments expression structure for the fact that it
forces you to read inside out and right to left, and I'd prefer not to
conflate the two issues here.  My assertion is that given an
expression structure that reads naturally regardless, horizontal bloat
is better than larger vertical bloat, in particular when the vertical
bloat does not fall along clean semantic boundaries.


 Secondly, the human brain can only deal with a limited number of tokens
 at any one time. It's easier to remember large numbers when they are
 broken up into chunks:

 824-791-259-401 versus 824791259401

 (three tokens, versus twelve)

 Likewise for reading code. Chunking code into multiple lines instead of
 one long expression, and temporary variables, make things easier to
 understand, not harder.

This is true, when the tokens are an abstraction.  I read some of the
research on chunking, basically it came down to people being able to
remember multiple numbers efficiently in an auditory fashion using
phonemes.  Words versus random letter combinations have the same
effect, only with visual images (which is why I think Paul Graham is
full of shit with regards to his shorter is better than descriptive
mantra in old essays).  This doesn't really apply if storing the
elements in batches doesn't provide a more efficient representation.
Of course, if you can get your statements to read like sensible
English sentences, there is definitely a reduction in cognitive load.


 And thirdly, you're not forcing the reader to scan back and forth -- or
 at least if you are, then you've chosen your functions badly. Functions
 should have descriptive names and should perform a meaningful task, not
 just an arbitrary collection of code.

This is why I quoted Einstein.  I support breaking compound logical
statements down to simple statements, then combining those simple
statements.  The problem arises when your compound statement still
looks like A B C D E F G H I J K L M N, and portions of that
compound statement don't have a lot of meaning outside the larger
statement.  You could say X = A B C D E, Y = F G H I J, Z = K L M N,
then say X Y Z, but now you've created bloat and forced the reader to
backtrack.


 When you read:

 x = range(3, len(sequence), 5)

 you're not forced to scan back and forth between that line and the code
 for range and len to understand it, because range and len are good
 abstractions that make sensible functions.

 There is a lot of badly written code in existence. Don't blame poor
 execution of design principles on the design principle itself.

I like to be fair and even handed, and I recognize that tool 

Re: how to tell a method is classmethod or static method or instance method

2012-02-15 Thread Nathan Rice
 And I'll take this opportunity to plug my dualmethod descriptor:

 http://code.activestate.com/recipes/577030-dualmethod-descriptor/

I use an analogous pattern in SQL Alchemy all the time (it's called
hybridmethod/hybridproperty there).

+1 to dualmethod, that pattern is great when you want a method or
property that does something concrete when passed an instance, or
something abstract relating to all instances when passed a class.


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Looking for PyPi 2.0...

2012-02-15 Thread Nathan Rice
 Hopefully soon crate.io will be useful for finding modules ;) I have plans
 for it to try and, encourage people to host their code and encourage
 following packaging standards. I'm currently focused mostly on the backend
 stability (e.g. getting it stable) but emphasizing things that are generally
 good for the packaging ecosystem is something I hope to do.

I think providing commit hooks for version control ala read the docs
is the #1 thing you could do in the short term to add a lot of value.
That would be enough for me to adopt the service :)

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: frozendict

2012-02-10 Thread Nathan Rice
On Fri, Feb 10, 2012 at 5:08 AM, Chris Angelico ros...@gmail.com wrote:
 On Fri, Feb 10, 2012 at 1:30 PM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 The only thing needed to avoid the hash collision is that your hash
 function is not not 100% predictable just by looking at the python
 source code.  I don't see why every dict would have to be created
 differently.  I would think having the most ubiquitous data structure
 in your language be more predictable would be a priority.  Oh well

 It's perfectly predictable. If you put a series of keys into it, you
 get those same keys back. Nobody ever promised anything about order.

 If your hash function is not 100% predictable, that means it varies on
 the basis of something that isn't part of either the Python
 interpreter or the script being run. That means that, from one
 execution to another of the exact same code, the results could be
 different. The keys will come out in different orders.

I think having a hash function that is not referentially transparent
is a bad thing.  Basing your language on a non-deterministic function?
 Yeah...

A type factory that produces the dict type on interpreter
initialization (or, replaces the hash function, rather), and uses
time/system information/etc would solve the problem, while limiting
the introduced non-determinism.  I don't care if the order of
iteration for keys is different from interpreter run to run.

I have used frozenset(mydict.items()) when my requirements dictated.
It is a minor performance hit.

Lets also not forget that knowing an object is immutable lets you do a
lot of optimizations; it can be inlined, it is safe to convert to a
contiguous block of memory and stuff in cache, etc.  If you know the
input to a function is guaranteed to be frozen you can just go crazy.
Being able to freeze(anyobject) seems like a pretty clear win.
Whether or not it is pythonic is debatable.  I'd argue if the meaning
of pythonic in some context is limiting, we should consider updating
the term rather than being dogmatic.

Just my 2 cents...


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: frozendict

2012-02-10 Thread Nathan Rice
 Lets also not forget that knowing an object is immutable lets you do a
 lot of optimizations; it can be inlined, it is safe to convert to a
 contiguous block of memory and stuff in cache, etc.  If you know the
 input to a function is guaranteed to be frozen you can just go crazy.
 Being able to freeze(anyobject) seems like a pretty clear win.
 Whether or not it is pythonic is debatable.  I'd argue if the meaning
 of pythonic in some context is limiting, we should consider updating
 the term rather than being dogmatic.

Sweet, looking at the reason for rejection:

1. How dicts (and multiply nested objects) should be frozen was not
completely obvious
2. frozen() implies in place, thus confusing users
3. freezing something like a list is confusing because some list
methods would disappear or cause errors
4. Because automatic conversion in the proposal was seen as too
involved to be so magical
5. Because frozendicts are the main end user benefit, and using dicts
as keys was seen as suspect

Honestly, as far as #1, we already have copy and deepcopy, the can of
worms is already opened (and necessarily so).  For 2, choose a better
name?  For 3, we have abstract base classes now, which make a nice
distinction between mutable and immutable sequences; nominal types are
a crutch, thinking in terms of structure is much more powerful.  I
agree with point 4, if magic does anything besides make the code
conform to what an informed user would expect, it should be considered
heretical.  As for #5, I feel using a collection of key value
relations as a key in another collection is not inherently bad, it
just depends on the context... The mutability is the rub.  Also,
immutability provides scaffolding to improve performance and
concurrency (both of which are top tier language features).

I understand that this is one of those cases where Guido has a strong
bad feeling about something, and I think a consequence of that is
people tread lightly.  Perhaps I'm a bit of a language communist in
that regard (historically a dangerous philosophy :)

As an aside, I find it kind of schizophrenic how on one hand Python is
billed as a language for consenting adults (see duck typing, no data
hiding, etc) and on the other hand users need to be protected from
themselves.  Better to serve just one flavor of kool-aid imo.


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: frozendict

2012-02-09 Thread Nathan Rice
On Thu, Feb 9, 2012 at 5:33 AM, Duncan Booth
duncan.booth@invalid.invalid wrote:
 Nathan Rice nathan.alexander.r...@gmail.com wrote:

 I put dicts in sets all the time.  I just tuple the items, but that
 means you have to re-dict it on the way out to do anything useful with
 it.  I am too lazy to write a frozendict or import one, but I would
 use it if it was a builtin.

 I hope you sort the items before putting them in a tuple, otherwise how do
 you handle two identical dicts that return their items in a different
 order?

Two dicts created from the same inputs will return items in the same
arbitrary order.  As long as you don't insert or delete a key you're
fine.


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: frozendict

2012-02-09 Thread Nathan Rice
 Two dicts created from the same inputs will return items in the same
 arbitrary order.  As long as you don't insert or delete a key you're
 fine.

 Two dicts that contain the same keys and values may or may not return them
 in the same order:

 dict.fromkeys('ia')
 {'i': None, 'a': None}
 dict.fromkeys('ai')
 {'a': None, 'i': None}

 Would your system count those two dicts as the same?

 If the sequence in which the keys were added to the dict (and deleted if
 appropriate) is exactly the same then it is likely but still not guaranteed
 that they will have the same order. The only ordering guarantee is that
 within a single dict keys and values will appear in a consistent order so
 long as you don't add/delete keys between calls.

As I said, two dictionaries created from the same input will be the
same...  'ai' != 'ia'.  If I need to hash a dict that I don't know was
created in a deterministic order, I'd frozenset(thedict.items()).


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: frozendict

2012-02-09 Thread Nathan Rice
On Thu, Feb 9, 2012 at 11:35 AM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Thu, Feb 9, 2012 at 8:19 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 As I said, two dictionaries created from the same input will be the
 same...

 That's an implementation detail, not a guarantee.  It will hold for
 current versions of CPython but not necessarily for other Python
 implementations.

That is true.  The implications of the function that creates
dictionaries being non-deterministic are a little scary though, so I
suspect that it will hold :)

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: frozendict

2012-02-09 Thread Nathan Rice
On Thu, Feb 9, 2012 at 8:24 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 On Thu, 09 Feb 2012 09:35:52 -0700, Ian Kelly wrote:

 On Thu, Feb 9, 2012 at 8:19 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 As I said, two dictionaries created from the same input will be the
 same...

 That's an implementation detail, not a guarantee.  It will hold for
 current versions of CPython but not necessarily for other Python
 implementations.

 That day may be sooner than you think. It is very likely that in Python
 3.3, dict order will be randomized on creation as a side-effect of adding
 a random salt to hashes to prevent a serious vulnerability in dicts.

 http://securitytracker.com/id/1026478

 http://bugs.python.org/issue13703


 If there is anyone still assuming that dicts have a predictable order,
 they're going to be in for a nasty surprise one of these days.

The only thing needed to avoid the hash collision is that your hash
function is not not 100% predictable just by looking at the python
source code.  I don't see why every dict would have to be created
differently.  I would think having the most ubiquitous data structure
in your language be more predictable would be a priority.  Oh well


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Looking for PyPi 2.0...

2012-02-08 Thread Nathan Rice
As a user:
* Finding the right module in PyPi is a pain because there is limited,
low quality semantic information, and there is no code indexing.
* I have to install the module to examine it;  I don't need to look at
docs all the time, sometimes I just want a
package/class/function/method breakdown.
* Given the previous point, having in-line documentation would be nice
(for instance, just the output of .. automodule::)
* Package usage/modification stats are not well exposed
* No code metrics are available
* I would like some kind of social service integration, for tagging
and +1/likes.  I know ratings were scrapped (and they weren't that
useful anyhow), but for example, if Armin Ronacher or Robert Kern
thumbs up a module there is a pretty good chance I will be interested
in it.

As a developer:
* I don't want to have to maintain my code repository and my package
releases separately.  I want to let module repository know that my
code repository exists, and that branches tagged as release should
be made available.
* I want to maintain one README.


I don't like someone needs to do this now type posts but every time
I use PyPi it infuratiates me.  I usually end up finding modules via
Stack Overflow, which seems silly to me.


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: frozendict

2012-02-08 Thread Nathan Rice
 Turn the question around: why should there be?
 Python is intentionally parsimonious in adding builtins.

For the same reason there are frozensets?

I put dicts in sets all the time.  I just tuple the items, but that
means you have to re-dict it on the way out to do anything useful with
it.  I am too lazy to write a frozendict or import one, but I would
use it if it was a builtin.


Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: SnakeScript? (CoffeeScript for Python)

2012-02-03 Thread Nathan Rice
 Mm I don't think it's what the OP is asking (unless I misunderstood...).
 I think he wants to compile some syntax TO Python.
 But I don't really see why you would something like this (if not for fun).

 Maybe because you think that Python syntax could be improved upon --
 for instance, Python with pattern-matching would be freaking awesome
 -- but at the same time you want to leverage Python's extensive
 ecosystem of libraries.  So instead of creating your own brand-new
 language with no third party libraries whatsoever, you create one that
 just compiles down to regular Python.

You can generalize the dictionary based dispatch used for case
statements to do this.  The main downsides are:

1.) You have to define your functions ahead of time or use lambdas
2.) The syntax is not quite as nice as it could be (e.g.)

foo = DispatchDict({
Pattern1: f1,
Pattern2: f2,
etc...
})

Reminds me more of javascript than I would like.

 Then how are you going to maintain the code? Maintain the compiled
 code or the source?

 As with all compiled software, you maintain the input, not the output.

I think maintaining the output can be valuable.  There are going to be
things that can be expressed in the more verbose expanded form that
will not be easily expressible in the terse pre-translated macro.
Unfortunately, most macro writers don't put much time into making sure
their macro produces concise code.

 And proving that your translator is always correct

 That's what unit tests are for.

I have a love hate affair with unit tests.  You need them, but I'd
really rather analytically prove that my software is correct under
some set of assumptions.


Cheers,

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Constraints -//- first release -//- Flexible abstract class based validation for attributes, functions and code blocks

2012-01-26 Thread Nathan Rice
PyPi name:  constraintslib  (you'll be dissapointed if you get
constraints by accident)
Docs: http://packages.python.org/constraintslib/
Github: https://github.com/nathan-rice/Constraints

From the docs:

Constraints - Sleek contract-style validation tools
===

Constraints provides flexible validation tools for a variety of circumstances.
All validation in constraints is done by type checking.  Constraints provides
a special abstract base class (Constraints) which facilitates on the fly
construction of validation types.  Constraints also provides a special class
(Symbol) which can be used to generate natural, easy to read
constraint expressions.

for example::

from constraints.proxy import Symbol
from constraints.constraints import Constraints
X = Symbol()
SizeConstraint = Constraints(X * 2 + 1 = 5)
ModuloConstraint = Constraints(X % 2 != 0, X != 3)
CharacterConstraint = Constraints(X[-1] == h)
   # My apologies for the lambda spam.  I provide some functions in
   # constraints.util for this purpose...
callable_expr = lambda x: all(lambda x: isinstance(x, SizeConstraint), x)
CollectionConstraint = Constraint(callable_expr)
isinstance(1, SizeConstraint)
   False
isinstance(2, SizeConstraint)
   True
isinstance(1, ModuloConstraint)
   True
isinstance(blah, CharacterConstraint)
   True
isinstance([2, 3, 4, 5], CollectionConstraint)
   True

Constraint instances also provide descriptors which will verify values at set
time.  For example::

class Foo(object):
   ...x = Constraints(X  2)
   ...
bar = Foo()
bar.x = 1
   Traceback (most recent call last):
  ...
   AssertionError: Specified value (1) does not satisfy this constraint

Design by contract style preconditions, postconditions and invariants are also
supported, and can be used either as context managers or function decorators::

x_pre = SizeConstraint.precondition(x)
x_post = SizeConstraint.postcondition(x)
x = 1
with x_pre:
   ...   do_stuff()
   ...
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified pre-condition
x = 5
with x_post:
   ...   x -= 4
   ...
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified post-condition
@x_pre
   ... def foo(x):
   ...return x
   ...
foo(1)
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified pre-condition
@x_post
   ... def foo(x):
   ...return x - 5
   ...
foo(6)
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified post-condition

Symbol objects are very flexible, and provide a nice
way to specify your constraints without resorting to a domain specific language.
Symbol objects are fairly simple;  whenever an operation is performed on them,
they capture it and return a new Symbol object wrapping the operation so that
it can be performed with concrete input at a later time.  There are exceptions
to this, for example isinstance, which uses the metaclass method, and the type
constructors (str, int, bool, etc) which throw an error if the correct type is
not returned.
-- 
http://mail.python.org/mailman/listinfo/python-announce-list

Support the Python Software Foundation:
http://www.python.org/psf/donations/


Constraints -//- first release -//- Flexible abstract class based validation for attributes, functions and code blocks

2012-01-26 Thread Nathan Rice
PyPi name:  constraintslib  (you'll be dissapointed if you get
constraints by accident)
Docs: http://packages.python.org/constraintslib/
Github: https://github.com/nathan-rice/Constraints

From the docs:

Constraints - Sleek contract-style validation tools
===

Constraints provides flexible validation tools for a variety of circumstances.
All validation in constraints is done by type checking.  Constraints provides
a special abstract base class (Constraints) which facilitates on the fly
construction of validation types.  Constraints also provides a special class
(Symbol) which can be used to generate natural, easy to read
constraint expressions.

for example::

from constraints.proxy import Symbol
from constraints.constraints import Constraints
X = Symbol()
SizeConstraint = Constraints(X * 2 + 1 = 5)
ModuloConstraint = Constraints(X % 2 != 0, X != 3)
CharacterConstraint = Constraints(X[-1] == h)
   # My apologies for the lambda spam.  I provide some functions in
   # constraints.util for this purpose...
callable_expr = lambda x: all(lambda x: isinstance(x, SizeConstraint), x)
CollectionConstraint = Constraint(callable_expr)
isinstance(1, SizeConstraint)
   False
isinstance(2, SizeConstraint)
   True
isinstance(1, ModuloConstraint)
   True
isinstance(blah, CharacterConstraint)
   True
isinstance([2, 3, 4, 5], CollectionConstraint)
   True

Constraint instances also provide descriptors which will verify values at set
time.  For example::

class Foo(object):
   ...x = Constraints(X  2)
   ...
bar = Foo()
bar.x = 1
   Traceback (most recent call last):
  ...
   AssertionError: Specified value (1) does not satisfy this constraint

Design by contract style preconditions, postconditions and invariants are also
supported, and can be used either as context managers or function decorators::

x_pre = SizeConstraint.precondition(x)
x_post = SizeConstraint.postcondition(x)
x = 1
with x_pre:
   ...   do_stuff()
   ...
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified pre-condition
x = 5
with x_post:
   ...   x -= 4
   ...
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified post-condition
@x_pre
   ... def foo(x):
   ...return x
   ...
foo(1)
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified pre-condition
@x_post
   ... def foo(x):
   ...return x - 5
   ...
foo(6)
   Traceback (most recent call last):
  ...
   AssertionError: The value (1) did not meet the specified post-condition

Symbol objects are very flexible, and provide a nice
way to specify your constraints without resorting to a domain specific language.
Symbol objects are fairly simple;  whenever an operation is performed on them,
they capture it and return a new Symbol object wrapping the operation so that
it can be performed with concrete input at a later time.  There are exceptions
to this, for example isinstance, which uses the metaclass method, and the type
constructors (str, int, bool, etc) which throw an error if the correct type is
not returned.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Constraints -//- first release -//- Flexible abstract class based validation for attributes, functions and code blocks

2012-01-26 Thread Nathan Rice
On Thu, Jan 26, 2012 at 2:51 PM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 Ooh, runtime turing-complete dependent-types. :)

 I'm not sure if you're aware of the literature on this sort of thing.
 It's nice reading. A library such as this that's designed for it could
 be used for static checks as well.

Actually, that is kind of the direction I was going :)

One of the nice things about Haskell is that the language is designed
in a way that is conducive to
proving things about your code.  A side benefit of being able to prove
things about your code is that
in some cases you will be able to derive code just from well crafted
specifications (like higher order
Prolog).  This isn't a game changer yet, but with advances in theorem
proving software and a thoughtful
language ontology, I could see it taking off very soon.  Dijkstra was
focused primarily on this area for the
last 25 years of his life.

 Probably deserves a better name than constraintslib, that makes one
 think of constraint satisfaction.

As you can probably tell from my other projects, I'm bad at coming up
with snappy names.

 Any way to get them to raise a different error, such as ValueError (in
 particular for preconditions)?

Currently, no.  I would like to add an event mechanism, or some kind
of function hooks (ala Enthought Traits but much lighter).  I'm sure
I'll come up with something soon :)

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Constraints -//- first release -//- Flexible abstract class based validation for attributes, functions and code blocks

2012-01-26 Thread Nathan Rice
 May I suggest a look at languages such as ATS and Epigram? They use
 types that constrain values specifically to prove things about your
 program. Haskell is a step, but as far as proving goes, it's less
 powerful than it could be. ATS allows you to, at compile-time, declare
 that isinstance(x, 0 = Symbol()  len(L)) for some list L. So it
 might align well with your ideas.

Thanks for the tip.

 Probably deserves a better name than constraintslib, that makes one
 think of constraint satisfaction.

 As you can probably tell from my other projects, I'm bad at coming up
 with snappy names.

 I'm bad at doing research on previous projects ;)

I guess I'm not plugging my other projects enough...  You should check
out elementwise.

Thanks,

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Elementwise 0.120116 -//- beta release -//- Lazily compute functions, method calls and operations on all elements of an iterable (or graph).

2012-01-16 Thread Nathan Rice
Elementwise provides helpful proxy objects which let you perform a
series of computations on every element of an iterable or graph, in a
lazy manner.

Docs: http://packages.python.org/elementwise/
GitHub: https://github.com/nathan-rice/Elementwise
Examples:

The standard ElementwiseProxy:

 nums = ElementwiseProxy([1, 2, 3, 4)
 print nums.bit_length()
1, 2, 2, 3
 nums + 1
2, 3, 4, 5
 print nums * 2
2, 4, 6, 8
 print nums == 2
False, True, False, False
 print ((nums + 1) * 2 + 3).apply(float)
7.0, 9.0, 11.0, 13.0
 print (nums.apply(float) + 0.0001).apply(round, 2)
1.0, 2.0, 3.0, 4.0
 print abs(nums - 3)
2, 1, 0, 1
 print (nums * 2 + 3) / 4
 print efoo2.undo(3)
1, 2, 3, 4
 print ((nums * 2 + 3) / 4).replicate([2, 2, 3, 3])
1, 1, 2, 2
 words = ElementwiseProxy([one, two, three, four])
 print (words +  little indians).upper().split(
).apply(reversed).apply(_.join) * 2
'INDIANS_LITTLE_ONEINDIANS_LITTLE_ONE',
'INDIANS_LITTLE_TWOINDIANS_LITTLE_TWO',
'INDIANS_LITTLE_THREEINDIANS_LITTLE_THREE',
'INDIANS_LITTLE_FOURINDIANS_LITTLE_FOUR'

The PairwiseProxy:

 nums = PairwiseProxy([1, 2, 3, 4])
 nums + [1, 2, 3, 4]
2, 4, 6, 8
 nums * [2, 2, 3, 3]
2, 4, 9, 12
 nums == [2, 2, 3, 5]
False, True, True, False
 (nums.apply(float) / itertools.count(2) +
itertools.count(1)).apply(round, args=itertools.repeat([2]))
1.5, 2.67, 3.75, 4.8
 abs(nums - [3, 2, 1, 1])
2, 0, 2, 3
 (nums * [2, 2, 1, 5] + [3, 5, 9, 0]) / [4, 1, 2, 3]
1, 9, 6, 6
 ((nums * itertools.repeat(2) + itertools.repeat(3)) /
itertools.repeat(4)).replicate([2, 2, 3, 3])
1, 0, 0, 0
 ((nums * [2, 3, 4, 5])  [5, 6, 7, 8]) != [True, True, False, True]
True, True, True, False

The RecursiveElementwiseProxy:

 treenums = RecursiveElementwiseProxy([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
 treenums + 1
((2, 3, 4), (5, 6, 7), (8, 9, 10))
 treenums * 2
((2, 4, 6), (8, 10, 12), (14, 16, 18))
 (treenums * 2 + 1).apply(float)
((3.0, 5.0, 7.0), (9.0, 11.0, 13.0), (15.0, 17.0, 19.0))


Feedback is welcome.
-- 
http://mail.python.org/mailman/listinfo/python-announce-list

Support the Python Software Foundation:
http://www.python.org/psf/donations/


Elementwise 0.120116 -//- beta release -//- Lazily compute functions, method calls and operations on all elements of an iterable (or graph).

2012-01-16 Thread Nathan Rice
Elementwise provides helpful proxy objects which let you perform a
series of computations on every element of an iterable or graph, in a
lazy manner.

Docs: http://packages.python.org/elementwise/
GitHub: https://github.com/nathan-rice/Elementwise
Examples:

The standard ElementwiseProxy:

 nums = ElementwiseProxy([1, 2, 3, 4)
 print nums.bit_length()
1, 2, 2, 3
 nums + 1
2, 3, 4, 5
 print nums * 2
2, 4, 6, 8
 print nums == 2
False, True, False, False
 print ((nums + 1) * 2 + 3).apply(float)
7.0, 9.0, 11.0, 13.0
 print (nums.apply(float) + 0.0001).apply(round, 2)
1.0, 2.0, 3.0, 4.0
 print abs(nums - 3)
2, 1, 0, 1
 print (nums * 2 + 3) / 4
 print efoo2.undo(3)
1, 2, 3, 4
 print ((nums * 2 + 3) / 4).replicate([2, 2, 3, 3])
1, 1, 2, 2
 words = ElementwiseProxy([one, two, three, four])
 print (words +  little indians).upper().split(
).apply(reversed).apply(_.join) * 2
'INDIANS_LITTLE_ONEINDIANS_LITTLE_ONE',
'INDIANS_LITTLE_TWOINDIANS_LITTLE_TWO',
'INDIANS_LITTLE_THREEINDIANS_LITTLE_THREE',
'INDIANS_LITTLE_FOURINDIANS_LITTLE_FOUR'

The PairwiseProxy:

 nums = PairwiseProxy([1, 2, 3, 4])
 nums + [1, 2, 3, 4]
2, 4, 6, 8
 nums * [2, 2, 3, 3]
2, 4, 9, 12
 nums == [2, 2, 3, 5]
False, True, True, False
 (nums.apply(float) / itertools.count(2) +
itertools.count(1)).apply(round, args=itertools.repeat([2]))
1.5, 2.67, 3.75, 4.8
 abs(nums - [3, 2, 1, 1])
2, 0, 2, 3
 (nums * [2, 2, 1, 5] + [3, 5, 9, 0]) / [4, 1, 2, 3]
1, 9, 6, 6
 ((nums * itertools.repeat(2) + itertools.repeat(3)) /
itertools.repeat(4)).replicate([2, 2, 3, 3])
1, 0, 0, 0
 ((nums * [2, 3, 4, 5])  [5, 6, 7, 8]) != [True, True, False, True]
True, True, True, False

The RecursiveElementwiseProxy:

 treenums = RecursiveElementwiseProxy([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
 treenums + 1
((2, 3, 4), (5, 6, 7), (8, 9, 10))
 treenums * 2
((2, 4, 6), (8, 10, 12), (14, 16, 18))
 (treenums * 2 + 1).apply(float)
((3.0, 5.0, 7.0), (9.0, 11.0, 13.0), (15.0, 17.0, 19.0))


Feedback is welcome.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: [Python-ideas] Symbolic expressions (or: partials and closures from the inside out)

2012-01-13 Thread Nathan Rice
On Fri, Jan 13, 2012 at 8:45 AM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 On Thu, Jan 12, 2012 at 3:45 PM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 I'm interested in fixing both issues. I believe both issues I've had
 could be solved by having a robust symbolic object.  These objects
 would basically usable like ordinary objects, however upon any
 attribute access or other form of interaction, the object would
 basically short circuit the calling function, and return a symbolic
 object directly to the outer scope.  The symbolic object would behave
 like a generator function frozen at the point of attribute access, and
 upon send()-ing (or whatever method), it would behave exactly as if
 the values sent had been the ones passed in originally (ideally
 without consuming the generator).

 I find the way you've formalized this a bit weird. It looks like
 you're suggesting adding laziness to Python.

 If that's what you want, maybe you should try PyPy and the thunk object space:

While thunk is neat, it doesn't accomplish precisely what I'm
describing in this instance.  When a function starts to run under
thunk, the computations take place as soon as the function gets to the
object inside its scope.

What I'm after is the ability to basically create functions using only
expressions, in a generative manner.  Lambda does accomplish this, but
in an extremely clunky manner... for example:

X = lambda x: x + 1
Y = lambda y: y * 2
Z = lambda z: z % 3

(or XYZ = lambda x: (((x + 1) * 2) % 3)

If I want to perform a second step after this, I need create another
lambda, because they don't chain/aren't generative.

The thing that Elementwise does that is very appealing is that most
operations are generative, so if you have an ElementwiseProxy object
x, x2 = (((x + 1) * 2) % 3) basically does the same thing as the
above, but you can then do x3 = x2 ** 3, and so on until you are ready
to get your results.  Once you have your results, you can use the same
ElementwiseProxy again with different inputs.  It is just a function
generation technique which has some elegant properties.  Having a
native object type designed to facilitate this would let people do a
lot of interesting things, and make things like Elementwise be a lot
more consistent.  I bet you could do some really neat things by
subclassing such an object as well.

This is certainly not a common programming paradigm, but I think most
people could reap a lot of benefits from it while being oblivious to
its presence.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python lib for creating Database tables

2012-01-12 Thread Nathan Rice
On Wed, Jan 11, 2012 at 4:38 PM, Emeka emekami...@gmail.com wrote:
 Hello All,

 I just made something pretty simple that I intend to use while creating
 database tables. It is still in the basic form, and much needs to be added.
 However, I use introspection to make it a bit easier and less work on the
 user.

 I would want my code to be reviewed by this great group. I look forward to
 your feedback  and comments.
 https://github.com/janus/cheeta

Having done a LOT of work with SQL Alchemy, I would definitely
encourage you to just bite the bullet and get on board with it now.  I
routinely do very challenging things with it, and it has yet to be a
roadblock.  The learning curve can be somewhat steep but it is
absolutely worth it.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Symbolic expressions (or: partials and closures from the inside out)

2012-01-12 Thread Nathan Rice
Greetings,

I have been writing a lot of code lately that involves creating
symbolic expressions of one form or another, which are then fully
evaluated at a later time.  Examples of this include Elementwise,
where I create expressions that act on every member of an iterable
(there is a much improved new version coming soon, by the way), and a
design by contract/validation lib I'm working on (which shall remain
nameless :D) that uses symbolic expressions in the *args of the
metaclass __new__ method to generate a constraint class which
validates input using __instancecheck__.  I do most of this with
lambdas, a little hacking with closures and FunctionType(), and
chainable objects.  I am very impressed that python is this flexible,
but there are some issues with the approach that I would like to
rectify, namely:

1.  Because of the early binding behavior of most things in Python, if
I want to include isinstance(X, someclass) in a symbolic expression, I
have to wrap it in a lambda (or use .apply(), in the case of
Elementwise).  This is not a huge deal for me, but it forces me to
create wrappers for lots of functions (e.g. isinstance_(X, someclass))
and/or have users wrap every such function they want to use in a
symbolic expression.   Having to do this also bloats the code a lot;
the github version of Elementwise is over 3,000 LoC at this point
(including prodigious documentation, but still...).

2.  Python expects that certain functions, such as int(), str(), etc,
will have a specific return type.  While in general I agree with this,
it makes Elementwise somewhat inconsistent (and it will do the same to
anything else that wants to work with symbolic expressions).

I'm interested in fixing both issues. I believe both issues I've had
could be solved by having a robust symbolic object.  These objects
would basically usable like ordinary objects, however upon any
attribute access or other form of interaction, the object would
basically short circuit the calling function, and return a symbolic
object directly to the outer scope.  The symbolic object would behave
like a generator function frozen at the point of attribute access, and
upon send()-ing (or whatever method), it would behave exactly as if
the values sent had been the ones passed in originally (ideally
without consuming the generator).

I have thought about ways to approximate this behavior python
currently, and while I could hack something together using inspect to
pull relevant info from the stack, then break out using a special
exception (potentially passing a generator with state as an exception
arg), this approach strikes me as VERY brittle, implementation
dependent, ugly and difficult to work with.  Additionally, you would
need to catch the special exception somewhere in the stack, so this
trick wouldn't work on the first thing in an expression to be
evaluated.

As an aside, I'd like to solicit some feedback on the validation
syntax I've been working on.  Currently, I have code that support
things like:

X = SymbolicObject()

const = Constraints(X * 2 + 1 = 5, X % 2 != 0)
const2 = Constraints(X[-1] == h)
const3 = Constraints(X[-1].upper() == H)

 print isinstance(3, const)
True

 print isinstance(2, const)
False

 print isinstance(1, const)
False

 print isinstance(bleh, const2)
True

 print isinstance(bleh, const3)
True

Callables are supported as well, so if you wanted to do something like:

Constraints(isinstance(X.attr, someclass), somefunc(X[-2].attr, args))

You could approximate that with:

Constraints(lambda x: isinstance(x.attr, someclass), lambda x:
somefunc(x[-2].attr, args))

As I mentioned in the first paragraph, Constraints is a metaclass, so
your validations are checked using __instancecheck__.  I'm also
considering having __init__ generate mock objects (for certain
straight-forward cases, anyhow).

Thanks for your time,

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: [Python-ideas] Symbolic expressions (or: partials and closures from the inside out)

2012-01-12 Thread Nathan Rice
 I have been writing a lot of code lately that involves creating
 symbolic expressions of one form or another, which are then fully
 evaluated at a later time.  Examples of this include Elementwise,


 Python is designed for concrete, rather than symbolic computation. But the
 latter has been done.

Being able to create abstract expressions that are later realized is
super useful and neat.  You can do this decently right now, but life
would be better if you didn't have to jump through so many hoops.
Having symbolic variables override *anything* would also make lambdas
obsolete and greatly increase the potential for lazy evaluation.

 0: rewrite the text -- a bit awkward in Python.

 action = compile(read({this}).format(this=book), 'xxx', 'eval')

Yeah, that is something I'd expect to see in Perl code :)

 1. default args -- has to be done when the function is defined.

 def action(this = book): read(this)

 2. closures (nested functions) -- also requires a planned-ahead definition.

 make_read(x):
  return lambda: read(x)
 action = make_read(book)

I use this extensively in Elementwise.

 3. bound methods -- only works for classes with methods.

 Class Book:
    def read(self): pass
 action = Book(book).read

 4. partial binding of function params -- generalizes bound methods; works
 for any function and argument.

 from functools import partial
 action = partial(read, book)

 if I want to include isinstance(X, someclass) in a symbolic expression,


 Consider using partial, which can totally bind all needed args *now* for
 *later* action.

The issue isn't so much that I *can't* do things as they are more
trouble than they should be, and it makes the end user interface for
the stuff I write less elegant.

For example, if I want to work with a symbolic object, but include a
function that is not well behaved, or if I was creating a constraint
on the result of a function applied to a symbolic object, I have to
know ahead of time everything I want to do, so I can wrap the whole
expression in a lambda.  Once I wrap it, the nice generative chaining
property disappears and I'm stuck with a callable.

 from functools import partial
 t = partial(isinstance, 1, int)
 t()
 True
 f = partial(isinstance, 1, float)
 f()
 False


 I have to wrap it in a lambda


 Are you sure that partial will not work for you? Since partial is written in
 Python, you can grab and adjust the code to your needs. It amounts to adding
 default args after the fact by using a generic closure.

In some cases it would, in some cases it wouldn't.  Since I basically
never do */** expansion on wrappers, lambdas tend to be my go-to more
often.

 (or use .apply(), in the case of

 Elementwise).  This is not a huge deal for me, but it forces me to
 create wrappers for lots of functions (e.g. isinstance_(X, someclass))
 and/or have users wrap every such function they want to use in a
 symbolic expression.   Having to do this also bloats the code a lot;
 the github version of Elementwise is over 3,000 LoC at this point
 (including prodigious documentation, but still...).

 2.  Python expects that certain functions, such as int(), str(), etc,
 will have a specific return type.  While in general I agree with this,


 People expect that class constructors produce an instance of the class. It
 is surprising when one does otherwise ;-). Builtin classes like int, bool,
 and str are classes just like ones you write.

type/str/int/etc as types is definitely semi-coherent, since the
language really treats them more like functions.  They are treated
that way all over the docs as well.

From the data model page:

object.__str__(self)
Called by the str() built-in function and by the...

object.__nonzero__(self)
Called to implement truth value testing and the built-in operation bool()

object.__complex__(self)
object.__int__(self)
object.__long__(self)
object.__float__(self)
Called to implement the built-in functions complex(), int(), long(),
and float(). Should return a value of the appropriate type.

So clearly this is an area that needs some polish :)

 X = SymbolicObject()

 const = Constraints(X * 2 + 1= 5, X % 2 != 0)
 const2 = Constraints(X[-1] == h)
 const3 = Constraints(X[-1].upper() == H)


 Using a special class is a standard way to delay concrete execution.

Standard, and currently a pain in the butt, starting from the fact
that operators don't hook into __getattribute__ and getting
progressively worse from there.

 print isinstance(3, const)

 True


 A Contraints instance defines a set. 'const' is the set 'odd_ge_3'
 It would look better if you used standard syntax and do the inclusion check
 in a __contains__ method.

Used standard syntax?  Can you elaborate please?

Also, a set is one of many things a Constraints instance could
logically be represented with, as well as a discontinuous interval, a
class in the colloquial sense, etc.  The nice thing about
__instancecheck__ is that every possible constraint reduces to a type
check.  Of course, you 

Re: python philosophical question - strong vs duck typing

2012-01-03 Thread Nathan Rice
On Tue, Jan 3, 2012 at 1:13 PM, Sean Wolfe ether@gmail.com wrote:
 Hello everybody, I'm a happy pythonista newly subscribed to the group.
 How is it going?
 I have a theoretical / philosophical question regarding strong vs duck
 typing in Python. Let's say we wanted to type strongly in Python and
 were willing to compromise our code to the extent necessary, eg not
 changing variable types or casting or whatever. Let's say there was a
 methodology in Python to declare variable types.

Do you think everyone who uses the code you write wants to deal with
your type decisions?

 The question is, given this possibility, would this get us closer to
 being able to compile down to a language like C or C++?

Declaring types would enable some additional optimizations, yes.  No,
it isn't worth it.

 What I am driving at is, if we are coding in python but looking for
 more performance, what if we had an option to 1) restrict ourselves
 somewhat by using strong typing to 2) make it easy to compile or
 convert down to C++ and thereby gain more performance.

Take a look at PyPy, with RPython.  That is the most future proof,
forward thinking way of doing what you want.

 It seems to be that accepting the restrictions of strong typing might
 be worth it in certain circumstances. Basically the option to use a
 strongly-typed Python as desired. Does this get us closer to being
 able to convert to Cpp? Does the Cython project have anything to do
 with this?

Declared typing is mostly annoying.  Implicit static typing is less
annoying, but still has issues.

Cython fills the same niche as PyPy's Rpython.  Use it if you have a
lot of C code you want to call, as you will get better performance
than a wrapper like SWIG.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Py-dea: Streamline string literals now!

2011-12-28 Thread Nathan Rice
Quotes are obnoxious in the nesting sense because everyone uses quotes
for string delimiters.  By the same token, quotes are wonderful
because not only are they intuitive to programmers, but they are
intuitive in general.  Parenthesis are pretty much in the same boat...
I *HATE* them nested, but they are so intuitive that replacing them is
a non starter;  Just write code that doesn't nest parenthesis.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Py-dea: Streamline string literals now!

2011-12-28 Thread Nathan Rice
On Wed, Dec 28, 2011 at 4:42 PM, Chris Angelico ros...@gmail.com wrote:
 On Thu, Dec 29, 2011 at 8:24 AM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 Quotes are obnoxious in the nesting sense because everyone uses quotes
 for string delimiters.  By the same token, quotes are wonderful
 because not only are they intuitive to programmers, but they are
 intuitive in general.  Parenthesis are pretty much in the same boat...
 I *HATE* them nested, but they are so intuitive that replacing them is
 a non starter;  Just write code that doesn't nest parenthesis.

 Parentheses have different starting and ending delimiters and must be
 'properly nested' (ie there must be exactly-matching inner parens
 inside any given set of outer parens (note that English has similar
 rules - you can't mis-nest parentheses (at any depth) in either
 language)). You can't guarantee the same about quoted strings -
 suppose the starting delimiter were ' and the ending  (or vice
 versa), it still wouldn't deal with the issue of coming across an
 apostrophe inside a quoted string.

I think you read more into my statement than was intended.  Parens are
bad like nested quotes are bad in the sense that they made statements
difficult to read and confusing.

While it is entirely possible to parse nested strings automatically in
a probabilistic manner with nearly flawless accuracy by examining
everything between the start and end of the line, generally I feel
that people are uncomfortable with probabilistic techniques in the
realm of programming :)  Best just to make the user be explicit.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python education survey

2011-12-26 Thread Nathan Rice
On Mon, Dec 26, 2011 at 9:52 AM, Rick Johnson
rantingrickjohn...@gmail.com wrote:
 On Dec 25, 9:27 pm, Chris Angelico ros...@gmail.com wrote:
 On Mon, Dec 26, 2011 at 4:44 AM, Rick Johnson
  [...]
 Conversely, why write an IDE into IDLE when perfectly-good IDEs
 already exist? I don't use IDLE for development per se; it's for
 interactive Python execution, but not editing of source files.

 I believe the answer is two fold:

 1. Including an IDE like IDLE into the Python distro helps noobs to
 get started quickly without needing to traverse a gauntlet of unknown
 IDEs on their own. If later they find something that they feel is more
 appropriate; so be it.

 2. (and most important to me... IDLE is written in Python using the
 Tkinter GUI (which ships with python also). Therefore, the source code
 for IDLE can be a GREAT teaching resource for how to write
 professional Tkinter applications. I KNOW THE CURRENT SOURCE SUCKS!
 However, we could change that.

 So, with those points being covered, i believe IDLE is very important
 to the Python community and could be useful to more people IF we clean
 it up a bit. It's really a great little IDE with even greater
 potential. If Guido would just say something (or at least some of the
 top Pythionistas (Hettinger i am looking at you!)) this community
 might work together to fix this problem.

Not everyone who has Python installed wants to learn the language.  I
do think that a learning distro that has a lot of core tools
pre-installed, and ships with some tutorials, would be a decent idea.
Sort of like Enthought for new users :)  I don't feel IDLE is worth
salvaging though.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
Elementwise provides a proxy object for iterables which supports
chained method calls, as well as elementwise expressions and some
built-in functions.

Example:

class ExampleList(ElementwiseProxyMixin, list):
def __new__(cls, iterable):
return list.__new__(cls, iterable)
foo = ExampleList([1, 2, 3, 4])

# You could also do: efoo = ElementwiseProxy(foo)
efoo = foo.each

assert list(efoo.bit_length()) == [1, 2, 2, 3]
print bit length: , list(efoo.bit_length())
assert list(efoo + 1) == [2, 3, 4, 5]
print with addition of 1: , list(efoo + 1)
assert list(efoo * 2) == [2, 4, 6, 8]
print with multiplication by 2: , list(efoo * 2)
assert list(efoo == 2) == [False, True, False, False]
print testing equality: , efoo == 2
assert list((efoo + 1) * 2 + 3) == [7, 9, 11, 13]
print chaining addition and multiplication: , (efoo + 1) * 2 + 3

Each ElementwiseProxy also has a parent attribute so you can
backtrack in the chain as needed rather than store each intermediate
value, if you think you might need them.

There are still some issues with proper support of things like bool()
and int(), which refuse to return things that are not of the correct
type.

Get it:

PyPi: http://pypi.python.org/pypi/elementwise/0.111220
GitHub: https://github.com/nathan-rice/Elementwise

This was developed as a proof of concept for expanding the role of
element-wise syntax in python, and to that end I welcome comments.

Nathan Rice
-- 
http://mail.python.org/mailman/listinfo/python-announce-list

Support the Python Software Foundation:
http://www.python.org/psf/donations/


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
On Tue, Dec 20, 2011 at 8:37 PM, Joshua Landau
joshua.landau...@gmail.com wrote:
 On 21 December 2011 00:24, Nathan Rice nathan.alexander.r...@gmail.com
 wrote:
 efoo_res = ((efoo2.capitalize() +  little indian).split(
 ).apply(reversed) * 2).apply(_.join) # note that you could do
 reversed(...) instead, I just like to read left to right
 efoo_res.parent.parent.parent # same as ((efoo2.capitalize() + 
 little indian).split( ) in case you need to debug something and
 want to look at intermediate values

 How is any of this better than the elementwise operators (~)? People
 should be able to expect len(x) to always return a number or raise an error.
 I know it's not part of the spec, but a lot breaks without these guarantees.
 When str(x) isn't a string, all the formatting code breaks*. And when the
 other suggestion (~str(x) or str~(x) or something similar) has all the
 benifits and none of the drawbacks, why should I use this?

len() will always return a number or raise an error, just like the
type functions (bool/int/etc) return that type or raise an error.  The
interpreter guarantees that for you.

This has a couple of advantages over element-wise operators:

1. Because everything is handled in terms of generator chains, all
operations on an ElementwiseProxy are evaluated lazily.  With
element-wise operator overloading you would need to perform each
operation immediately.

2. As a result of #1, you can undo operations you perform on an
ElementwiseProxy with the parent property.

3. This still works if the person who created the class you're working
with doesn't add support for element-wise operators.  Sure, you could
monkey patch their code, but that can lead to other problems down the
line.

4. There isn't an obvious/intuitive character for element-wise
versions of operators, and fewer symbols is better than more IMHO
(see: Perl).  Also, if you use the ElementwiseProxyMixin, you can
sprinkle element-wise stuff in neatly just by using variable.each
where you would use ~ in your examples.

 Upon this implementation I take back my comment on the whole typing thing.
 Your title just really confused me.

 * You can't just make functions non-elementwise unless called through
 .apply either:
 def str(x): return x.__str__()

str is one of the special cases (along with repr, unicode, int, float,
long, bool, etc).  These can't ever be elementwise in CPython (I don't
know that this holds in other interpreters).

The idea is that you use ElementwiseProxy(x) or preferably x.each,
work with your data in an element-wise capacity as needed, then list()
or iter() back out.  I think it should be a deliberate change of
context.  Interleaving the proxy (say via x.each) in mostly scalar
expressions works, but wasn't the use case I designed it for, and in
those circumstances it doesn't really offer anything above the map
function.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
 Have you seen PyLINQ? It has a similar approach to operating on
 collections, returning a PyLINQ object after each call to facilitate
 chaining. https://github.com/kalessin/PyLINQ/blob/master/pylinq/linq.py

I hadn't seen it previously.  I am a VERY heavy user of SQL Alchemy
though, and I am sure chaining generative ClauseElements/Queries/etc,
has burned some patterns into my subconscious at this point.

 This is a personal opinion on the code, but I'd move instantiating the
 new ElementwiseProxy out of each method and into its own decorator:

    # declare this outside of the class
    def chainable(fn):
        def _(self, *args, **kwargs):
            return ElementwiseProxy(fn(self, *args, **kwargs), self)
        return _

 This way, each method that is chainable is a little more obvious
 without inspecting the code, and the method body itself is only doing
 what the method says it does:

    @chainable
    def __add__(self, other):
        return (e + other for e in object.__getattribute__(self,
 iterable))

This is a reasonable suggestion and I will play with something along
those lines soon.

 Incidentally, displaying an ElementwiseProxy instance doesn't go down
 well with iPython:

 In [1]: from elementwise import *

 In [2]: e = ElementwiseProxy(['one','two','three'])

 In [3]: e
 Out[3]: ERROR: An unexpected error occurred while tokenizing input
 The following traceback may be corrupted or invalid
 The error message is: ('EOF in multi-line statement', (6, 0))

I love IPython, but it has had known problems with iterators for
years.  A long time ago, I agonized over what I thought was a bug in
my code where itertools.count would skip numbers in IPython, but my
unit tests all passed.  Everything should work fine if you tuple() it
first.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
On Wed, Dec 21, 2011 at 11:29 AM, Robert Kern robert.k...@gmail.com wrote:
 On 12/21/11 3:15 PM, Nathan Rice wrote:

 Incidentally, displaying an ElementwiseProxy instance doesn't go down
 well with iPython:

 In [1]: from elementwise import *

 In [2]: e = ElementwiseProxy(['one','two','three'])

 In [3]: e
 Out[3]: ERROR: An unexpected error occurred while tokenizing input
 The following traceback may be corrupted or invalid
 The error message is: ('EOF in multi-line statement', (6, 0))


 I love IPython, but it has had known problems with iterators for
 years.  A long time ago, I agonized over what I thought was a bug in
 my code where itertools.count would skip numbers in IPython, but my
 unit tests all passed.  Everything should work fine if you tuple() it
 first.


 This is a different problem, actually. The problem is that the recently
 added (by me, actually) pretty-printing system tries to dispatch based on
 the type. In order to handle old-style classes, it checks for the type using
 .__class__ first. ElementProxy's __getattribute__() gets in the way here by
 returning a generator instead of the ElementProxy class.

Thanks for the heads up Robert.  Given that IPython is awesome and
people should probably be doing an '.apply(type)' in that instance
anyhow, I will corner case that on __getattribute__.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python education survey

2011-12-21 Thread Nathan Rice
+1 for IPython/%edit using the simplest editor that supports syntax
highlighting and line numbers.  I have found that
Exploring/Prototyping in the interpreter has the highest ROI of
anything I teach people.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
On Wed, Dec 21, 2011 at 12:07 PM, Paul Dubois pfdub...@gmail.com wrote:
 You're reinventing Numeric Python.

I prefer to think of it in terms of paying homage to NumPy (and
functional programming).  A big part of the motivation for this was
bringing the elegance of NumPy to other areas of python besides
numerical/scientific programming.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
 On Tue, Dec 20, 2011 at 8:37 PM, Joshua Landau
 joshua.landau...@gmail.com wrote:
  On 21 December 2011 00:24, Nathan Rice nathan.alexander.r...@gmail.com
  wrote:
  efoo_res = ((efoo2.capitalize() +  little indian).split(
  ).apply(reversed) * 2).apply(_.join) # note that you could do
  reversed(...) instead, I just like to read left to right
  efoo_res.parent.parent.parent # same as ((efoo2.capitalize() + 
  little indian).split( ) in case you need to debug something and
  want to look at intermediate values
 
  How is any of this better than the elementwise operators (~)? People
  should be able to expect len(x) to always return a number or raise an
  error.
  I know it's not part of the spec, but a lot breaks without these
  guarantees.
  When str(x) isn't a string, all the formatting code breaks*. And when
  the
  other suggestion (~str(x) or str~(x) or something similar) has all
  the
  benifits and none of the drawbacks, why should I use this?

 len() will always return a number or raise an error, just like the
 type functions (bool/int/etc) return that type or raise an error.  The
 interpreter guarantees that for you.


 The point wasn't that either way was better, but that with this
 implementation you get neither choice (len(x) vs len~(x)) or
 reliability.

If len didn't have the hard coded behavior, you would have the choice
of len(x) or len(x.each).  Since a lot of code relies on len()
returning an it, I think it is fine to accept that you have to use
x.each.apply(len).  I agree that this is a case where some kind of
elementwise designation in the syntax would be better; if there was a
∀ character on the keyboard and more people knew what it meant I would
have fewer reservations.


 The reliability point works like this: You want to elementwise a few
 functions, that before you were doing on a single item.
 BEFORE:
 item = foreignfunc1(item)
 item = foreignfunc2(item)
 item = foreignfunc3(item)

 NOW (your method):
 item = ElementwiseProxy(item)
 item = foreignfunc1(item)
 item = foreignfunc2(item)
 item = foreignfunc3(item)
 item = list(item)

well, I would say it more like:

item.each.apply(foreignfunc1).apply(foreignfunc2).apply(foreignfunc3)
# I like to read left to right, what can I say?

and I wouldn't list() it right away, since it is nice and lazy.

 You might think your method works. But what if foreignfunc is str? And you
 can't blacklist functions. You can't say everything works bar A, B and C.
 What if you get: lambda x:str(x)? You can't blacklist that. That makes the
 ElementwiseProxy version buggy and prone to unstable operation. If it's
 consistent, fine. But it's not.

I don't need to blacklist anything.  Everything that has funny
behavior like str goes through special methods on the class (that I
know of), and isn't hooked through __getattribute__, so I just handle
it somewhat normally.

 1. Because everything is handled in terms of generator chains, all
 operations on an ElementwiseProxy are evaluated lazily.  With
 element-wise operator overloading you would need to perform each
 operation immediately.


 I agree this can be a preferred advantage.But you still have to choose one.
 ~ could be lazy, or it could be eager. But in both implementations you
 have to choose. That said, you have map and imap, and so you could have
 ElemetwiseProxy and eElementwiseProxy (eager), and you can have ~ and
 i~. Remember that the syntax I'm using is just for PEP consistency. Some
 more creative people can find a syntax that works.

From my perspective the strength of operators is that they are
intuitive, since we use them constantly in other areas; I can make a
good guess about what X * Y or X + Y means in various contexts.  When
you introduce operators that don't have any well ingrained, standard
meaning, you just make the syntax cryptic.


 2. As a result of #1, you can undo operations you perform on an
 ElementwiseProxy with the parent property.


 Use case? If this is actually a wanted feature, parent could be made a
 general property of iterators.
 (x for x in foo).parent == foo
 I think that's a separate proposal that isn't intrinsic to this idea.

One quick use case:  I want to debug something big, slow and nasty; .
I set breakpoints with conditions where it seems like the issue lies
from the stack trace.  Unfortunately I missed the root cause, and the
variables that would help me debug it have been garbage collected.  I
can go through the entire process again, try to set better breakpoints
and cross my fingers, or iterate over some subset of parent operations
right there.  I think I'll take the latter.

 3. This still works if the person who created the class you're working
 with doesn't add support for element-wise operators.  Sure, you could
 monkey patch their code, but that can lead to other problems down the
 line.

As I understood it, the elementwise operators in the PEP weren't
language magic, but new hooks to special methods.  If it is language
magic, that will probably

Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
On Wed, Dec 21, 2011 at 12:53 PM, Arnaud Delobelle arno...@gmail.com wrote:

 You can already do:

 efoo2 = [one, two, three, four]
 [_.join(reversed((x.capitalize() +  little indian).split( )) * 2)
     for x in efoo2]

 Note 1: I've ignored the fact that reversed(...)*2 is erroneous
 Note 2: I wouldn't such code myself, in either form

 What's the advantage of your elementwise stuff?

Sit two theoretically identical programmers who have a decent grasp of
python, understand the basics of ElementwiseProxy and the components
of your version down side by side, and see which one can figure out
what the output should be first.  I will bet real money it is the one
working with the ElementwiseProxy code.  We have all had a lot of
practice reading inside out and backwards in the python community with
comprehensions and such, but it is in no way natural or easy.

Additionally, everything done via an ElementwiseProxy is lazy, so you
only pay for what you eat :)

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
 It doesn't seem to work correctly when both operands are Elementwise:

 numerator = ElementwiseProxy(range(5))
 denominator = ElementwiseProxy([2, 2, 3, 3, 3])
 remainder = numerator % denominator
 print remainder
 Traceback (most recent call last):
  File stdin, line 1, in module
  File elementwise.py, line 72, in __repr__
    return , .join(e.__repr__() for e in
 object.__getattribute__(self, iterable))
 TypeError: sequence item 0: expected string, ElementwiseProxy found
 list(remainder)
 []

 Cheers,
 Ian

Ian, can you clarify the expected output in that case?  My initial
guess would be that you want to do a modulo on the cartesian product
of parameters from the proxies, sort of like:

import itertools
numerator = range(5)
denominator = [2, 2, 3, 3, 3]

remainder = [n % d for (n, d) in itertools.product(numerator, denominator)]

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
On Wed, Dec 21, 2011 at 1:24 PM, Joshua Landau
joshua.landau...@gmail.com wrote:
 I was under the impression that these were meant to be interchangeable. This
 is because functions are just wrappers to non-functions, really.

 from elementwise import ElementwiseProxy as P
 (lambda x:x+[1])(P([[0],[0],[0]]))
 [0, 1], [0, 1], [0, 1]

 If we have to use .apply, we might as well use map :P.

Apply is not required, you can use functions.  I just hate reading
inside out and backwards.  compare:

func3(func2(func1(x))) # Fine if the chain is short, but quickly gets unreadable

x.apply(func1).apply(func2).apply(func3) # More verbose when working
with short chains, but infinitely clearer and more readable when
things start getting complicated, or for less experienced coders

 Note that len and dir crash.

 Here is a perfect example:
 int(P([1,2,3]))
 Traceback (most recent call last):
   File stdin, line 1, in module
 TypeError: __int__ returned non-int (type ElementwiseProxy)

It is alpha software :P  Easily fixed though.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-21 Thread Nathan Rice
On Wed, Dec 21, 2011 at 1:41 PM, Ian Kelly ian.g.ke...@gmail.com wrote:

 I expected the equivalent of:

 remainder = [n % d for (n, d) in zip(numerator, denominator)]

 which is what numpy does.

I do want to come up with a nice way to do that... However:

if numerator and denominator are plain lists that magically have an
each method...

each_numerator = numerator.each
each_denominator = denominator.each

each_numerator % each_denominator

see where I'm going with the mismatch on the semantics?  I know the
example is a bit contrived, sorry.

Expanding iterators by default might be a worth a shot though, since
passing around iterators like that is pretty rare.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: [TIP] Anyone still using Python 2.5?

2011-12-21 Thread Nathan Rice
Just because the default python version on a server is 2.4 doesn't
mean you can't install 2.7.2... If the admins that run the machine are
too lazy/stupid to install a second copy of Python let them rot.

Of course, if by some nightmare scenario you have code that can't be
upgraded for whatever reason, I'm so sorry.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-20 Thread Nathan Rice
Elementwise provides a proxy object for iterables which supports
chained method calls, as well as elementwise expressions and some
built-in functions.

Example:

class ExampleList(ElementwiseProxyMixin, list):
def __new__(cls, iterable):
return list.__new__(cls, iterable)
foo = ExampleList([1, 2, 3, 4])

# You could also do: efoo = ElementwiseProxy(foo)
efoo = foo.each

assert list(efoo.bit_length()) == [1, 2, 2, 3]
print bit length: , list(efoo.bit_length())
assert list(efoo + 1) == [2, 3, 4, 5]
print with addition of 1: , list(efoo + 1)
assert list(efoo * 2) == [2, 4, 6, 8]
print with multiplication by 2: , list(efoo * 2)
assert list(efoo == 2) == [False, True, False, False]
print testing equality: , efoo == 2
assert list((efoo + 1) * 2 + 3) == [7, 9, 11, 13]
print chaining addition and multiplication: , (efoo + 1) * 2 + 3

Each ElementwiseProxy also has a parent attribute so you can
backtrack in the chain as needed rather than store each intermediate
value, if you think you might need them.

There are still some issues with proper support of things like bool()
and int(), which refuse to return things that are not of the correct
type.

Get it:

PyPi: http://pypi.python.org/pypi/elementwise/0.111220
GitHub: https://github.com/nathan-rice/Elementwise

This was developed as a proof of concept for expanding the role of
element-wise syntax in python, and to that end I welcome comments.

Nathan Rice
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-20 Thread Nathan Rice
If you take a moment and examine the version number, you will notice
that it is a date code.  In my opinion that is far more informative
than an arbitrary number.  I use the major version number to
signify... Wait for it... Major changes :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-20 Thread Nathan Rice
On Tue, Dec 20, 2011 at 4:00 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 On Tue, 20 Dec 2011 15:45:07 -0500, Nathan Rice wrote:

 If you take a moment and examine the version number, you will notice
 that it is a date code.

 Not any date code I'm familiar with. 0.111220 doesn't look anything like
 a date to me.

 Possibly if the last release was two thousand years ago. I'd rather stick
 to actively maintained software, if it's all the same with you.

Date code != date.

 In my opinion that is far more informative than
 an arbitrary number.  I use the major version number to signify... Wait
 for it... Major changes :)

 Well, that's one opinion. Another opinion is that nobody cares what
 specific day you release a new version, and that versions 0.191231 and
 0.200101 probably aren't that big a difference.

Nobody cares about version numbers in general, except as a way to
fulfill dependencies.  By using a date code, your versions are
guaranteed to sort in release order (which is nice, say if someone was
to download your software via FTP), you can tell what release has what
ticket fixes in an issue tracker, stuff like that.  It also gives me
an easy way to be nostalgic about releases

As for the extra 20 that I exclude, if I haven't updated the major
version number by the time 2020 rolls around I deserve any trouble it
causes :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-20 Thread Nathan Rice
On Tue, Dec 20, 2011 at 7:03 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Tue, Dec 20, 2011 at 12:45 PM, Nathan Rice
 nathan.alexander.r...@gmail.com wrote:
 There are still some issues with proper support of things like bool()
 and int(), which refuse to return things that are not of the correct
 type.

 And that's a good thing.  As type conversion functions, bool(x) and
 int(x) should *always* return bools and ints respectively (or raise an
 exception), no matter what you pass in for x.

I was hoping to have the proxy be completely transparent.  I don't
disagree with your statement though.

 If I do list(efoo), where efoo is an ElementwiseProxy object, should
 I expect to get the efoo collection converted to a list, or another
 ElementwiseProxy where each element has been converted to a list?  I
 would hope the former.

Iterators are how you go from an ElementwiseProxy back to a regular
collection.  Thus list/set/etc or anything that takes an iterator will
work.

 This was developed as a proof of concept for expanding the role of
 element-wise syntax in python, and to that end I welcome comments.

 The examples you gave are all numerical in nature.  If I might
 inquire, what might I use this for that I can't already do with numpy?

efoo2 = ElementwiseProxy([one, two, three, four])

efoo_res = ((efoo2.capitalize() +  little indian).split(
).apply(reversed) * 2).apply(_.join) # note that you could do
reversed(...) instead, I just like to read left to right
efoo_res.parent.parent.parent # same as ((efoo2.capitalize() + 
little indian).split( ) in case you need to debug something and
want to look at intermediate values

The idea is to provide a syntax that lets you do very complex things
on collections in a more readable manner, without having 5 or 6 lines
of generator expressions.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Elementwise -//- first release -//- Element-wise (vectorized) function, method and operator support for iterables in python.

2011-12-20 Thread Nathan Rice
 efoo2 = ElementwiseProxy([one, two, three, four])

 efoo_res = ((efoo2.capitalize() +  little indian).split(
 ).apply(reversed) * 2).apply(_.join) # note that you could do
 reversed(...) instead, I just like to read left to right
 efoo_res.parent.parent.parent # same as ((efoo2.capitalize() + 
 little indian).split( ) in case you need to debug something and
 want to look at intermediate values

Just a quick note, I realized after I sent this that reversed returns
an iterator, so * will not work.  Otherwise everything is kosher.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Making the case for typed lists/iterators in python

2011-12-19 Thread Nathan Rice
 I think there are two aspects to your idea:
 1. collections that share a single type
 2. accessing multiple elements via a common interface

You are correct, and I now regret posing them in a coupled manner.

 Both are things that should be considered and I think both are useful in
 some contexts. The former would provide additional guarantees, for example,
 you could savely look up an attribute of the type only once while iterating
 over the sequence and use it for all elements. Also, I believe you could
 save some storage.

 The second aspect would mean that you have a single function call that
 targets multiple objects, which is syntactic sugar, but that's a good thing.
 To some extent, this looks like a C++ valarray, see e.g. [1] and [2] (note
 that I don't trust [1] and that [2] is perhaps a bit outdated), in case you
 know C++ and want to draw some inspiration from this.

 Anyway, I believe something like that would already be possible today, which
 would give people something they could actually try out instead of just
 musing about:

   class ValarrayWrapper(object):
       def __init__(self, elements):
           self._elements = elements
       def map(self, function):
           tmp = [function(x) for x in self._elements]
           return ValarrayWrapper(tmp)
       def apply(self, function)
           self._elements[:] = [function(x) for x in self._elements]

 I could even imagine this to implement generic attribute lookup by looking
 at the first element. If it contains the according attribute, return a proxy
 that allows calls to member functions or property access, depending on the
 type of the attribute.

Thank you for the references, I am always interested to see how other
languages solve problems.

I have received the code please comment repeatedly, I will have to
take some time after work today to deliver.

 I believe that typed lists that get demoted to normal lists with
 a warning on out of type operations preserve this information while
 providing complete backwards compatibility and freedom.


 I don't think that a warning helps people write correct code, a meaningful
 error does. Otherwise, with the same argument you could convert a tuple on
 the fly to a list when someone tries to change an element of it.

I do agree errors are more normative than warnings.  The problem with
an error in these circumstances is it will certainly break code
somewhere.  Perhaps a warning that becomes an error at some point in
the future would be the prudent way to go.

Thanks!

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Making the case for typed lists/iterators in python

2011-12-16 Thread Nathan Rice
I realize this has been discussed in the past, I hope that I am
presenting a slightly different take on the subject that will prove
interesting.  This is primarily motivated by my annoyance with using
comprehensions in certain circumstances.

Currently, if you want to perform successive transformations on the
elements of a list, a couple of options:

1. Successive comprehensions:

L2 = [X(e) for e in L1]
L3 = [Y(e) for e in L2]
L4 = [Z(e) for e in L3]
or
L2 = [e.X() for e in L1]

This gets the job done and gives you access to all the intermediate
values, but isn't very succinct, particularly if you are in the habit
of using informative identifiers.

2. One comprehension:

L2 = [Z(X(Y(e))) for e in L1]
or
L2 = [e.X().Y().Z() for e in L1]

This gets the job done, but doesn't give you access to all the
intermediate values, and tends to be pretty awful to read.

Having typed lists let you take preexisting string/int/etc methods
and expose them in a vectorized context and provides an easy way for
developers to support both vectors and scalars in a single function
(you could easily fix other people's functions dynamically to
support both).  Additionally, typed lists/iterators will allow
improved code analysis and optimization.  The PyPy people have already
stated that they are working on implementing different strategies for
lists composed of a single type, so clearly there is already community
movement in this direction.

Just compare the above examples to their type-aware counterparts:

L2 = X(L1)
L2 = L1.X()

L2 = Z(Y(X(L1)))
L2 = L1.X().Y().Z()

Also, this would provide a way to clean up stuff like:

\n.join(l.capitalize() for l in my_string.split(\n))

into:

my_string.split(\n).capitalize().join_this(\n)

Before anyone gets up in arms at the idea of statically typed python,
what I am suggesting here would be looser than that.  Basically, I
believe it would be a good idea in instances where it is known that a
list of single type is going to be returned, to return a list subclass
(for example, StringList, IntegerList, etc).  To avoid handcuffing
people with types, the standard list modification methods could be
hooked so that if an object of an incorrect type is placed in the
list, a warning is raised and the list converts to a generic object
list.  The only stumbling block is that you can't use __class__ to
convert from stack types to heap types in CPython.  My workaround for
this would be to have a factory that creates generic List classes,
modifying the bases to produce the correct behavior.  Then, converting
from a typed list to a generic object list would just be a matter of
removing a member from the bases for a class.  This of course
basically kills the ability to perform type specific list optimization
in CPython, but that isn't necessarily true for other implementations.
 The additional type information would be preserved for code analysis
in any case.  The case would be even simpler for generators and other
iterators, as you don't have to worry about mutation.

I'd like to hear people's thoughts on the subject.  Currently we are
throwing away useful information in many cases that could be used for
code analysis, optimization and simpler interfaces.  I believe that
typed lists that get demoted to normal lists with a warning on out
of type operations preserve this information while providing complete
backwards compatibility and freedom.

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Making the case for typed lists/iterators in python

2011-12-16 Thread Nathan Rice
Nothing stops me from implementing it, in fact it is VERY trivial to
wrap member class methods onto a list subclass, and wrap functions to
support vectorized behavior.  The problem is that as soon as you hit
anything outside your code that returns a list or iterator, everything
gets blown away unless you explicitly wrap the return value, which
entirely defeats the point.

On Fri, Dec 16, 2011 at 1:23 PM, Stefan Behnel stefan...@behnel.de wrote:
 Nathan Rice, 16.12.2011 18:48:

 I realize this has been discussed in the past, I hope that I am
 presenting a slightly different take on the subject that will prove
 interesting.  This is primarily motivated by my annoyance with using
 comprehensions in certain circumstances.

 Currently, if you want to perform successive transformations on the
 elements of a list, a couple of options:

 1. Successive comprehensions:

 L2 = [X(e) for e in L1]
 L3 = [Y(e) for e in L2]
 L4 = [Z(e) for e in L3]
 or
 L2 = [e.X() for e in L1]

 This gets the job done and gives you access to all the intermediate
 values, but isn't very succinct, particularly if you are in the habit
 of using informative identifiers.

 2. One comprehension:

 L2 = [Z(X(Y(e))) for e in L1]
 or
 L2 = [e.X().Y().Z() for e in L1]

 This gets the job done, but doesn't give you access to all the
 intermediate values, and tends to be pretty awful to read.

 Having typed lists let you take preexisting string/int/etc methods
 and expose them in a vectorized context and provides an easy way for
 developers to support both vectors and scalars in a single function
 (you could easily fix other people's functions dynamically to
 support both).  Additionally, typed lists/iterators will allow
 improved code analysis and optimization.  The PyPy people have already
 stated that they are working on implementing different strategies for
 lists composed of a single type, so clearly there is already community
 movement in this direction.

 Just compare the above examples to their type-aware counterparts:

 L2 = X(L1)
 L2 = L1.X()

 L2 = Z(Y(X(L1)))
 L2 = L1.X().Y().Z()


 What keeps you from implementing this? You don't need to change the language
 for it, just wrap the list in a class that overrides __getattr__() to return
 something that does the appropriate transformation for each element. I would
 be surprised if you needed more than a couple of lines of Python code for
 that.

 Stefan

 --
 http://mail.python.org/mailman/listinfo/python-list
-- 
http://mail.python.org/mailman/listinfo/python-list


Odd behavior of object equality/identity in the context of relative vs fully qualified imports

2011-12-15 Thread Nathan Rice
I just ran into this yesterday, and I am curious if there is a
rational behind it...

I have a class that uses a dictionary to dispatch from other classes
(k) to functions for those classes (v).  I recently ran into a bug
where the dictionary would report that a class which was clearly in
the dictionary's keys was giving a KeyError.  id() produced two
distinct values, which I found to be curious, and
issubclass/isinstance tests also failed.  When I inspected the two
classes, I found that the only difference between the two was the
__module__ variable, which in one case had a name relative to the
current module (foo), and in another case had the fully qualified name
(bar.foo).  When I went ahead and changed the import statement for the
module to import bar.foo rather than import foo, everything worked as
expected.  My first thought was that I had another foo module in an
old version of the bar package somewhere on my pythonpath;  After a
thorough search this proved not to be the case.

Has anyone else run into this?  Is this intended behavior?  If so, why?

Nathan
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Odd behavior of object equality/identity in the context of relative vs fully qualified imports

2011-12-15 Thread Nathan Rice
It would be more work than I want to go into to provide full context
(unless it is to file a bug report, if it actually is a bug).  I
verified that there are no cyclical dependency issues using snakefood,
and I doublechecked that just changing the import from full to partial
name is sufficient to reintroduce the bug.

Can I get confirmation that this is not expected behavior?  I will go
ahead and file a bug report it that is the case.

Nathan

On Thu, Dec 15, 2011 at 10:08 AM, Dave Angel d...@davea.name wrote:
 On 12/15/2011 09:34 AM, Nathan Rice wrote:

 I just ran into this yesterday, and I am curious if there is a
 rational behind it...

 I have a class that uses a dictionary to dispatch from other classes
 (k) to functions for those classes (v).  I recently ran into a bug
 where the dictionary would report that a class which was clearly in
 the dictionary's keys was giving a KeyError.  id() produced two
 distinct values, which I found to be curious, and
 issubclass/isinstance tests also failed.  When I inspected the two
 classes, I found that the only difference between the two was the
 __module__ variable, which in one case had a name relative to the
 current module (foo), and in another case had the fully qualified name
 (bar.foo).  When I went ahead and changed the import statement for the
 module to import bar.foo rather than import foo, everything worked as
 expected.  My first thought was that I had another foo module in an
 old version of the bar package somewhere on my pythonpath;  After a
 thorough search this proved not to be the case.

 Has anyone else run into this?  Is this intended behavior?  If so, why?

 Nathan

 Hard to tell with such generic information.  But I'm guessing you imported
 your script from some other module, creating a circular import sequence.
  The circular can be a problem in its own right.  But even worse, if the
 script is part of the chain is that it's loaded twice, with different names.
  And any top-level items, such as classes, will be instantiated twice as
 well.  is your script called foo.py by any chance?

 --

 DaveA

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: unittest. customizing tstloaders / discover()

2011-12-12 Thread Nathan Rice
Nose is absolutely the way to go for your testing needs.  You can put
__test__ = False in modules or classes to stop test collection.

On Mon, Dec 12, 2011 at 5:44 AM, Thomas Bach bac...@uni-mainz.de wrote:
 Gelonida N gelon...@gmail.com writes:

 Do I loose anything if using nose. or example can all unit tests / doc
 tests still be run from nose?

 AFAIK you don't loose anything by using nose – the unittests should all
 be found and doctests can be run via `--with-doctest', I never used
 doctests though.

 regards
 --
 http://mail.python.org/mailman/listinfo/python-list
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Working with databases (ODBC and ORMs) in Python 3.2

2011-11-10 Thread Nathan Rice
For now, get started in Python 2.7.  Write code with an eye to 3.x
portability, and you will be fine.  You probably won't see 3.x
overtake 2.x for at least 3-4 years, and a decent amount of stuff is
still 2.x only.  Since it sounds like you are a windows/net shop, go
ahead and use Iron Python.

SQL Alchemy is your one stop shop.  It is basically 3.x compatible,
but see my previous statement about 3.x.  I haven't used SQL Alchemy
with SQL Server but honestly, SQL Alchemy is THE showcase python
library -- I doubt you will run into any issues.  Just google
sqlalchemy sql server, I'm sure there's a blog post explaining the
specifics in detail.

Nathan

On Thu, Nov 10, 2011 at 1:56 PM, tkp...@hotmail.com tkp...@hotmail.com wrote:
 We are in the process of trying to decide between Python 2.7 and 3.2
 with a view to making a 5-10 year commitment to the right platform,
 and would appreciate some guidance on how best to connect to SQL
 databases in 3.2. ceODBC 2.01 provides an ODBC driver for Python 3.2,
 does anyone have experience using it? Also, are there any ORMs (object
 relational mapper)s that work well with 3,2?

 Thanks in advance

 Thomas Philips
 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Forking simplejson

2011-10-28 Thread Nathan Rice
Just a random note, I actually set about the task of re-implementing a
json encoder which can be subclassed, is highly extensible, and uses
(mostly) sane coding techniques (those of you who've looked at
simplejson's code will know why this is a good thing).  So far
preliminary tests show the json only subclass of the main encoder
basically tied in performance with the python implementation of
simplejson.  The C version of simplejson does turn in a performance
about 12x faster, but that's apples to oranges.  The design of the
encoder would also make a XML serializer pretty straight forward to
implement as well (not that I care about XML, *blech*).

I'm torn between just moving on to some of my other coding tasks and
putting some time into this to make it pass the simplejson/std lib
json tests.  I really do think the standard lib json encoder is bad
and I would like to see an alternative in there but I'm hesitant to
get involved.

Nathan


On Thu, Oct 27, 2011 at 11:24 AM, Amirouche Boubekki
amirouche.boube...@gmail.com wrote:


 2011/10/27 Chris Rebert c...@rebertia.com

 On Wed, Oct 26, 2011 at 2:14 AM, Amirouche Boubekki
 amirouche.boube...@gmail.com wrote:
  Héllo,
 
  I would like to fork simplejson [1] and implement serialization rules
  based
  on protocols instead of types [2], plus special cases for protocol free
  objects, that breaks compatibility. The benefit will be a better API for
  json serialization of custom classes and in the case of iterable it will
  avoid a calls like:
 
  simplejson.dumps(list(my_iterable))
 
  The serialization of custom objects is documented in the class instead
  of
  the ``default`` function of current simplejson implementation [3].
 
  The encoding algorithm works with a priority list that is summarized in
  the
  next table:
 
      +---+---+
      | Python protocol   | JSON          |
      |  or special case  |               |
      +===+===+
 snip
      | (§) unicode       | see (§)       |
 snip
  (§) if the algorithm arrives here, call unicode (with proper encoding
  rule)
  on the object and use the result as json serialization

 I would prefer a TypeError in such cases, for the same reason
 str.join() doesn't do an implicit str() on its operands:
 - Explicit is better than implicit.
 - (Likely) errors should never pass silently.
 - In the face of ambiguity, refuse the temptation to guess.

 granted it's better.


 --
 http://mail.python.org/mailman/listinfo/python-list


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Forking simplejson

2011-10-28 Thread Nathan Rice
I've found that in a lot of cases getting a patch submitted is only
half about good engineering.  The other half is politics.  I like one
of those things, I don't like the other, and I don't want to take time
out of my coding schedule to write something if in the end a reviewer
shoots down my patch for contrived reasons.  I don't know what the
python committers are like but I guess you could say I'm once bitten
twice shy.

Nathan

On Fri, Oct 28, 2011 at 4:52 PM, Terry Reedy tjre...@udel.edu wrote:
 On 10/28/2011 1:20 PM, Nathan Rice wrote:

 Just a random note, I actually set about the task of re-implementing a
 json encoder which can be subclassed, is highly extensible, and uses
 (mostly) sane coding techniques (those of you who've looked at
 simplejson's code will know why this is a good thing).  So far
 preliminary tests show the json only subclass of the main encoder
 basically tied in performance with the python implementation of
 simplejson.  The C version of simplejson does turn in a performance
 about 12x faster, but that's apples to oranges.  The design of the
 encoder would also make a XML serializer pretty straight forward to
 implement as well (not that I care about XML, *blech*).

 I'm torn between just moving on to some of my other coding tasks and
 putting some time into this to make it pass the simplejson/std lib
 json tests.  I really do think the standard lib json encoder is bad

 Python is the result of people who thought *something* was 'bad'

 and I would like to see an alternative in there

 and volunteered the effort to make something better.

 but I'm hesitant to get involved.

 As someone who is involved and tries to encourage others, I am curious why.

 --
 Terry Jan Reedy

 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Forking simplejson

2011-10-26 Thread Nathan Rice
Since this happily went off to the wrong recipient the first time...

The python json module/simpljson are badly in need of an architecture
update.  The fact that you can't override the encode method of
JSONEncoder and have it work reliably without monkey patching the pure
python encoder is a sign that something is horribly wrong.

On Wed, Oct 26, 2011 at 5:14 AM, Amirouche Boubekki
amirouche.boube...@gmail.com wrote:
 Héllo,

 I would like to fork simplejson [1] and implement serialization rules based
 on protocols instead of types [2], plus special cases for protocol free
 objects, that breaks compatibility. The benefit will be a better API for
 json serialization of custom classes and in the case of iterable it will
 avoid a calls like:

 simplejson.dumps(list(my_iterable))

 The serialization of custom objects is documented in the class instead of
 the ``default`` function of current simplejson implementation [3].

 The encoding algorithm works with a priority list that is summarized in the
 next table:

 +---+---+
 | Python protocol   | JSON  |


 |  or special case  |   |
 +===+===+
 | (ø) __json__  | see (ø)   |


 +---+---|

 | map   | object|


 +---+---+
 | iterable  | array |
 +---+---+
 | (*) float,int,long| number|


 +---+---+
 | (*) True  | true  |
 +---+---+
 | (*) False | false |


 +---+---+
 | (*) None  | null  |
 +---+---+
 | (§) unicode   | see (§)   |


 +---+---+

 (ø) if the object implements a __json__ method, the returned value is used
 as the serialization of the object


 (*) special objects which are protocol free are serialized the same way it's
 done currently in simplejson
 (§) if the algorithm arrives here, call unicode (with proper encoding rule)
 on the object and use the result as json serialization


 As soon as an object match a rule, it's serialized.

 What do you think ? Do you find this API an improvement over simplejson ? Is
 it worth to code ?

 Where are documented the different protocols implemented by Python objects ?



 Regards,

 Amirouche

 [1] https://github.com/simplejson/simplejson
 [2]
 https://github.com/simplejson/simplejson/blob/master/simplejson/encoder.py#L75
 [3]
 http://simplejson.readthedocs.org/en/latest/index.html#simplejson.JSONEncoder.default

 --
 http://mail.python.org/mailman/listinfo/python-list


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Java is killing me! (AKA: Java for Pythonheads?)

2011-08-12 Thread Nathan Rice
SNIP

public FooClass(String requiredArgument1, Long requiredArgument2, map
yourOptionalArgumentMap) {
   ...
}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Struqtural: High level database interface library

2010-07-17 Thread Nathan Rice
 Oh yes, I'd rather write lines of that rather than pages of SQL in a Python 
 string.

(not to mention, avoid some easy to fall into security flaws, not have
to worry about porting dialect specific SQL code, etc, etc).

Fixed that for you.  I can't take the credit for that part though,
that magic comes from SQL Alchemy.  All Struqtural does is let you
move data into a database easily, move data from a database to Python
easily, and simplify the creation of some common complex schemas.
-- 
http://mail.python.org/mailman/listinfo/python-list


[ANN] Struqtural: High level database interface library

2010-07-16 Thread Nathan Rice
Struqtural makes it easy to get data into a database, and easy to work
with it once it's there.  Some of the big features include:

* Automatically generate all tables and relations needed to represent
XML in a database, including one to one, one to many, many to one and
many to many relationships (JSON and YAML support is planned for a
future release), returning mapped objects.
* Automatically generate python objects for a specified table in a
database, with support for discovery of all types of relationships
(sort of like SQL Soup on 4 different kinds of steroids).
* Automatically create persisted representations of python objects in
a database, along with a persistent version of the object class.
* Automatically infer SQL data types and create table representations
for delimited text files (i.e. CSV/TSV), returning mapped objects.
* Easily generate and query EAV/vertical attribute tables.
* Easily generate and query graphs/trees/directed acyclic graphs.
* Easily manage session configuration and creation for multiple databases.
* Easily override almost all behavior with custom code or
configuration variables
* And much more...


Once you're up and running, it's SQL Alchemy under the hood, with a
few tune-ups that you are free to bypass if you don't like them.


Home page: http://www.turnkey-analytics.com/struqtural/
PyPI: http://pypi.python.org/pypi/Struqtural
Source: https://code.launchpad.net/pydatastep
Bugs: https://bugs.launchpad.net/pydatastep


To see Struqtural in action, take a look at the tutorial...
=

Struqtural has been designed to be as smart as possible. Because of
that, most common use cases are retardedly simple. Let’s take a look,
shall we?

First, let’s just examine the most basic use case:

 from struqtural.structures.structure import Structure
 from struqtural.loaders import loader
 data = [{A:True, B:1, C:1.5, D:a},
... {A:False, B:2, C:2.5, D:b},
... {A:True, B:3, C:3.5, D:c},
... {A:False, B:4, C:4.5, D:d}]
 example_structure = Structure(loader.CollectionLoader, data, B, 
 SimpleInstance)
 print primary keys:, example_structure.primary_keys
primary keys: ['B']
# Note that you could have also specified the primary key using an iterable
 print table name:, example_structure.table
table name: SimpleInstances
 print table columns:, example_structure.columns
table columns: ['SimpleInstances.A', 'SimpleInstances.C',
'SimpleInstances.B', 'SimpleInstances.D']
 for true_instance in example_structure.filter(B2):
... print true_instance
SimpleInstance(A=True, C=3.5, B=3, D=c)
SimpleInstance(A=False, C=4.5, B=4, D=d)
 for small_true_instance in example_structure.query().filter(A, C3):
... print small_true_instance
SimpleInstance(A=True, C=1.5, B=1, D=a)
Another nice feature is that Struqtural is pretty flexible about how
you pass it data:

 from struqtural.structures.structure import Structure
 from struqtural.loaders import loader
 more_data = [[T, 1, 1.0],
...  [FALSE, 2, 2.0],
...  [true, 3, 3.0],
...  [False, 4, 4.0]]
# Note that more_data is strings, which isn't uncommon in the real world
 data_headers = [A, B, E]
 categories = Structure(loader.CollectionLoader, (data_headers, more_data), 
 [B, E], Category)
# Just a quick aside to demonstrate that Struqtural gets your table names right
 print table name:, categories.table
table name: Categories
 for category in categories:
... print category
...
Category(A=True, B=1, E=1.0)
Category(A=False, B=2, E=2.0)
Category(A=True, B=3, E=3.0)
Category(A=False, B=4, E=4.0)
As you can see the strings have been handled elegantly. Type
conversion is completely controllable and extensible. A small
collection of useful type inference and conversion functions have been
included.

How about if we want to create a new structure out of multiple
previously existing ones:

 example_structure = Structure(loader.CollectionLoader, data, B, 
 SimpleInstance)
 connector = example_structure.connector
 categories = Structure(loader.CollectionLoader, (data_headers, more_data), 
 [B, E], Category, connector)
 joint_structure = Structure(loader.JoinLoader, categories, 
 example_structure)
 for instance in joint_structure:
... print instance
Category(A=True, B=1, E=1.0, C=1.5, D=a)
Category(A=False, B=2, E=2.0, C=2.5, D=b)
Category(A=True, B=3, E=3.0, C=3.5, D=c)
Category(A=False, B=4, E=4.0, C=4.5, D=d)
Note that we took advantage of some intelligence on the join we did
there, since we have identically named, identically typed columns in
the two tables. If you needed to be explicit about it you could just
as easily have called structure like so (where the dictionary key is
the column on the left table, in this case categories, and the value
is the column on the joined table):

 joined_with = (example_structure, {'A':'A', 'B':'B'})
 joint_structure = Structure(loader.JoinLoader, categories, joined_with)
Next, let’s create persisted versions of 

Re: Why doesn't python's list append() method return the list itself?

2010-07-14 Thread Nathan Rice
The better question is, do I ever use them? Thinking back over the code I've
written in the last couple of years, I would say probably two or three times
(mostly in unit tests).  I've had to code around string's sequence behavior
DOZENS of times.  Is it nifty that strings can be sliced like that?  Sure.
 In general my experience has been that the string methods (and some misc
functions in other modules) do a better job in simple cases, and regular
expressions do a better job in complex cases.  I just don't see string
slicing having utility that is irreplaceable, and it is bug-inducing in many
cases, or at the very least it can propagate programming errors way down
stream.

 Ultimately, I highly doubt it's going anywhere, so it's a moot point.  I
definitely feel that python is trading real usability for flash with
string slicing though.

On Tue, Jul 13, 2010 at 8:48 PM, Aahz a...@pythoncraft.com wrote:

 [Original not available on my swerver, responding here]

 On 7/11/10 10:03 PM, Nathan Rice wrote:
 
  Yeah, I long ago filed the in place place in the same folder as
  strings-as-sequences, all() returning True for an empty iterable and any
  returning True rather than the thing which triggered it.

 Because I love to repeat myself:

 ...string iteration isn't about treating strings as sequences of strings,
 it's about treating strings as sequences of characters.  The fact that
 characters are also strings is the reason we have problems, but characters
 are strings for other good reasons.  --Aahz
 http://mail.python.org/pipermail/python-3000/2006-April/000897.html

 Do you really want to give up Python's lovely string-slicing
 capabilities?
 --
 Aahz (a...@pythoncraft.com)   *
 http://www.pythoncraft.com/

 Normal is what cuts off your sixth finger and your tail...  --Siobhan
 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why doesn't python's list append() method return the list itself?

2010-07-12 Thread Nathan Rice
Stephen:

I'm not adverse to being able to do that, but the number of times that I've
wanted to do that is greatly outweighed by the number of times I've had to
pass a function (somestring,) or call if isinstance(foo, basestring):
... to avoid producing a bug.  The more abstract and adaptive the code you
are writing, the more annoying it gets - you end up with a rats nest of
string instance checks and strings wrapped in tuples.  Looking at my code, I
don't have a lot of use cases for string slicing or iterating character by
character.

Most of the time I use the string methods, they're faster and (IMO) clearer
- lower, index/rindex, find, etc.  One use case that I avoid is extracting
substrings, by slicing out the results of rfind.  There's a good case for
this but I feel it's brittle so I usually just jump to regular expressions
(and it could be performed equally well with a substring method).  That
doesn't mean I don't think it's useful, just that as it stands the default
language behavior is bug producing, and in my opinion people would be
equally well served with an as_list method on strings that makes the
behavior explicit.


Chris:

Let's not run around questioning people's math skills, that's actually my
area of expertise, and it's impolite besides :)

While having all([]) return True from a formal standpoint makes sense it
typically reduces people to writing if all(something) and something:,
because feeding an iterable that has been filtered in some way (and thus has
a range between 0 and n, where n is the length of the original iterable) is
an incredibly common use case.  In fact, I'm going to go out on a limb here
and say there are a lot of bugs floating around that haven't been caught
because the code author used all() under the assumption that it would be
passed a non-empty list.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why doesn't python's list append() method return the list itself?

2010-07-11 Thread Nathan Rice
Do list(reversed(list(reversed([1, 2, 3, 4])) + [[]]))

Though TBH sometimes get annoyed at this behavior myself.  There are a lot
of people who are very vocal in support of returning none, and it makes
sense in some ways.  Since reversed returns an iterator though, it makes
this code horrible and unreadable.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Why doesn't python's list append() method return the list itself?

2010-07-11 Thread Nathan Rice
Yeah, I long ago filed the in place place in the same folder as
strings-as-sequences, all() returning True for an empty iterable and any
returning True rather than the thing which triggered it.  Almost always
annoying and worked around, but that's the price you pay for the other nice
stuff :)  It just takes writing a few hundred lines of Java code for me to
shrug and forget about it.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Opinions please -- how big should a single module grow?

2010-07-09 Thread Nathan Rice
I start to look at whether some subset of functions or classes are not
referenced by other subsets of functions or classes in a module when it gets
to about 1K LoC, and if I don't find any by the time it gets to about 1500
LoC, I start to look at ways I can refactor the code in the module to be
less coupled.  This might just be anecdotal, but in all the python libraries
I've looked at (including the larger 30K+ LoC ones) the quality of code in a
module tends to be lower if the module is over around 1500 LoC.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: python app development

2010-07-03 Thread Nathan Rice
Expert Python Programming by Tarek Ziade is a fairly good book, covers a lot
of core stuff, though it doesn't really cover gui app development at all.

On Sat, Jul 3, 2010 at 1:48 PM, mo reina urban.yoga.journ...@gmail.comwrote:

 an anyone recommend a resource (book,tutorial,etc.) that focuses on
 application development in python? something similar to Practical
 Django Projects, but for stand alone applications instead of web apps
 (for now).

 i'm in a bit of a funny place, i have a decent/good grasp of python
 syntax and my logic isn't bad, but i have no clue on how to assemble
 an application, i seem to be stuck on writing scripts.

 i've looked at the source of a few projects but the flow is way over
 my head, i understand the syntax but not the logic, which is why i'm
 looking for a project-cenetered learning resource, instead of a
 reference or language-feature resource. also, it seems that a lot of
 app programming is 90% gui bindings, with very little actual code, or
 am i totally way off mark?

 i recently picked up the django practical projects book, and in a few
 days i re-wrote a website i did with django. i feel it was the book's
 project-centric approach that made this possible.
 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorators, with optional arguments

2010-07-02 Thread Nathan Rice
I like to think of decorators with arguments as decorator factory functions.
 I try and unroll them as much as possible... I have some decorators that
work like so (and please note that the wraps and returns_as_output are
separate so that I can mutate the behavior as needed, if you just wanted a
single decorator this could be condensed):

def wrap(f, wrapping_function, *args):
argspec = inspect.getargspec(f)
without_defaults = len(argspec.args) - len(argspec.defaults or [])
f._args = {}
f._varkw = []
f._arg_defaults = (None,) * without_defaults + (argspec.defaults or
tuple())
for arg in args:
if arg in argspec.args:
f._args[arg] = argspec.args.index(arg)
else:
if argspec.keywords:
f._varkw.append(arg)
return decorator.decorator(wrapping_function, f)


def return_as_output(output_f):
def func(f, *args, **kwargs):
new_args = list(args)
for (dict_name, index) in f._args.items():
if len(args)  index:
new_args[index] = output_f(args[index])
else:
d = f._arg_defaults[index]
kwargs[dict_name] = output_f(kwargs.pop(dict_name, d))
for dict_name in f._varkw:
kwargs[dict_name] = output_f(kwargs.pop(dict_name, None))
return f(*new_args, **kwargs)
return func

def iterables(*args):
'''
Decorator that guarantees that the named arguments will be iterable.
'''
as_iterables = return_as_output(iter_)
return lambda f: wrap(f, as_iterables, *args)

Just as an example... I have a family of decorators that check compliance
with abstract base classes, then try to mutate variables to provide it if
duck typing would fail.  I don't know if this helps, it is kind of
convoluted, but hopefully it gives you another example to work from.
-- 
http://mail.python.org/mailman/listinfo/python-list


  1   2   >