exceptions

M

Michael Hudson

Alexander Schmolck said:
Scott David Daniels said:
See this older thread:
<http://groups.google.com/[email protected]>

Xerox's experience (in deliberately removing the "continue from
exception" language feature) I found very instructive.

Did this language support working interactively? If so I'd be pretty surprised
to hear that no one found it useful to be able to manually fix things and
continue execution; not being able to do so is presumably my number one gripe
with python [1] -- it annoys me no end if I need to start an expensive
computation from scratch because some trivial and easily fixable problem
occured towards the end of the computation (sometimes it is possible to
salvage stuff by hand by pickling things from the appropriate post-mortem
frame, but I'd *much* prefer being able to say: foo=some_value; resume).

I'd like this too. It might be quite hard to implement
non-disruptively but I haven't thought about it too hard. Would make
an excellent project for a master's thesis, IMHO.
Footnotes:
[1] Number 2 would be the stupid try: finally: idiom which also seems to
screw up tracebacks
?

(which has occasionally led me to get rid of them completely
while debugging -- surely not a good thinge). My other gripes
are again related to python's limitations for interactive
software development -- I rather like python, but I really wish
it did that better.

What do you mean here, specifically?

I find I can do interactive development in Python most of the time (I
do wish it was more possible with PyObjC, though).

Cheers,
mwh
 
P

Peter Hansen

John said:
Peter Hansen said:
Zunbeltz Izaola wrote:
[...]
But what I'm doing is not unittest.

Pardon: I don't know why I thought this was related to testing
code.

[...]

It couldn't be that you're obsessed with unit testing, of course
<wink>.

Perhaps that's it. Another viable theory is that I spend
so much time answering questions here that sometimes I fail
to read the requests carefully enough. Doubtless there
are other possibilities.

-Peter
 
A

Alexander Schmolck

Michael Hudson said:
it annoys me no end if I need to start an expensive computation from
scratch because some trivial and easily fixable problem occured towards the
end of the computation (sometimes it is possible to salvage stuff by hand
by pickling things from the appropriate post-mortem frame, but I'd *much*
prefer being able to say: foo=some_value; resume).

I'd like this too. It might be quite hard to implement
non-disruptively but I haven't thought about it too hard. Would make
an excellent project for a master's thesis, IMHO.
Footnotes:
[1] Number 2 would be the stupid try: finally: idiom which also seems to
screw up tracebacks

?

I verified that this doesn't happen with plain python -- ipython's traceback
pretty printing code however doesn't display the right line for frames where
the exception occured within try: finally:. I've now tracked it down to the
use of inspect.getinnerframes, the line numbers here are subtly different from
what traceback.extract_tb returns (last executed expression in frame vs. where
the error occured). Since I couldn't find something readymade, I'll submit
some patch to ipython that merges the functionality of the two functions.
What do you mean here, specifically?

In no particular order:

- Interactively redefining modules or classes in a way that propogates
to other modules/preexisting instances is not exactly fun. One can often
get by by judicious use of reload, mutating classes [1] (got to be careful
to to avoid pickle failing with something along the lines of
"myModule.myClass is not of type myModule.myClass")

- no images, i.e. you can't freeze and dump the state of the whole system

- it's not particularly easy or convenient to get an useful overview of the
variables in your "workspace", e.g. memory consumption, narrowing down to
"interesting" categories etc (I know that there is of course no general way
of doing that, but compare e.g. for matlab)

- pdb is uhm, well... suboptimal (also crashes on me from time to time, not
sure why)

- global variables in python are a painful in a number of ways that does
affect interactive development

- there is not much of a culture to make modules work properly for interactive
users -- things are often not reload-safe, export all sorts of crap, not
just their interface (so that 'from foo import *' likely will hose things up
-- this is slightly aggravated 'helpful' naming conventions such as
datetime.datetime or StringIO.StringIO). Finally I think some modules,
notably GUI toolkits won't work at all.

- the available IDEs I know of are clearly far from ideal. I'd venture the
uneducated guess that ipython+emacs is amongst the best offerings for
interactive development with python and it's really not that great -- e.g.
if you use the py-execute commands source level debugging no longer will
work since the temp file created by python-mode for execution will be gone
(you can of course hang on to it, which is actually what I wound up doing
but that's very risky -- you end up inadvertenly fixing temp-files rather
than the real thing. I guess it might help if there were some easy way to
exec(file) a string, but lie about were it came from (i.e. ``exec foo,
filename="bla.py", startline=10)). In case anyone wonders that given my
misgivings about pdb I'm bothered about this -- well, one can easily set up
emacs/ipython to jump to right file and line when an error in your
interactive session occurs (and than walk up and down the traceback). This
is **very** useful, I have it activated pretty much all the time.

I find I can do interactive development in Python most of the time (I
do wish it was more possible with PyObjC, though).

I'm not saying it's impossible (I *always* run ipython in emacs, never python
in the commandline on a file, with the sole exception of regression test) but
kludging a workable interactive enviroment together needs, I think, a fair
amount of expertise and additional software (something like ipython+emacs) --
so I'd guess that most people primarily treat python as a really fast C
compiler (but I might be wrong), which is a pitty.

Also, whlilst python interactive offerings might be great when compared to
Java and C++( thankfully I haven't tried), it clearly falls far short of what
is in principle achievable and indeed has been often been achieved many, many
years ago (squeak, cmucl/sbcl+slime, matlab, j and plt scheme, to name just a
few all have things to offer for interactive work that a python user can only
dream of).


'as


Footnotes:

[1] Here are a few of the hacks I'm using, in case anyone might find them
useful -- or even better tell me about better alternatives (If someone has
cooked something reasoable for reloading modules, I'd love to hear about
it).

# to update all existing class instances

def updateClass(oldClass, newClass):
"""Destrucitively modify the ``__dict__`` and ``__bases__`` contents of
`oldClass` to be the same as of `newClass`. This will have the effect that
`oldClass` will exhibit the same behavior as `newClass`.

Won't work for classes with ``__slots__`` (which are an abomination
anyway).
"""
assert type(oldClass) is type(newClass) is type #FIXME
#FIXME redefinition of magic methods
for name in dir(oldClass):
if not name.startswith('__') or not name.endswith('__'):
delattr(oldClass, name)
for name in dir(newClass):
if not name.startswith('__') or not name.endswith('__'):
setattr(oldClass, name, newClass.__dict__[name])
# XXX should check that this is absolutely correct
oldClass.__bases__ = newClass.__bases__


## easy pickling and unpickling for interactive use

def magicGlobals(level=1):
r"""Return the globals of the *caller*'s caller (default), or `level`
callers up."""
return inspect.getouterframes(inspect.currentframe())[1+level][0].f_globals

def __saveVarsHelper(filename, varNamesStr, outOf,extension='.bpickle',**opts):
filename = os.path.expanduser(filename)
if outOf is None: outOf = magicGlobals(2)
if not varNamesStr or not isString(varNamesStr):
raise ValueError, "varNamesStr must be a string!"
varnames = varNamesStr.split()
if not splitext(filename)[1]: filename += extension
if opts.get("overwrite") == 0 and os.path.exists(filename):
raise RuntimeError("File already exists")
return filename, varnames, outOf

def saveVars(filename, varNamesStr, outOf=None, **opts):
r"""Pickle name and value of all those variables in `outOf` (default: all
global variables (as seen from the caller)) that are named in
`varNamesStr` into a file called `filename` (if no extension is given,
'.bpickle' is appended). Overwrites file without asking, unless you
specify `overwrite=0`. Load again with `loadVars`.

Thus, to save the global variables ``bar``, ``foo`` and ``baz`` in the
file 'savedVars' do::

saveVars('savedVars', 'bar foo baz')

"""
filename, varnames, outOf = __saveVarsHelper(
filename, varNamesStr, outOf, **opts)
print "pickling:\n", "\n".join(isort(varnames))
try:
f = None
f = open(filename, "wb")

cPickle.dump(dict(zip(varnames, [outOf, varnames])),
f, 1) # UGH: cPickle, unlike pickle doesn't accept bin=1
finally:
if f: f.close()

def loadVars(filename, ask=True, into=None, only=None):
r"""Load variables pickled with `saveVars`.
Parameters:

- `ask`: If `True` then don't overwrite existing variables without
asking.
- `only`: A list to limit the variables to or `None`.
- `into`: The dictionary the variables should be loaded into (defaults
to global dictionary).
"""
filename = os.path.expanduser(filename)
if into is None: into = magicGlobals()
varH = loadDict(filename)
toUnpickle = only or varH.keys()
alreadyDefined = filter(into.has_key, toUnpickle)
if alreadyDefined and ask:
print "The following vars already exist; overwrite (yes/NO)?\n",\
"\n".join(alreadyDefined)
if raw_input() != "yes":
toUnpickle = without(toUnpickle, alreadyDefined)
if not toUnpickle:
print "nothing to unpickle"
return None
print "unpickling:\n",\
"\n".join(isort(list(toUnpickle)))
for k in varH.keys():
if k not in toUnpickle:
del varH[k]
into.update(varH)
 
H

Hung Jung Lu

Alexander Schmolck said:
[1] Here are a few of the hacks I'm using, in case anyone might
find them useful -- or even better tell me about better
alternatives (If someone has cooked something reasoable
for reloading modules, I'd love to hear about it).

I have already answered to you on one previous occasion, and told you
another time in this present thread. I've used this kind of trick in
wxPython. It's good for interactively developing widgets, without
re-starting your program.

Now here is a third try. :)

(
For the first time, see:
http://groups.google.com/[email protected]
)

You can of course use a metaclass to make things a bit easier. Here is
a draft version.

#----- autoupdate.py
'''metaclass for auto-update classes'''
class __metaclass__(type):
# automatically keeps tracks of instances
def __new__(cls, class_name, bases, class_dict):
import inspect
module_name = class_dict['__module__']
instance_dict_name = '_%s__instances' % class_name
# see if there is already an older class
import sys
old_instance_dict = None
if sys.modules.has_key(module_name):
module = sys.modules[module_name]
if hasattr(module, class_name):
old_instance_dict = getattr(
getattr(module, class_name),
instance_dict_name)
# add instance list
import weakref
class_dict[instance_dict_name] = weakref.WeakValueDictionary()
# override the __init__
if class_dict.has_key('__init__'):
def new_init(self, *args, **kw):
instance_dict_name = '_%s__instances' % (
self.__class__.__name__)
getattr(self.__class__,
instance_dict_name)[id(self)] = self
self.__original_init__(*args, **kw)
class_dict['__original_init__'] = class_dict['__init__']
class_dict['__init__'] = new_init
else:
def new_init(self, *args, **kw):
instance_dict_name = '_%s__instances' % (
self.__class__.__name__)
getattr(self.__class__,
instance_dict_name)[id(self)] = self
class_dict['__init__'] = new_init
# build the class, with instance_dict
new_class = type.__new__(cls, class_name, bases, class_dict)
# copy over the instance dictionary, and update __class__
if old_instance_dict is not None:
for instance_id, instance in (
old_instance_dict.iteritems()):
getattr(new_class,
instance_dict_name)[instance_id] = instance
instance.__class__ = new_class
# return new class
return new_class

#----- Spam.py
from autoupdate import __metaclass__
class Egg:
'''Put here your class code'''
# def print(self):
# print 'Hello World!'

#----- from your Python console
import Spam
x = Spam.Egg()
# ... edit your Spam.py file and change code for Spam.Egg class,
# e.g.: add a print() method to Spam.Egg by uncommenting
# the corresponding lines. Save the file.
reload(Spam)
x.print() # prints 'Hello World!'
 
A

Alexander Schmolck

Alexander Schmolck said:
[1] Here are a few of the hacks I'm using, in case anyone might
find them useful -- or even better tell me about better
alternatives (If someone has cooked something reasoable
for reloading modules, I'd love to hear about it).

I have already answered to you on one previous occasion,

Sorry, maybe I missed it (at the time I had no access to a reliable
newsserver, so many articles didn't show up).
and told you another time in this present thread.

Yep, I've guessed correctly that your mention of weakrefs alluded to a
technique along those lines -- I haven't finished my reply to your article yet
as I sunk quite a bit of time on debugging IPython yesterday.
I've used this kind of trick in wxPython. It's good for interactively
developing widgets, without re-starting your program.

Now here is a third try. :)

Thanks for your trying again, I've only had time for a glance but this looks
quite neat -- I notice that it has evolved a bit since your original posting
:)

So far I have shied away from a metaclass based solution, as I got by with the
simple hack I posted and this hack doesn't require modifications to source
code. Another reason was that metaclasses don't combine well, but since I
haven't ended up using metaclasses much so far that might not be a problem. So
thanks for posting this, it looks quite useful.

'as
 
A

Alexander Schmolck

There are a few lessons learnt from younger programming languages,
like Io.

I'm a bit suprised we have to learn from IO given that at least on superficial
inspection, IO mostly seems to self as ruby is to smalltalk.
One lesson is that you really would like to avoid rigid statement syntax.

How do younger languages like IO make this point more forcefully than lisp,
smalltalk etc -- languages which have been around for decades?

I also suspect that the statement/expression distinction is beneficial at
least for inexperienced programmers (a declared target audience of python),
simply because it means that there are less ways to express the same thing and
nesting is limited -- in other words, I believe there is some trade off
involved.
In the example of the original topic of this thread, you cannot
intercept/override exception handling mechanism because the
try:...except:... block is not a function.

I don't think having try/except functions instead of statements provides a
sufficient solution. Apart from the fact that functions in themselves don't
provide an adequate control flow mechanism for exceptions, I don't want to
have to write my own error handling mechanisms in order to be able to deal
with some limited subset of errors raised in *my* code -- I want to be able to
deal with *all* errors in an interactive session, no matter where they were
raised and I don't want to have to rewrite (or slow down) *any* code in order
to do so.
Similar situations happen with issues regarding aspect-oriented programming.
In a language like Io, everything is a method that send message to an
object. Even If(...) statements are methods, as well as loops. The advantage
is you can intercept things at your heart's content.

It would allow some interception, but I don't think enough for my heart's
content because exceptions are completely different beasts from functions,
certainly in python (dynamically scoped ones, for starters).
In comparison, Python's exception handling is not interceptible, because
exception handling is hard-coded in syntax.

I don't think syntax is the sticking point here -- you could do some
additional, possibly useful, things if raise where, say, a method, but I can't
see how it would go anywhere near solving the problem.
It does not mean all hope is lost in Python. But it does mean that
instead of using the raise... statement in Python, you need to call a
function/method instead.

Such an approach doesn't really help much -- not only because I obviously
can't (and don't want to) rewrite all the code that might raise an exception
(which often isn't even python).
You can then intercept at that level: either by actually throwing an
exception, or by redirecting it to some user intervention funtion, or by
totally ignoring it (like using a 'pass' statement.)

Yes, but this is clearly insufficient.
Interactive programming with features like edit-and-continue still has
room to grow (most edit-and-continue features are not transactional,
that is, you cannot revert changes easily.) But in my opinion that's
an arena for prototype-based languages,

I don't see how prototype-based languages have a particular edge here --
Common lisp and Dylan, for example, support continuable conditions and can
hardly be called protype-based.
As for Python's interactive programming, I've done some experiment
before. It's not totally impossible. It's a bit uncomfortable. Python
does have module reload and weakref. When you use these tools
properly, you can achieve a high degree of non-stop programming.

I know -- I currently don't depend on weakref, but I use reload quite a lot
and I do all my programming in interactive sessions which sometimes last days.
It does not come as part of the language per-se. You need to build up some
tools yourself first.

This is one of the sticky points -- it requires some work and expertise (and
even then you are a long way off from e.g. smalltalk) and this in turn is
likely to mean that most python users won't get to experience the benefits of
interactive development (which in turn presumably means that libraries and
utilities often don't cater well for interactive use).

'as
 
H

Hung Jung Lu

Alexander Schmolck said:
How do younger languages like IO make this point more forcefully than lisp,
smalltalk etc -- languages which have been around for decades?

Sorry, the last time I used Lisp was more than 20 years ago. I might
have to look it up again. I tend to rely on people that have more
experience. Io was based on experience from lots of other languages.
with some limited subset of errors raised in *my* code -- I want to be able to
deal with *all* errors in an interactive session, no matter where they were
raised and I don't want to have to rewrite (or slow down) *any* code in order
to do so.

One typical example mentioned in AOP is precisely exception handling.
If you look at Python's internal way of handling exception (read the
manual part on extending and embedding,) errors are typically
indicated by returning a NULL value. And there are a few functions to
call to set exceptions. That is, internally, Python exceptions are
implemented going through function mechanisms, any how. Now, if these
functions could be interceptible a la AOP, there you go with "catching
*all* errors."

Sure, I understand you don't want to write any code. You just want to
be the end user and enjoy the free ride. But someone has to write it,
at some level. What you are saying is that you don't want to be this
someone. All the nice interactive, edit-and-continue features in the
various languages are not born out of magic, they were written by
someone, right? :)
It would allow some interception, but I don't think enough for my heart's
content because exceptions are completely different beasts from functions,
certainly in python (dynamically scoped ones, for starters).

Exceptions in Python are implemented as (a) returning typically a NULL
value in Python functions at the C level, (b) setting exception
informations in global static variables, often via usage of some
functions like PyErr_SetString(). And in this regard, conceptually is
not different from AOP way of exception handling. And in this regard,
perfectly interceptible via function overrides, if it were not C but
some other language a la Io.

What I am saying is, it is totally possible to design a language where
exceptions are implemented using AOP approach, where each function
could return an additional implicit value (or a NULL value as in the
case of Python.) Now, the function (or "metafunction") in your AOP
code that handles the exception raising or catching can be overridden,
if you are using something like Io where all functions can be
overriden. That is, exception handling conceptually can be done via
functions. And in Microsoft C++, this is in fact the way how
exceptions are implemented: by including an extra return value. It's
just too bad that the end user cannot override internal C/assembler
functions. (There are products to do this type of overriding.
Profilers, memory leak detectors, debuggers, etc. are good examples...
in their "instrumentation" phase, they do AOP-ish insertion of
additional code and override the normal behavior.)

In short, for many language implementations, exceptions ultimately are
based on function features. They are not "completely different
beasts". Mostly everything ultimately comes down to plain-vanilla
function calls.
Such an approach doesn't really help much -- not only because I obviously
can't (and don't want to) rewrite all the code that might raise an exception
(which often isn't even python).

I know, that's why I said "it does not mean all hope is lost". It
doesn't help much, but it helps a little.
Yes, but this is clearly insufficient.

Do you have any better idea? Short of stopping whining and starting to
re-write the Python interpreter yourself? I am sure you are totally
welcome to do so. :)
I don't see how prototype-based languages have a particular edge here --

