Zope 3.0, and why I won't use it

F

Fred Pacquier

Max M said:
I thought so :)
I'm on Windows too, and Z3 the installer seems to be in a pretty sorrow
state there.
I think it is pretty simple to get it running. But stuff like scripts
being called "mkzopeinstane" instead of "mkzopeinstane.py" and there
being references to folders that don't exists in the Windows install, so
you need to guess which ones to use instead.

Thanks for the sanity check ! I though I was being really dumb there :)
I've installed a few early Zope versions under Solaris and Linux some years
back, but had not used it since. When I saw X3 coming out with a Windows
installer, I though they'd made it really easy for once and wanted a quick
test run on my desktop. Ended up pretty nonplussed by all the stuff dumped
under site-packages and no really obvious way to launch the damn thing :)
 
M

Max M

Tim said:
If you have more details about that, the zope3-dev list would be a
better place to reveal them.

Shure. I wasn't bitching. I just tried the Window installer yesterday
evening, so I haven't really had time to comment. But I crosspost this
to z3dev (via gmane), and vill continue the discussion there.

I tried to follow the instructions in the Zope3Book at:

http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/Zope3Book/installzope3.html

Especially:

1.3.3 Creating a Zope Instance

It says:

"""
Creating a new instance is easy. Enter the Zope 3 directory and enter
the following command:

1 /bin/mkzopeinstance -u username:password -d path/to/instance
"""

First problem here is that there is no obvious "Zope 3" directory on the
windows installation.

Most of Z3 gets installed in site-packages, so I search that folder and
find a "mkzopeinstance.py" file in:

<PYTHON>\Lib\site-packages\zope\app\server

I run that, and nothing happens.

So I look on, and to my surprise i find a file called "mkzopeinstance" in:

<PYTHON>\Scripts

Which isn't exactly logical. It is in the root of my Python install, and
I didn't exactly remember that it wasn't there before ... I guess that
must be the Zope 3 folder on Windows ;-)

I look into it and check that it isn't a shell script, rename it to
"mkzopeinstance.py" and runs it. It creates an instance allright with
all the skeleton files.

Now I want to start the server and look into the <INSTANCE>/bin where
there is a "runzope" but no "runzope.bat". So I start to wonder if more
files are going to have missing extension, so that I will need to spend
the entire night appending ".py" to script in random order ;-)

So I gave up and went to bed, wanting to try again later when I had
better time.

So I guess I spend enough time to be confused, but not enough to make
constructive critiscism.


--

hilsen/regards Max M, Denmark

http://www.mxm.dk/
IT's Mad Science
 
T

Tim Peters

[Max M]
Shure. I wasn't bitching. I just tried the Window installer yesterday
evening, so I haven't really had time to comment. But I crosspost this
to z3dev (via gmane), and vill continue the discussion there.

I tried to follow the instructions in the Zope3Book at:
....

Ya, I sure agree it's not obvious what to do on Windows! There have
been detailed Windows instructions since X3 alpha 1, but subsequent
release pages didn't point to them. I see Jim updated the 3.0.0-final
release page to include them now:

<http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZopeX3300>

Start from that next time, and it should go much easier.
 
J

Jim Fulton

We didn't say that. A reporter said that. As Martijn pointed out, this
was probably a missunderstanding of our work on interfaces.
Guido has repeatedly stated that a future version of Python will include static type support. The Zope project has driven numerous past changes to Python. What's funny about this?

For the record, I'm against static typing for Python, although,
if Guido decides he wants it, I have an open mind. :)

Jim
 
A

Alex Martelli

include static type support. The Zope project has driven numerous past
changes to Python. What's funny about this?
For the record, I'm against static typing for Python, although,
if Guido decides he wants it, I have an open mind. :)

Glad to hear that. As for me, I'd love it if function arguments, only,
could bear an 'as' clause (making 'as' a keyword is long overdue):

def x(y as foo, z as bar):
<body of x>

translating into:

def x(y, z):
y = adapt(y, foo)
z = adapt(z, bar):
<body of x>

where builtin 'adapt' does protocol adaptation. On the other hand, if
the semantics of those 'as' clauses were something like:

def x(y, z):
if type(y) is not foo: raise TypeError, 'y must be foo'
if type(z) is not bar: raise TypeError, 'z must be bar'
<body of x>

