Re: CLPython (was Re: merits of Lisp vs Python)

2006-12-15 Thread metawilm
Paul Rubin wrote:
> I thought it was of some interest though I'm a little surprise by the
> choice of CL rather than Scheme as a target.

In many aspects Python is a subset of CL. In CLPython, exceptions are
Lisp conditions with a custom metaclass (strictly spoken not portable
CL), Python (meta)classes are CLOS classes, methods are implemented
using hashtables and functions and CLOS generic functions, strings and
numbers have direct equivalents, hash tables implement dicts, Python
functions are funcallable CLOS instances, tuples and lists are Lisp
lists and vectors, generators are closures. Thus a great part of
implementing CLPython consisted of connecting already existing dots. I
found that quite amazing.

> I'm still not sure about the mapping of Python strings to Lisp strings.
> What happens with the following in CLPython?
>
>   a = 'hello'
>   a[0] = 'H'   # attempt to change first letter to upper case

As CLPython mirrors Python semantics, this results in a TypeError. The
internal representation of an immutable Python string is a mutable Lisp
string, but there is no way you can actually modify it from within
CLPython.

Now in some cases modifying strings is dangerous (e.g. when stored in
an instance dict to represent an attribute), but in other cases it can
be completely safe. And modifying strings is a normal Lisp feature, so
it sounds strange to disallow it at all times. Maybe there should be a
way for the user to declare that he knows what he is doing, and does
not want the Python implementation to be "crippled" w.r.t. the host
language. Normally you start the CLPython interpreter using (repl);
maybe something like this would allow dangerous statements:

  (let ((*strict-python-semantics* nil))
(repl))

Oh, and there is actually one way to modify Python strings in the
interpreter, namely using Lisp commands:

PYTHON(12): (repl)
[CLPython -- type `:q' to quit, `:help' for help]
>>> s = "abc"
'abc'
>>>  (setf (aref _ 0) #\x)
#\x
>>> s
'xbc'
>>> type(s)
#
>>> type(s) == str
1
>>> s
'xbc'
>>>  (inspect _)
A NEW simple-string (3) "xbc" @ #x11548f6a
   0-> The character #\x [#x0078]
   1-> The character #\b [#x0062]
   2-> The character #\c [#x0063]
[1i] PYTHON(13): :ptl
>>>

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


Re: CLPython (was Re: merits of Lisp vs Python)

2006-12-16 Thread metawilm
Paul Rubin wrote:
> [EMAIL PROTECTED] writes:
> > >   a = 'hello'
> > >   a[0] = 'H'   # attempt to change first letter to upper case
> >
> > As CLPython mirrors Python semantics, this results in a TypeError. The
> > internal representation of an immutable Python string is a mutable Lisp
> > string, but there is no way you can actually modify it from within CLPython.
>
> How do you manage that?  The compiler can't check.  Is there some kind
> of special dispatch on the assignment statement instead of turning it
> into a setf?

Indeed, the assignment of subitems is dynamically dispatched, and
always goes via __setitem__ methods, as specified in the language. The
__setitem__ methods for strings and tuples raise exceptions. The ones
for lists and vectors could be translated into a simple (setf (aref ..)
..) and (setf (nth ..) ..), unless the index is actually a slice and
actually a subsequence must be replaced.

Now, the above description using __setitem__ methods is how it
apparently works, as observed from the outside. Internally there is a
generic function (setf py-subs) that does the work itself, skipping the
lookup and calling of __setitem__, if the object is a vector or dict.
(The user can call x.__setitem__ explicitly, so that method must exist
internally.)

Maybe you were thinking that CLPython, given Python code, outputs a big
pile of self-contained equivalent Lisp code that can be run
independently, and then CLPython is finished. Instead, only a small
amount of Lisp code is generated, but that code can only be run when
the CLPython environment is loaded. The generated code refers to that
environment, e.g. s[0] = 'x' is translated into a call to (setf
(py-subs ..) ..), and function (setf py-subs) is part of the CLPython
environment that must be loaded at run-time.

If you compile a Python function, the result is a (mostly) normal Lisp
function - its origin from the Python world does not really matter.
Also, all Python data structures are first-class Lisp data. Thus
CLPython objects live happily together with "normal" Lisp objects in
the same image.

And now we arrive at the most exciting part: other Lisp libraries can
be loaded in the same image, and we can create connections. Like, after
loading CLIM and defining how CLPython objects should be presented, we
should get a Python interpreter where classes are displayed graphically
and where you can inspect and modify them by mouse. Imagine that you
have interactively added a method to a class by dragging a function to
a class, then being able to right-click and select "write method",
which will write the definition of the method in the right place in the
class definition source code in your Climacs (CLIM-based Emacs) buffer.

That's the kind of features I have in mind, and the best thing is that
conceptually a lot of the work consists of connecting dots that already
out there. But as there are so many of them, a few extra pencils would
be quite welcome 

- Willem

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


Re: Nested For and While Statements

2007-09-24 Thread metawilm
On Sep 24, 10:10 pm, Zentrader <[EMAIL PROTECTED]> wrote:
> > Your for loops both use the same counting index.
>
> Since those variables are local to the for loop,

No, "for" loops don't introduce a scope. The one variable named "j" is
shared.

> for j in range( 10 ):
>   print j, "first loop"
>   for j in range( 5 ):
>  print " ", j, "2nd loop"

The reason it does work as hoped, is that the generators, including
those created by the call to "range", keep internal state to know the
next value to yield. The existence or current value of iteration
variables like "j" is completely irrelevant.

Here, the first the call to "range" creates a generator, and binds j
to the first value yielded, which is 0. Then the second range-
generator is created, iterated over using the same variable. Then the
first generator is asked for its second value (= 1), and j is bound to
that regardless its current value.

- Willem

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


Re: Nested For and While Statements

2007-09-25 Thread metawilm
On Sep 25, 7:07 pm, Zentrader <[EMAIL PROTECTED]> wrote:
> Note that in list comprehension, [x for x in (1, 2, 3)], the
> for loop allocates memory the same way, but the scope changes so that
> "x" is visible outside the for loop,

How is this different? The variable spilling of list comprehension is
the same as for regular for loops. The (#) and (##) lines below don't
print the same value of j.

>>> for j in range(3):
...   print j, "first loop" (#)
...   for j in range(3):
... print " ", j, "2nd loop"
...   print j, "first loop, again?"  (##)


- Willem

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