It does. You just don't see it. Most people can't see it. And I am not
telling the details. :) Smart people know what I am talking about. And
I'll just leave it at that. Sorry, can't say anymore. :)
I know -- I currently don't depend on weakref,

Weakref is the key, at least that was my experience. I urge you to
think again on why weakrefs are necessary. Whether to use metaclass,
AOP-ish approach, or brute force class changes, it's all just icing on
the cake. Weakref was the key, in my experience.
This is one of the sticky points -- it requires some work and expertise (and
even then you are a long way off from e.g. smalltalk) and this in turn is
likely to mean that most python users won't get to experience the benefits of
interactive development (which in turn presumably means that libraries and
utilities often don't cater well for interactive use).

I know. Python has been criticized from many directions. But you
either live with the workarounds, or stop whining and do the work
inside the interpreter so others can enjoy your work. :) In my
personal case, I choose the first alternative. The advantage is that I
can keep whining. I am almost sure that this would also be your
choice. :)

regards,

Hung Jung
 
H

Hung Jung Lu

Alexander Schmolck said:
How do younger languages like IO make this point more forcefully than lisp,
smalltalk etc -- languages which have been around for decades?

Double checked with Lisp just now. And Lisp did not allow me to
redefine "if", "setq", "t", etc. In a sense, Lisp is not keywordless,
whereas Io is truly keywordless. As I said, in Io even "if" and
"while" are implemented as regular functions. In Lisp, you cannot
intercept "if", "setq", etc. In Io, everything is interceptible.
Therefore, Lisp seems not nearly as flexible as Io.