then that's the day I move to Ruby, or any other language that remained
halfway sensible (if any).

In other words, if the 'as' clause (or whatever absurd syntax ends up
being adopted in its place -- judging on recent performance, probably a
two-arguments version of splat, or a nice << to complement the just as
nice 'print>>bah,humbug' syntax -- good thing I don't really care about
syntax sugar;-) ends up being a way to ease *type-checking*, then, well,
I'll evaluate that as being on a par with easing alcohol abuse. What
the syntax supports, people will do more of, and we already know that
type-checking, like alcohol abuse, is a _very_ popular although
self-destructive practice.

Protocol adaptation is the polar opposite from type checking. I'd see
syntax that supports adaptation as being on a par with easing things
that are good for you, as well as pleasant, and yet are not widely
practiced -- yoga, aerobics, many other forms of exercise, healthy
nutrition -- the language gently encouraging you to do the right thing.


Alex
 
T

Terry Reedy

(Someone):
Guido has repeatedly stated that a future version of Python will
include static type support. The Zope project has driven numerous past
changes to Python. What's funny about this?

What is sad to me is that the reporter seems to have gotten it backwards.
To me, the point of interfaces and adapters is to support and extend the
notion of generic programming, not undermine it. After reading the
Programmers' Introduction referenced in a previous post, Zope 3 seems to
have made contributions in this regard that may well trickle into standard
Python.

Terry J. Reedy
 
J

Josiah Carlson

include static type support. The Zope project has driven numerous past
changes to Python. What's funny about this?

Glad to hear that. As for me, I'd love it if function arguments, only,
could bear an 'as' clause (making 'as' a keyword is long overdue):

def x(y as foo, z as bar):
<body of x>

translating into:

def x(y, z):
y = adapt(y, foo)
z = adapt(z, bar):
<body of x>

where builtin 'adapt' does protocol adaptation. On the other hand, if
the semantics of those 'as' clauses were something like:

def x(y, z):
if type(y) is not foo: raise TypeError, 'y must be foo'
if type(z) is not bar: raise TypeError, 'z must be bar'
<body of x>

then that's the day I move to Ruby, or any other language that remained
halfway sensible (if any).

In other words, if the 'as' clause (or whatever absurd syntax ends up
being adopted in its place -- judging on recent performance, probably a
two-arguments version of splat, or a nice << to complement the just as
nice 'print>>bah,humbug' syntax -- good thing I don't really care about
syntax sugar;-) ends up being a way to ease *type-checking*, then, well,
I'll evaluate that as being on a par with easing alcohol abuse. What
the syntax supports, people will do more of, and we already know that
type-checking, like alcohol abuse, is a _very_ popular although
self-destructive practice.

Protocol adaptation is the polar opposite from type checking. I'd see
syntax that supports adaptation as being on a par with easing things
that are good for you, as well as pleasant, and yet are not widely
practiced -- yoga, aerobics, many other forms of exercise, healthy
nutrition -- the language gently encouraging you to do the right thing.

Decorators to the rescue?

def d_adapt(t):
def f(a):
return adapt(a, t)
return f

def d_adaptors(*adaptors):
#some work necessary to make kwargs work
def f(fcn):
def f(*args):
return fcn(*[i(j) for i,j in zip(adaptors, args)])
return f
return f

@d_adaptors(d_adapt(foo), d_adapt(bar))
def x(y, z):
<body of x>


- Josiah
 
A

Andrea Griffini

@d_adaptors(d_adapt(foo), d_adapt(bar))
def x(y, z):
<body of x>

First listing type coercions and then listing the variables
on which they're applied ? IMO this is worse than pre-ansi C.

I'd prefer explicit calls at the begin of the body rather
than that... it would be way more readable.

Andrea
 
A

Alex Martelli

Josiah Carlson said:
def d_adapt(t):
def f(a):
return adapt(a, t)
return f

def d_adaptors(*adaptors):
#some work necessary to make kwargs work
def f(fcn):
def f(*args):
return fcn(*[i(j) for i,j in zip(adaptors, args)])
return f
return f

@d_adaptors(d_adapt(foo), d_adapt(bar))
def x(y, z):
<body of x>

Can do with less work:

def d_adap(*types):
def f(fcn):
def f(*args):
return fcn(*(adapt(i, j)
for i, j in izip(types, args)))
f.__name__ = fcn.__name__
return f
return f

