Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

What's bad about Python?

Name: Anonymous 2005-12-21 8:09

Because I'm learning it, almost done through the tutorial, and it looks great.

Name: Anonymous 2011-07-20 9:52

>>80
Fuck you Shiichan.

Name: Anonymous 2011-07-20 9:55

>>81 That will teach you how to be a faggot with your quotes. You didn't even use then ``properly''!!

Name: Anonymous 2011-07-20 10:06

>>82
you didn't use "then" properly

Name: Anonymous 2011-07-20 10:34

>>82,83
*than

Name: Anonymous 2011-07-20 10:37

>>82
`' for to delimit code/identifiers/characters, ``'' for the rest.

Name: Anonymous 2011-07-20 10:52

>>85
s/for to/to/

Name: Anonymous 2011-07-20 13:24

>>73
what i read from that is "if you're language doesn't have set!, it better have delimited continuations."

Name: Anonymous 2011-07-20 14:19

>>87
Even with mutable state, they're more convenient and easier to use.

Name: Anonymous 2011-07-20 17:13

>>27
Quibble summary hydrophobia Copernicus kern!

Name: Anonymous 2011-07-20 17:20

Particle determinate monarchic off trilogy tog omelet oases necessary.

Name: Anonymous 2011-07-20 17:29

Solstice. Floppy parabolic.

Name: Anonymous 2011-07-20 17:35

Wriggle hydrofluoric selenate clip slingshot grip ninth peddle.

Name: Anonymous 2011-07-20 18:47

>>88
so how would it work in Scheme? How would it be different from call/cc?

Name: kodak_gallery_programmer !!M8okqD4wRfs+xmp 2011-07-20 19:10

Friends don't let friends use Scheme.

Name: Anonymous 2011-07-20 21:11

>>94
People who use Scheme don't have friends.

Name: Anonymous 2011-07-20 22:58

>>95
People who use C++ have friends but never use them because it's "bad practice"

Name: Anonymous 2011-07-21 3:43

>>93
call/cc captures the whole continuation, not part of it. This means that if you're writing a continuation-based green threads library using call/cc, it will not only capture the current continuation of the thread, but also the scheduler's. This is easily fixed by delimiting the captured continuation with (prompt (next-thread-cont)). Usually, call/cc is affected by prompts (like in the usual CPS implementation of single prompt shift/reset), but its interface remains horrible and useful only for early returns and few other things (IMHO).

There are four control operator (called *F* operators) that act all almost the same, but differ when you nest them (note: prompt and reset are the same thing, I'll be using prompt here)
(prompt E[(control0 k expr)]) (-F-) captures the continuation E[], and reifies it as (λ (x) E[x]), it is then passed to a procedure (λ (k) expr), reducing to: ((λ (k) expr) (λ (x) E[x])).
(prompt E[(shift0 k expr)]) (-F+) is the same thing, but the captured continuation is reified as (λ (x) (prompt E[x]), reducing to ((λ (k) expr) (λ (x) (prompt E[x])).
(prompt E[(control k expr)]) (+F-) reifies the continuation the same as control0, but it introduces a prompt at the bottom, reducing to (prompt ((λ (k) expr) (λ (x) E[x]))).
(prompt E[(shift k expr)]) (+F+), logically, does the same thing as shift0, introducing a prompt at the bottom: (prompt ((λ (k) expr) (λ (x) (prompt E[x])))).

How to implement them? For plain shift and reset, it's really simple, in CPS:
(reset E) => (λ (cc) (cc (E (λ (x) x))))
(shift E) => (λ (cc) (E (λ (retval) (λ (kk) (kk (cc retval)))) (λ (x) x)))
So, reset sets the continuation of E (a thunk) to the empty continuation λx.x, and applies its return value to the old continuation cc. shift reifies the current continuation cc into a function that takes one argument retval and a continuation kk, and applies cc to retval and its result to kk, and sets the continuation of E (an unary function) to the empty continuation, so that it will immediately return to the nearest reset.
As you can see, shift's reified continuation has a nested application in it, and CPS taught us that it is wrong and evil, so we transform that application in standard CPS: (cc x kk). kk is acting as a continuation for cc, which is a continuation, so it is a continuation to a continuation, or a metacontinuation. And as you can see, there's one in reset too! (the transformation is left as an exercise for the reader)
The shift/reset implementation in terms of call/cc and set! uses the same approach, storing the metacontinuation in some mc variable.
So, how is call/cc affected by this? The usual CPS transformation is
(call/cc E) => (λ (cc) (E (λ (x) (λ (kk) (cc x))) cc))
or, it disregards the new continuation and applies x to the old one, and doesn't change the continuation of E.
But reset resets a continuation to the empty continuation, and uses the old one as metacontinuation for it, so call/cc will only capture the partial continuation to the nearest reset.

This is cool and all, but what about control, and their 0 variants? And wouldn't various applications of reset interfere with each other? Yes, they would. The solution is prompt tags. A prompt tag is just a mark in a continuation frame, and this definition is as useful as saying that monads are monoids in the category of endofunctors, so let's make an example of how they're implemented in non-CPS:

Let's assume that the implementation uses a chain of activation records,
(prompt-at *tag* ...) marks the activation record with *tag*, (control0-at *tag* k ...) starts copying the activation records and it stops right before a record marked with *tag*, possibly raising an exception of some sort when it can't find one, and reifies it as above. The end.
control-at and shift-at stop right after the tag, shift0-at and shift-at introduce one in the captured continuation. The end. (Yes, it's that simple)

The CPS implementation of them is longer, and it's all about masturbation over metacontinuations and sequences of continuations, which is better explained here: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.72.8645&rep=rep1&type=pdf (hint: ignore the monads part if you're not interested in them)

This post is too long.

Name: Anonymous 2011-07-22 1:28

>>97
Thanks for the effort but it didn't help...

My understanding is that delimited continuation let you capture a small amount of future rather than all the future. Is that right? If so, what is that useful for?

Name: Anonymous 2011-07-22 2:11

>>97
Maybe I'm stupid or didn't pay enough attention to your post -- is each of the control/prompt and reset/shift pairs able to implement the other one?

Name: Anonymous 2011-07-22 3:10

>>51
It's object model is silly: why have both types and duck-typing?
Python has dynamic typing, how is that different than duck typing?

I also don't like auto-local scope and the "nonlocal" keyword or whatever that nonsense is. Just have lexical scope like JavaScript and Lua, fuck.
auto-local scope? isnt that just lexical scope? If Lua has lexical scope than why do you have to explicity declare variables as local to scope?

Name: Anonymous 2011-07-22 3:12

>>99
Maybe I'm stupid
Oh, no, you're not. That's a legitimate question, instead, I dind't mention that.

Yes, they can, but for some pairs it's a bit tricky:
control0 can easily implement all of them, and that's what the paper I linked basically does, using a control operator with control0-like semantics.
shift0 and control can easily implement shift.
For many years, many believed that shift couldn't implement control, but it was disproved in Shift to control, also proving that any control operator can implement each other (this is my logical conclusion, it is known that they can, but I'm not sure that this is the why)

>>98
If so, what is that useful for?
Nothing, you can do anything delimited continuations do with call/cc and set!, but if you remove set!, call/cc becomes helpless. And delimited continuations can express mutable state, or any computational effect.

So, nothing, really, if you've got mutable state, you can just drop delimited continuations, the only advantages are efficiency, readability, ease of use, theoretical beauty, and the lack of need of harmful mutable state.
Also, most of the time you don't need to capture the whole continuation.
When you see some strange nested call/cc application with set!, that code is just emulating delimited continuations.

Name: Anonymous 2011-07-22 3:15

>>100
Python has dynamic typing, how is that different than duck typing?
Duck typing is a bad rediscovery of Smalltalk-style message passing, for me.

And Python is known to always have got scoping wrong.

Name: Anonymous 2011-07-22 3:20

>>102
>And Python is known to always have got scoping wrong.
but in Perl and Lua you have to explicitly declare variables as local, that has to be wrong

Name: Anonymous 2011-07-22 3:43

>>103
Any language with at least one statement has got several things wrong.

Name: Anonymous 2011-07-22 3:56

>>104
what are you talking about? most every high level language is made up of statements and expressions

Name: Anonymous 2011-07-22 3:59

>>105
In most Lisps, there are no statements, only expressions. HIBT?

Name: Anonymous 2011-07-22 4:07

>>105
Exactly. With this new acquired knowledge, you can infer that ``most every high level language has got several things wrong''.

Name: Anonymous 2011-07-22 4:37

>>107
You're trying very hard to be funny but you're not.

Name: Anonymous 2011-07-22 4:49

>>108
It can't be helped.

Name: Anonymous 2011-07-22 6:17

>>101
So, nothing, really, if you've got mutable state, you can just drop delimited continuations, the only advantages are efficiency, readability, ease of use, theoretical beauty, and the lack of need of harmful mutable state.
While I do not particularly feel like arguing whether mutable state is indeed that harmful, I would like to know why you said delimited continuations are more efficient than mutable state. An example of a case where delimited continuations are more efficient than set!ting things around would be really nice too, if you don't mind.

I would also like to argue whether delimited continuations, when used to hack around mutable state, make the code more readable. Implementing things like generators and restartable exceptions does cause code to be a lot cleaner and more readable, but I can't see much uses past that maybe except implementing yet another version of the amb operator.

Name: Anonymous 2011-07-22 7:49

>>39
Ironically, I think they were thinking the same way when they wrote the code without comments.  Deadlines to meet (and a life). 

Never keeps me from wanting to ring their necks though..

Name: Anonymous 2011-07-22 8:59

>>110
I never said you should use them instead of set!, but instead of call/cc+set!.
The mutable state considered harmful part was more a joke than serious, what's bad about call/cc+set! are the excessive calls to call/cc, which is a costly operation in most non-CPS implementations.
Are two (or more) full stack copies less expensive than a single, partial stack copy?
You can get some comparisons and timings here: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.11.3425

I would also like to argue whether delimited continuations, when used to hack around mutable state, make the code more readable.
Well, I still have to see something more complicated than a non-local return or amb written using call/cc that doesn't look like absolute spaghetti code. Most applications of delimited continuations I've seen were pretty straightforward.
I don't have any example of how awesome delimited continuations can be at the moment, mostly because I lack imagination. Maybe lexers/parsers?

Name: Anonymous 2011-07-22 10:17

>>100
>>103

I think you do not understand a couple of things.

Pyuthon is duck types and has types. What this means is that you can call isInstance(someobject) and get its class. This means that Python objects carry around information about their "type" despite the fact that they really don't need to since it's a msg-passing language where it's just going to hash a string anyway. Inheritance is not requires, or, rather, it wouldn't be required if Python did scoping right and closures were actually easy to use. If this were the case, you could just make "classes" functions that insert closures into dictionaries. This is how both JS and Lua do things most of the time, although Lua also has metatables, which are nearly CLOS-like in power.

The reason Python does scoping wrong is simple if you actually understand lexical scope and closures and realize how undeniably useful they are (basically, if you are not Guido.) Nothign about Python is designed for using closures, not even the way the scope of loops works.

Name: Anonymous 2011-07-22 10:20

>>112
pretend Scheme has shift and reset instead of call/cc. will you implement call/cc for me?

Name: Anonymous 2011-07-22 10:29

>>114
(define (call/cc f)
 (shift k (f k)))

Name: Anonymous 2011-07-22 10:35

>>115
Disregard that,
(define (call/cc f)
 (f (lambda xs (shift _ (apply values xs)))))

Name: Anonymous 2011-07-22 11:09

>>116
Oh, fuck me. It's in the paper I linked in >>97.

Name: Anonymous 2011-07-22 11:11

>>115
>>116
>>117
thanks

Name: Anonymous 2011-07-22 11:18

>>118
That's an approximation and it's potentially wrong (I'm sure it is), the working version is in the paper.

Name: Anonymous 2011-07-22 11:56

- Everything you write will be open source. No FASLs, DLLs or EXEs. There may be some very important instances where a business wouldn't want anybody to see the internal implementation of their modules and having strict control over levels of access are necessary. Python third-party library licensing is overly complex. Licenses like MIT allow you to create derived works as long as you maintain attrubution; GNU GPL, or other 'copyleft' licenses don't allow derived works without inheriting the same license (viral licensing). To inherit the benefits of an open source culture you also inherit the complexities of the licensing hell.
- Installation mentality, Python has inherited the idea that libraries should be installed, so it infact is designed to work inside unix package management, which basically contains a fair amount of baggage (library version issues) and reduced portability. Of course it must be possible to package libraries with your application, but its not conventional and can be hard to deploy as a desktop app due to cross platform issues, language version, etc. Open Source projects generally don't care about Windows, most open source developers use Linux because "Windows sucks".
- Python (like most other scripting languages) does not require variables to be declared, as (let (x 123) ...) in Lisp or int x = 123 in C/C++. This means that Python can't even detect a trivial typo - it will produce a program, which will continue working for hours until it reaches the typo - THEN go boom and you lost all unsaved data. Local and global scopes are unintuitive. Having variables leak after a for-loop can definitely be confusing. Worse, binding of loop indices can be very confusing; e.g. "for a in list: result.append(lambda: fcn(a))" probably won't do what you think it would.
- Probably the biggest practical problem with Python is that there's no well-defined API that doesn't change. This make life easier for Guido and tough on everybody else. That's the real cause of Python's "version hell".
- Python's garbage collection uses naive reference counting, which is slow and doesn't handle circular references, meaning you can't use arbitrary graphs as your data.
- Problems with arithmetic: no Numerical Tower (or even rational numbers or complex numbers), meaning 1/2 would produce 0, instead of 0.5, leading to various hard to notice errors.
- No switch (why not??)
- Expressions in default arguments are calculated when the function is defined, not when it’s called.
- Poor UTF support and unicode string handling is somewhat awkward
- No outstanding feature, that makes the language, like the brevity of APL or macros of Lisp.
- Python's lambda doesn't allow conditionals, a side effect of Python making a distinction between expressions and statements. Nor does Python have a useful form lambda. Python's implementation of lambda is limited to a single expression, virtually crippling it.
- No tail call optimization. "I don't like reading code that was written by someone trying to use tail recursion. It's the ultimate code obfuscation." --Guido Van Rossum
- Assignments are not expressions
- self everywhere can make you feel like OO was bolted on, even though it wasn't.
- Quite quirky e.g. __init__. Triple-quoted strings seem like a syntax-decision from a David Lynch movie, and double-underscores seem appropriate in C, but not in a language that provides list comprehensions. There has to be a better way to mark certain features as internal or special than just calling it __feature__.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List