If there are tricks in Lisp to intercept "if", "setq", etc. I'd like
to know. Same if these limitations are specific to some particular
implementations of Lisp. I greatly suspect that these limitations of
Lisp are general, since Lisp does not naturally have prototype-based
scopes like onion-skins, and overriding things like "if" could more
easily create havoc.

regards,

Hung Jung
 
M

Michele Simionato

Double checked with Lisp just now. And Lisp did not allow me to
redefine "if", "setq", "t", etc. In a sense, Lisp is not keywordless,
whereas Io is truly keywordless. As I said, in Io even "if" and
"while" are implemented as regular functions. In Lisp, you cannot
intercept "if", "setq", etc.

It does. You just don't see it. Most people can't see it. And I am not
telling the details. :) Smart people know what I am talking about. And
I'll just leave it at that. Sorry, can't say anymore. :)


Michele Simionato
 
M

Michele Simionato

If there are tricks in Lisp to intercept "if", "setq", etc. I'd like
to know. Same if these limitations are specific to some particular
implementations of Lisp. I greatly suspect that these limitations of
Lisp are general, since Lisp does not naturally have prototype-based
scopes like onion-skins, and overriding things like "if" could more
easily create havoc.

regards,

Hung Jung

Sorry for the previous message, but I couldn't resist the temptation
to mock you. So you may realize how irritating certain statements can
be.