@ d_adap(foo, bar)
def x(y, z):
<body of x>

but the point is whether, if and when 'optional static typing' _syntax_
gets it, it will have this semantics or that of inserting a lot of
typechecks... people can do typecheks or adaptation now, and neither
will go away -- but which, if either, should syntax facilitate? That,
as I see it, is key.


Alex
 
J

Josiah Carlson

Andrea Griffini said:
First listing type coercions and then listing the variables
on which they're applied ? IMO this is worse than pre-ansi C.

Since I didn't learn C (1999) until after the ANSI standard, if you
would care to explain that'd be great. Is it perhaps something like (I
can't remember the syntax I've seen, as I've only seen it a few times)...

int main(argc, argv)
(int argc, char[] argv)
{ /*body/* }

I'd prefer explicit calls at the begin of the body rather
than that... it would be way more readable.

So the trick is to ask yourself what is available now. Decorators are
available now (or in a month or two when 2.4 comes out), and are about
as close to what you want as is going to happen before Py3k, and even
then, it may have syntax you don't want.

Me, I'll just stick my type checking and coercions (if either are
necessary) in the function body where I always have.

- Josiah
 
J

Josiah Carlson

(e-mail address removed) (Alex Martelli) wrote:

[snip your better implementation]
but the point is whether, if and when 'optional static typing' _syntax_
gets it, it will have this semantics or that of inserting a lot of
typechecks... people can do typecheks or adaptation now, and neither
will go away -- but which, if either, should syntax facilitate? That,
as I see it, is key.

I guess it all depends.
"In the face of ambiguity, refuse the temptation to guess."
"Explicit is better than implicit."

With the requisite zens quoted, I'd say that there should be an explicit
way to do both, because guessing which one (but not both) is necessarily
the wrong thing to do.

With that said, type-based dispatch, checking and adaptation are
provided by decorators, which are explicit. They are not a syntax
per-se, but they will get the job done in the mean time (if placing type
checking and adaptations in the function body is not sufficient).

- Josiah
 
V

Ville Vainio

Alex> where builtin 'adapt' does protocol adaptation. On the
Alex> other hand, if the semantics of those 'as' clauses were
Alex> something like:

Alex> def x(y, z):
Alex> if type(y) is not foo: raise TypeError, 'y must be foo'
Alex> if type(z) is not bar: raise TypeError, 'z must be bar'
Alex> <body of x>

Alex> then that's the day I move to Ruby, or any other language
Alex> that remained halfway sensible (if any).

Even if it allowed portions of the code to be statically compiled to
reach "native" performance? Or if it allowed resolving ambiguous
situations in type inference? Type declarations would of course be
optional, and they could be a big win esp. for non-cpython
implementations of the language. Beats reverting to C#/whatever for
situations where you want good JITtability. In CPython "adaptation"
might be the way to go, of course, but that would still enable the
same code to run on different variants of Python.

Alex> syntax sugar;-) ends up being a way to ease *type-checking*,
Alex> then, well, I'll evaluate that as being on a par with easing
Alex> alcohol abuse. What

I don't think people have been too keen to get static type checking
into the language anyway. It might be an option in pychecker, but that
should be enough. Dynamic type checking, well, that's an obvious net
loss over adaptation.
 
A

Alex Martelli

Josiah Carlson said:
I guess it all depends.
"In the face of ambiguity, refuse the temptation to guess."
"Explicit is better than implicit."

With the requisite zens quoted, I'd say that there should be an explicit
way to do both, because guessing which one (but not both) is necessarily
the wrong thing to do.

Since the actual need for type-checking is extremely rare, I contend it
should not _at all_ be a candidate for a syntax to facilitate it. Since
the actual need for adaptation is much wider, I contend it's the one
obvious choice for the "nice syntax" if any.
With that said, type-based dispatch, checking and adaptation are
provided by decorators, which are explicit. They are not a syntax
per-se, but they will get the job done in the mean time (if placing type
checking and adaptations in the function body is not sufficient).

Type checking is ugly, so it's quite fitting that it be implemented in
ugly ways -- by boilerplate or user-coded splats. Adaptation is
beautiful, and beautiful is better than ugly (see, I can quote the zen
of Python too...), so it should have nice syntax (<var> 'as' <itf>).

Type-based dispatch is a little bit of a mess to implement with
decorators, IMHO. Consider the hypothetical code...:

class A(object):
@ dispatch(int)
def foo(x): ...

@ dispatch(float)
def foo(x): ...

class B(object):
@ dispatch(int)
def foo(x): ...

@ dispatch(str)
def foo(x): ...

Sure, dispatch can be a H**2OF which returns a dispatching-foo and
stashes somewhere a (say) foo__int, foo__float or whatever, but the
problem is, _WHAT_ 'somewhere'. dispatch isn't told what class body
it's being called from, so it can't easily stash stuff in the obvious
place, the class dictionary being built. Attributes of the
dispatching-foo don't seem good, because of the problem of getting at
the right previously-returned dispatching-foo object on successive calls
of dispatch from within the same class body (but not from separate class
bodies). Maybe some peek-into-the-stack black magic or custom
metaclass can help, but it does seem a little bit of a mess, unless I'm
overlooking something obvious. If the implementation is hard to
explain, it's a bad idea...


Alex
 
A

Alex Martelli

Ville Vainio said:
Alex> where builtin 'adapt' does protocol adaptation. On the
Alex> other hand, if the semantics of those 'as' clauses were
Alex> something like:

Alex> def x(y, z):
Alex> if type(y) is not foo: raise TypeError, 'y must be foo'
Alex> if type(z) is not bar: raise TypeError, 'z must be bar'
Alex> <body of x>

Alex> then that's the day I move to Ruby, or any other language
Alex> that remained halfway sensible (if any).

Even if it allowed portions of the code to be statically compiled to
reach "native" performance? Or if it allowed resolving ambiguous
situations in type inference? Type declarations would of course be
optional, and they could be a big win esp. for non-cpython

My prediction is that, once 'of course optional' type declaration gets
in, it will become the mandated approach in most new-to-Python shops, by
fallacious analogy with (say) VB and Perl's "optional" type declaration,
and by dint of managers' general liking for putting silly unjustified
restriction on professionals to hamper their productivity. That is
going to be a huge cost. What will it buy in exchange?

If typenames in a type declaration context can be statically resolved at
compile-time, then so can just about every other use of names, right?
After all, if the compiler can statically resolve what object 'foo' is
bound to in a clause 'x as bar.foo', it means it must somehow have
inferred that some 'class foo' statement will inevitably get executed
before then in module bar, or whatever other attribute assignment
produces that binding of name 'foo' within name 'bar'.

And of course the 'foo' type will generally be built up in another
module, so we're talking about a compiler that examines other modules in
order to be able to compile this one. Whole-program compilation with
compile-time inferred name-object bindings would be such a huge and
total revolution wrt today's Python that very little would stay the
same. OK, then, if that's the revolution that's in Python's future,
let's see it come _first_ -- there would be huge wins without requiring
any source code changes _IF_ name-to-object resolution could be
uniformly done at compile-time rather than at runtime, even across
modules. Though I've never seen any example of whole-program
compilation and optimization done right, in practice (with compile time
NOT growing faster than O(N) and soon becoming untenable for large
programs), I do know that _in theory_ it's feasible -- I'd just be
astonished if it was shown that Python, never having been designed for
it, "just happens" to be the right language to have it finally occur.

implementations of the language. Beats reverting to C#/whatever for
situations where you want good JITtability. In CPython "adaptation"
might be the way to go, of course, but that would still enable the
same code to run on different variants of Python.

If adaptation was a dialect-specific thing, it would hamper the ability
to move large frameworks and applications across dialects.

I don't see "falling back" to a lower-level language where you need one
as a disaster. Doesn't have to be _AS_ low-level as C# or Java or C, of
course; I think pyrex does a great job of showing how a restricted
Python dialect/variant which, among other things, includes optional
declarations, can make your life much easier. I don't see why there
couldn't be pyrex# or Jirex versions, or even languages inspired from
Python but farther from it than Pyrex is, such as Bobo.

Alex> syntax sugar;-) ends up being a way to ease *type-checking*,
Alex> then, well, I'll evaluate that as being on a par with easing
Alex> alcohol abuse. What

I don't think people have been too keen to get static type checking
into the language anyway. It might be an option in pychecker, but that
should be enough. Dynamic type checking, well, that's an obvious net
loss over adaptation.

I agree pychecker or the like might well have options to check on
everything under the sun -- no problem. For reasons that escape me,
shop rules such as "all programs will pass lint with this and that
option" seem to never stick. Shop rules such as "-Wall -pedantic on all
compilations and NEVER any commit of code with warnings" (a good idea,
actually) or "all VB programs must have option explicit" (maybe better
than nothing, given VB's typing mess, if you have to do VB) or "all perl
runs will always have -w" (probably a good idea), etc, etc, _are_
observed, in practice, to stick. And there are good rules for Python,
too, of course, ones that promote productivity, from 'we do not ever use
"exec"' to similar edicts against 'from x import *'. As long as control
freaks don't get an effective way to destroy Python's greatest strength,
namely signature-based polymorphism, I'm happy...


Alex
 
F

Fred Pacquier

Tim Peters said:
Ya, I sure agree it's not obvious what to do on Windows! There have
been detailed Windows instructions since X3 alpha 1, but subsequent
release pages didn't point to them. I see Jim updated the 3.0.0-final
release page to include them now:

<http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZopeX3
<300>

Huh, thanks for that pointer ! Sure makes a lot more sense that way, and a
lot less to guess at, even for a developer release :)

If only the lower part of that page had figured in a prominent
WINDOWS_INSTALL_README.TXT or some such in the Windows installer, there'd
been much less bitchin' here :)
 
B

Bryan

alex,

you've mentioned several times the concept of adapting parameters to a method. but i'm not able to understand your few
examples. can you go more into depth (and with simpler examples) on this topic?

thanks,

bryan
 
J

Jeremy Jones

Bryan said:
alex,

you've mentioned several times the concept of adapting parameters to a
method. but i'm not able to understand your few examples. can you go
more into depth (and with simpler examples) on this topic?

thanks,

bryan

Bryan,

Thanks for asking this. You aren't alone in wanting to know more.

Jeremy
 
V

Ville Vainio

Alex> My prediction is that, once 'of course optional' type
Alex> declaration gets in, it will become the mandated approach in
Alex> most new-to-Python shops, by

I don't think this has happened with Lisp either, so it doesn't
necessarily happen with Python. Python has a strong culture of dynamic
typing, it wouldn't disappear overnight. It's a matter of education,
mostly.

Alex> And of course the 'foo' type will generally be built up in
Alex> another module, so we're talking about a compiler that
Alex> examines other modules in order to be able to compile this
Alex> one. Whole-program compilation with compile-time inferred
Alex> name-object bindings would be such a huge and total
Alex> revolution wrt today's Python that very little would stay
Alex> the same. OK, then, if that's the revolution that's in
Alex> Python's future, let's see it come _first_ -- there would be
Alex> huge wins without requiring any source code changes _IF_
Alex> name-to-object resolution could be uniformly done at
Alex> compile-time rather than at runtime, even across modules.

Ok, let's :).

I figure the concept of "frozen" modules would need to be introduced:

python -f a.py b.py c.py

=> a.pyf b.pyf c.pyf

It would now be impossible to introduce new names in the module global
area. All the classes introduced in the module would be immutable,
i.e. no rebinding of methods. Attributes would work through
__slots__. Imports would need to only address other frozen modules
(which would apply to most of the standard library at some point :).

Granted, it's not the laissez-faire Python we all know and love, but
many problems could be solved by using that kind of programming style
alone. Several more "sophisticated" frameworks could be able to use a
lean, "frozen" subset of classes and functions.

Alex> I don't see "falling back" to a lower-level language where
Alex> you need one as a disaster. Doesn't have to be _AS_
Alex> low-level as C# or Java or C, of course; I think pyrex does
Alex> a great job of showing how a restricted Python
Alex> dialect/variant which, among other things, includes optional
Alex> declarations, can make your life much easier. I don't see

I admit that the concept of frozen modules is somewhere b/w an
additional lower level language and an extension to Python as an
idea.

Alex> couldn't be pyrex# or Jirex versions, or even languages
Alex> inspired from Python but farther from it than Pyrex is, such
Alex> as Bobo.

I assume you mean Boo here.
 
T

Tim Peters

[Tim Peters]<http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/ZopeX3300>

[Fred Pacquier]
Huh, thanks for that pointer ! Sure makes a lot more sense that way, and a
lot less to guess at, even for a developer release :)

Yup -- it's essential.
If only the lower part of that page had figured in a prominent
WINDOWS_INSTALL_README.TXT or some such in the Windows
installer, there'd been much less bitchin' here :)

Ah, but where would you put this file? In a *tarball* distribution,
it's easy: you stick README_FILES_WITH_SCREAMING_NAMES in the root of
the distribution, and then they're easy to find.

But this is a Windows *installer*, and every file it installs is
"hiding" under some subdirectory of your pre-existing Windows Python
installation. Where could the X3 Windows installer put
WINDOWS_INSTALL_README.TXT where a new user is likely to find it?

I don't believe such a place exists. It would be anti-social to
clutter the root of the Python installation with package README files,
and I doubt most users would think to look there anyway. And that's
the "most obvious" place I can dream up.

Doing something other than that (for example, maybe popping up a
README file in Notepad at the end of installation) would require
changes to distutils, since X3's Windows installer is built by
distutils. The point of that isn't that changing distutils makes it
impossible, the point is that since distutils *today* doesn't have
such abilities, no distutils-built installer built today (whether X3's
or any other Python project's) can do such things.
 
C

Carlos Ribeiro

Bryan,

Thanks for asking this. You aren't alone in wanting to know more.

Jeremy

Well, my name is not Alex, and my answer will probably fall short of a
comprehensive definition :) But let's see if I can help here...

Adaptation is the act of taking one object and making it conform to a
given protocol (or interface). Adaptation is the key to make dynamic
code that takes parameters from arbitrary types work in a safe, well
behaved way.

The basic concept underlying adaptation is the "protocol", also called
"interface" in some implementations. For all purposes of this
discussion, and for simplicity reasons, we can safely assume that
protocols and interfaces are equivalent.

A protocol is a set of primitives that is supported by a given object.
For example: the iterator protocol defines the following primitives:
__iter__ and next() (as documented in
http://docs.python.org/lib/typeiter.html). Any object from any class
that implement these methods, regardless of its ancestors, is said to
support the iterator protocol.

Any object that supports the iterator protocol can be used whenever an
iterable is acceptable. This includes for loops and list
comprehensions. The biggest advantage of adaptation comes when one
realize how flexible this design is, specially when compared with
old-style type checking. In a old-style type checking environment,
parameters to a given routine must conform to the declared type of the
arguments. For iterators, it would mean that only objects descending
from some abstract class (let's say, "Iterable") would be accepted.
Now, even with multiple inheritance, this design is severely limited.

Now, back to Python world. In many situations, there is no need for
adaptation; the object itself supports the protocol, and can be
supplied directly. But there are situations when the object itself
can't be immediately used; it has to be adapted, or prepared, to
support the protocol. Another situation is when an object is passed to
a routine that *doesn't* support the required protocol; this is an
error, that can be catched by the adapt() framework in a superficially
similar but fundamentally different approach from type checking (and
that's whats Alex has been pointing out).

The adapt protocol (as presented on PEP246 -
http://www.python.org/peps/pep-0246.html) defines a very flexible
framework to adapt one object to a protocol. The result of the
adaptation (if possible) is an object that is guaranteed to support
the protocol. So, using adapt(), we can write code like this:

def myfunc(obj):
for item in adapt(obj, Iterable):
...

Finally, one may be wondering, is there any situation when an object
needs to be "adapted"? Why don't just check for the availability of
the interface? There are many reasons to use the adapt framework. The
protocol checking is one of the reasons -- it allows errors to be
catched much earlier, and at a better location. Another possible
reason is that complex objects may support several protocols, and
there may be name clashes between some of the methods. One such
situation is when an object support different *versions* of the same
protocol. All versions have the same method names, but semantics may
differ slightly. The adapt() call can build a new object with the
correct method names and signatures, for each protocol or version
supported by the object. Finally, the adaptation method can optionally
build an opaque "proxy" object, that hides details of the original
methods signature, and it's thus safer to pass around.

Well, that's a broad overview of the subject. There is a lot of stuff
to learn, and using adaptation properly is something that takes some
time. Hope it helps.

--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: (e-mail address removed)
mail: (e-mail address removed)
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,211
Messages
2,571,092
Members
47,693
Latest member
david4523

Latest Threads

Top