BTW, for the sake of other interested readers, I will point out that
in Lisp you can just wrap you code in a macro, and the macro can do
*everything* on the source code. Including replacing all your "if" and
"setq" with custom version of them. So practically you get what you want.
It is also explicit, since only the "if" and "setq" in the code inside the
macro will be redefined, instead of magically change the global meaning of
your basic language, which maybe is not such a good idea.


Michele Simionato
 
J

Jacek Generowicz

Double checked with Lisp just now. And Lisp did not allow me to
redefine "if", "setq", "t", etc.

I presume you mean Common Lisp. I'm pretty sure that Scheme allows you
to do this without any restriction.
If there are tricks in Lisp to intercept "if", "setq", etc.I'd like
to know.

In Common Lisp you are not allowed to rediefine any external symbols
in the COMMON-LISP package:

http://www.lisp.org/HyperSpec/Body/sec_11-1-2-1.html

and, in particular,

http://www.lisp.org/HyperSpec/Body/sec_11-1-2-1-2.html

.... so you define your own versions in another package. If you want to
know more about the issues surrounding this, then I suggest you ask on
c.l.lisp, as this is, after all, c.l.python.
Same if these limitations are specific to some particular
implementations of Lisp.

If by "Lisp" you mean "Common Lisp": no. If by "Lisp" you mean "the
Lisp language family" and by "implementation" you mean "dialect": yes.
I greatly suspect that these limitations of Lisp are general, since
Lisp does not naturally have prototype-based scopes like
onion-skins, and overriding things like "if" could more easily
create havoc.

Python does not expose pointers to the programmer. I greatly suspect
that this limitation is general to all programming languages, as this
could easily create havoc :)
 
A

Alexander Schmolck

[This requires less time than replying to your previous post, so I'll do it
first]

Therefore, Lisp seems not nearly as flexible as Io.

It would seem you are completely clueless about Lisp, so there isn't much
point discussing this statement.

If you are at all interested in programming languages as such I think you'd be
well rewarded if you at least have a good look at scheme (CL is also well
worth some study). Whether one likes scheme as a practical programming
language or not, I think it's difficult not to find it invaluable as a sort of
conceptual assembler. A great number of programming paradigms can be concisely
and illuminatingly expressed and reasoned about using just a handful of the
powerful abstractions such as, e.g. (properly tail recursive) lambda, call/cc,
cons, symbols and defmacro¹.


In addition, the majority of excellent computer science books I've come across
(and many great articles) use scheme or some other lisp and, even better, are
often freely available on the web²!


'as

¹ defmacro is not part of the standard, but generally available, and, I think,
much easier conceptualized than scheme's more complicated hygenic macro
systems.

² Just to mention the most famous:
http://mitpress.mit.edu/sicp/full-text/book/book.html
 
H

Hung Jung Lu

Sorry for the previous message, but I couldn't resist the temptation
to mock you. So you may realize how irritating certain statements can
be.

Ha. We are in newsgroups. No one pays money to get answers. Whether
someone wants to give you answers or not, it's up to them. If someone
answers, you are grateful. If no one answers, tough luck, that's life.
Move on. You can never force anyone to teach you. Irritating, why? Are
other people your slaves? Why should anyone spend their time to
educate you? That just does not work. It's a free world. On the other
hand, you are welcome to ask other people, ask as many people as you
can. I have helped hundreds of people in this newsgroup, often posting
detailed code where no one else did. So I have been more than nice and
helpful to many people, and you probably know that.

If you look at the Lisp group, you'll understand what I mean. :) By
the way, I posted there before I posted to Python. Others have
provided more complete and detailed answers. At this modern age, one
not only needs to learn, but one needs to learn how to learn.
Meta-learning, if you wish. :)

regards,

Hung Jung
 
P

Peter Hansen

[...] At this modern age, one
not only needs to learn, but one needs to learn how to learn.
Meta-learning, if you wish. :)

Thus proving the point once again...

-Peter
 
M

Michele Simionato

Jacek Generowicz said:
I'm pretty sure that Scheme allows you
to do this without any restriction.

Indeed. I knew it was possible to redefine macros but I did not expect
it was possible to redefine "built-in" "globally" so easily:

(define-macro (if c . args)
''surprise!)

(display (if #t 'true 'false)) ;=> surprise

By "globally" I mean that everything that depends of "if" will be modified:

(display (when #t 1)) ;=> surprise

which is a recipe for disasters. So I see the logic of the restriction
in Common Lisp.


Michele Simionato
 
H

Hung Jung Lu

Alexander Schmolck said:
If you are at all interested in programming languages as such
I think you'd be well rewarded if you at least have a good
look at scheme (CL is also well worth some study).

Thanks for all the references. Appreciate it.

Hung Jung
 

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
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top