Re: What is Expressiveness in a Computer Language
"Marshall" <[EMAIL PROTECTED]> writes: > Pascal Costanza wrote: >> Marshall wrote: >> > Pascal Costanza wrote: >> >> Consider a simple expression like 'a + b': In a dynamically typed >> >> language, all I need to have in mind is that the program will attempt to >> >> add two numbers. In a statically typed language, I additionally need to >> >> know that there must a guarantee that a and b will always hold numbers. >> > >> > I still don't really see the difference. >> > >> > I would not expect that the dynamic programmer will be >> > thinking that this code will have two numbers most of the >> > time but sometimes not, and fail. I would expect that in both >> > static and dynamic, the thought is that that code is adding >> > two numbers, with the difference being the static context >> > gives one a proof that this is so. >> >> There is a third option: it may be that at the point where I am writing >> this code, I simply don't bother yet whether a and b will always be >> numbers. In case something other than numbers pop up, I can then >> make a decision how to proceed from there. > > Ouch; I have a really hard time understanding this. > > I can't see how you'd call + on a and b if you think they might > not be numbers. If they could be something other than numbers, > and you're treating them as if they are, is that sort of like > doing a case analysis and only filling in one of the cases? > If so, wouldn't you want to record that fact somehow? But suppose + were polymorphic and someone (dynamically) added a method on + to handle strings? If the type error were that a and b happened to be strings, there would be at least two courses of action in the development of the program: limit a and b so that they are never strings at this point, or define a method on + to add correct functionality for the + operator. Note that I use the term "correct", because the correctness of the subprogram (including any added methods on +) depends both on the correctness of usage within the language, and also correctness of extensibilities allowed by the language for the purpose of satisfying goals of the program. In the many cases where the eventual goals of the program are not known at the beginning of the design, this extensibility is a good thing to have. Note that the above paragraph explicitly leaves out Common Lisp, because + is not extensible in CL. CL does, however, allow for methods to be defined on functions not already defined by the standard, so the argument could still apply to some generic function named my-+, or even on my-package::+ where the CL defined + operator is shadowed. -- Duane Rettig[EMAIL PROTECTED]Franz Inc. http://www.franz.com/ 555 12th St., Suite 1450 http://www.555citycenter.com/ Oakland, Ca. 94607Phone: (510) 452-2000; Fax: (510) 452-0182 -- http://mail.python.org/mailman/listinfo/python-list
Re: What is Expressiveness in a Computer Language
Darren New <[EMAIL PROTECTED]> writes: > Marshall wrote: >> I can't see how you'd call + on a and b if you think they might >> not be numbers. > > Now substitute "<" for "+" and see if you can make the same argument. :-) Sure. Properly extended to handle strings, "abc" < "def" might return true. -- Duane Rettig[EMAIL PROTECTED]Franz Inc. http://www.franz.com/ 555 12th St., Suite 1450 http://www.555citycenter.com/ Oakland, Ca. 94607Phone: (510) 452-2000; Fax: (510) 452-0182 -- http://mail.python.org/mailman/listinfo/python-list
Re: What is Expressiveness in a Computer Language
Ketil Malde <[EMAIL PROTECTED]> writes: > "Marshall" <[EMAIL PROTECTED]> writes: > >> There are also what I call "packaging" issues, such as >> being able to run partly-wrong programs on purpose so >> that one would have the opportunity to do runtime analysis >> without having to, say, implement parts of some interface >> that one isn't interested in testing yet. These could also >> be solved in a statically typed language. (Although >> historically it hasn't been done that way.) > > I keep hearing this, but I guess I fail to understand it. How > "partly-wrong" do you require the program to be? This conclusion is false. To be "wrong", whether partly or fully, a program needs to specifically not conform to the requirements that the programmer gives it. You are assuming that only a completed program can be right. Let me give a counterexample: Consider this part of a CL program: CL-USER(1): (defun foo (x) (declare (optimize speed (safety 0) (debug 0)) (fixnum x) ) (bar (the fixnum (1+ x FOO CL-USER(2): This is of course not a complete program, because the function BAR is not yet defined. If I try to run it, it will of course get an error. But does that require then that I call this a "partly wrong" program? No, of course not; it is not a program; it is a function, and for my purposes it is completely correct (I've debugged it already :-) So what can we do with an incomplete program? Nothing? Well, no. Of course, we can't run it (or can we?). But even before talking about running the program, we can at least do some reasoning about it: 1. It seems to have some static type declarations (in a dynamic langiuage? oh my :-). 2. The 1+ operation limits the kinds of operations that would be acceptable, even in the absence of static type declarations. 3. The declarations can be ignored by the CL implementation, so #2 might indeed come into play. I ensured that the declarations would be "trusted" in Allegro CL, by declaring high speed and low safety. 4. I can compile this function. Note that I get a warning about the incompleteness of the program: CL-USER(2): (compile 'foo) Warning: While compiling these undefined functions were referenced: BAR. FOO NIL NIL CL-USER(3): 5. I can disassemble the function. Note that it is a complete function, despite the fact that BAR is undefined: CL-USER(3): (disassemble 'foo) ;; disassembly of # ;; formals: X ;; constant vector: 0: BAR ;; code start: #x406f07ec: 0: 83 c0 04 addl eax,$4 3: 8b 5e 12 movl ebx,[esi+18] ; BAR 6: b1 01 movbcl,$1 8: ff e7 jmp *edi CL-USER(4): 6. I can _even_ run the program! Yes, I get an error: CL-USER(4): (foo 10) Error: attempt to call `BAR' which is an undefined function. [condition type: UNDEFINED-FUNCTION] Restart actions (select using :continue): 0: Try calling BAR again. 1: Return a value instead of calling BAR. 2: Try calling a function other than BAR. 3: Setf the symbol-function of BAR and call it again. 4: Return to Top Level (an "abort" restart). 5: Abort entirely from this (lisp) process. [1] CL-USER(5): 7. But note first that I have many options, including retrying the call to BAR. What was this call to BAR? I can reason about that as well, by getting a backtrace: [1] CL-USER(5): :zoom Evaluation stack: (ERROR #) ->(BAR 11) [... EXCL::%EVAL ] (EVAL (FOO 10)) (TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP) (TPL:START-INTERACTIVE-TOP-LEVEL # # ...) [1] CL-USER(6): 8. If I then define BAR, with or without compiling it, and then take that option to retry the call: [1] CL-USER(6): (defun bar (x) (1- x)) BAR [1] CL-USER(7): :cont 10 CL-USER(8): Hmm, I was able to complete the program dynamically? Who ever heard of doing that? :-) > During development, I frequently sprinkle my (Haskell) program with > 'undefined' and 'error "implement later"' - which then lets me run the > implemented parts until execution hits one of the 'undefined's. Why do it manually? And what do you do when you've hit the undefined? Start the program over? > The "cost" of static typing for running an incomplete program is thus > simply that I have to name entities I refer to. I'd argue that this > is good practice anyway, since it's easy to see what remains to be > done. Good practice, yes, but why not have the language help you to practice it? -- Duane Rettig[EMAIL PROTECTED]Franz Inc. http://www.franz.com/ 555 12th St., Suite 1450 http://www.555citycenter.com/ Oakland, Ca. 94607Phone: (510) 452-2000; Fax: (510) 452-0182 -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
"Paddy" <[EMAIL PROTECTED]> writes: > Mark Tarver wrote: > >> How do you compare Python to Lisp? What specific advantages do you >> think that one has over the other? >> >> Note I'm not a Python person and I have no axes to grind here. This is >> just a question for my general education. >> >> Mark > I've never programmed in Lisp but I have programmed in Cadence Skill a > Lisp inspired language with infix notation as an option. I found Skill > to be a very powerful language. At the time I new only AWK, C, Pascal, > Forth, Postcript, Assembler and Basic. Skill was superior and I came > to love it. Remember; Lisp is a program-language programming language. Sometimes, one programs in Lisp without really knowing it: http://www.franz.com/careers/jobs/outside/cadence03.21.06.lhtml -- Duane Rettig[EMAIL PROTECTED]Franz Inc. http://www.franz.com/ 555 12th St., Suite 1450 http://www.555citycenter.com/ Oakland, Ca. 94607Phone: (510) 452-2000; Fax: (510) 452-0182 -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp-like macros in Python?
sturlamolden <[EMAIL PROTECTED]> writes: > Hello > > The Lisp crowd always brags about their magical macros. I was > wondering if it is possible to emulate some of the functionality in > Python using a function decorator that evals Python code in the stack > frame of the caller. The macro would then return a Python expression > as a string. Granted, I know more Python than Lisp, so it may not work > exactly as you expect. > > Any comments and improvements are appreciated. > > Regards, > Sturla Molden I don't know python, but check out http://www.cl-user.net/asp/libs/clpython -- Duane Rettig[EMAIL PROTECTED]Franz Inc. http://www.franz.com/ 555 12th St., Suite 1450 http://www.555citycenter.com/ Oakland, Ca. 94607Phone: (510) 452-2000; Fax: (510) 452-0182 -- http://mail.python.org/mailman/listinfo/python-list
Re: A critic of Guido's blog on Python's lambda
Alexander Schmolck <[EMAIL PROTECTED]> writes: > Ken Tilton <[EMAIL PROTECTED]> writes: > >> In Common Lisp we would have: >> >> (defvar *x*) ;; makes it special >> (setf *x* 1) >> (print *x*) ;;-> 1 >> (let ((*x* 2)) >>(print *x*)) ;; -> 2 >> (print *x*) ;; -> 1 > > You seem to think that conflating special variable binding and lexical > variable binding is a feature and not a bug. What's your rationale? A bug is a non-conformance to spec. Kenny's statement was specifically about Common Lisp, which has a spec. Now, what was your rationale for it _being_ a bug? -- Duane Rettig[EMAIL PROTECTED]Franz Inc. http://www.franz.com/ 555 12th St., Suite 1450 http://www.555citycenter.com/ Oakland, Ca. 94607Phone: (510) 452-2000; Fax: (510) 452-0182 -- http://mail.python.org/mailman/listinfo/python-list
Re: A critic of Guido's blog on Python's lambda
Alexander Schmolck <[EMAIL PROTECTED]> writes: > Duane Rettig <[EMAIL PROTECTED]> writes: > >> Alexander Schmolck <[EMAIL PROTECTED]> writes: >> >> > Ken Tilton <[EMAIL PROTECTED]> writes: >> > >> >> In Common Lisp we would have: >> >> >> >> (defvar *x*) ;; makes it special >> >> (setf *x* 1) >> >> (print *x*) ;;-> 1 >> >> (let ((*x* 2)) >> >>(print *x*)) ;; -> 2 >> >> (print *x*) ;; -> 1 >> > >> > You seem to think that conflating special variable binding and lexical >> > variable binding is a feature and not a bug. What's your rationale? >> >> A bug is a non-conformance to spec. > > There is a world beyond specs, you know. If copies of allegro CL accidently > sent out death-threats to the US president on a weekly basis, because someone > at franz accidently or purposefully left in some pranky debugging code the > fact that this behaviour would likely neither violate the ansi spec nor any > other specs that ACL officially purports to adhere to wouldn't make it any > less of a bug (or help to pacify your customers). It wouldn't be a bug in Allegro CL, because it would never happen in an Allegro CL that hasn't been enhanced with some kind of program. And although that program itself could have a bug whereby such a threat were accidental, I would tend not to call it accidental, I would tend to call it expicit, and thus not a bug but an intended consequence of such explicit programming. My reason for responding to you in the first place was due to your poor use of the often misused term "bug". You could have used many other words or phrases to describe the situation, and I would have left any of those alone. For example: >> Kenny's statement was specifically about Common Lisp > > No Kenny's statement was about contrasting the way something is done in python > and the way something is done in common lisp (with the implication that the > latter is preferable). Of course the way something is done in common lisp is > almost tautologically in closer agreement with the ansi common lisp spec than > the way it is done in python, so agreement with the clhs is not a useful > criterion when talking about design features and misfeatures when contrasting > languages. > > I thought it would have been pretty obvious that I was talking about language > design features and language design misfeatures (Indeed the infamously post > hoc, "It's a feature, not a bug" I was obviously alluding too doesn't make > much sense in a world were everything is tightly specified, because in it > nothing is post-hoc). Whether it is preferable is a matter of opinion, and whether Kenny meant it to infer preferability (I suspect so) or not has nothing to due with whether it is a bug. Instead, you should call it a "design misfeature", which would set the stage for a more cogent argumentation on the point, rather than on the hyperbole. By the way, if you do call it a design misfeature, I would be arguing against you, but that is another conversation. >>, which has a spec. > > Bah -- so does fortran. But scheme also has operational semantics. > >> Now, what was your rationale for it _being_ a bug? > > I just don't think the way special variable binding (or variable binding in > general[1]) is handled in common lisp is particularly well designed or > elegant. Then call it "misdesigned" or "inelegant". > Special variables and lexical variables have different semantics and using > convention and abusing[2] the declaration mechanism to differentiate between > special and lexical variables doesn't strike me as a great idea. Then call it a "bad idea". > I can certainly think of problems that can occur because of it (E.g. ignoring > or messing up a special declaration somewhere; setf on a non-declared variable > anyone? There are also inconsistent conventions for naming (local) special > variables within the community (I've seen %x%, *x* and x)). Then call it "not fully standardized or normative". > Thus I don't see having to use syntactically different binding and assignment > forms for special and lexical variables as inherently inferior. Then call it "inherently inferior". > But I might be wrong -- which is why was asking for the rationale of Kenny's > preference. But you _didn't_ ask him what rationale he had for his _preference_, you asked him his rationale for considering it not a _bug_. > I'd be even more interested in what you think (seriously; should > you consider it a design feature (for reasons oth
Re: A critic of Guido's blog on Python's lambda
Alexander Schmolck <[EMAIL PROTECTED]> writes: > I think that in most contexts lexical transparency is desirable so that > deviations from lexical transparency ought to be well motivated. I also > believe that a construct that is usually used to establish a lexically > transparent binding shouldn't be equally used for dynamic bindings so that it > isn't syntactically obvious what's going on. I've already provided some > reasons why CL's design wrt. binding special and lexical variables seems bad > to me. I don't think these reasons were terribly forceful but as I'm not aware > of any strong motivation why the current behaviour would be useful I'm > currently considering it a minor wart. > > To make things more concrete: What would be the downside of, instead of doing > something like: > > (let ((*x* ...)) [(declare (special *x*))] ...) ; where [X] denotes maybe X Let's start with this. You seem to be saying that the above construct is inferior to the alternatives you are about to suggest. Why? And since you are adding an optional form, let's break it down into its separate situations: 1. (let ((*x* ...)) (declare (special *x*)) ...) Here there is no question about the specialness of *x*; it is textually obvious what the binding is - that it is not a lexical binding but a special binding. 2. (let ((*x* ...)) ...) [where there is no special declaration for *x* within the form] Here, the issue is that it is not obvious that *x* is special (in this case, it would have to already be a dynamic variable (what we internally call "globally special"), because a special declaration within a lexical context does not affect inner bindings. Perhaps this form is the one you are really having trouble with. > doing any of the below: > > a) using a different construct e.g. (fluid-let ((*x* ...)) ...) for binding >special variables Unless you also _remove_ the #2 case above, this seems no diferent than writing a macro for the #1 case, above. > b) having to use *...* (or some other syntax) for special variables In fact, the spec does suggest precisely this (see http://www.franz.com/support/documentation/8.0/ansicl/dictentr/defparam.htm, in the Notes section), and to the extent that programmers obey the suggestion, the textual prompting is present in the name. > c) using (let ((q (special *x*) (,a ,b ,@c)) (values 1 2 '(3 4 5 6))) > (list q ((lambda () (incf *x*))) a b c)) ; => (1 3 3 4 (5 6)) > > (It's getting late, but hopefully this makes some vague sense) Well, sort of; this seems simply like a sometimes-fluid-let, whose syntax could easily be established by a macro (with destructurings whose form is (special X) could be specially [sic] treated. Now if in the above example you would have trouble with (a) and/or (c) based on the absence of a "lexical" declaration (i.e. one that would undo the effect of a globally special declaration), thus guaranteeing that a fluid-let or a "sometimes-fluid-let" would work, you should know that while I was working on the Environments Access module I theorized and demonstrated that such a declaration could be easily done within a conforming Common Lisp. I leave you with that demonstration here (though it really is only for demonstration purposes only; I don't necessarily propose that CL should add a lexical declaration to the language): [This only works on Allegro CL 8.0]: CL-USER(1): (defvar pie pi) PIE CL-USER(2): (compile (defun circ (rad) (* pie rad rad))) CIRC NIL NIL CL-USER(3): (circ 10) 314.1592653589793d0 CL-USER(4): (compile (defun foo (x) (let ((pie 22/7)) (circ x FOO NIL NIL CL-USER(5): (foo 10) 2200/7 CL-USER(6): (float *) 314.2857 CL-USER(7): (sys:define-declaration sys::lexical (&rest vars) nil :variable (lambda (declaration env) (declare (ignore env)) (let* ((spec '(lexical t)) (res (mapcar #'(lambda (x) (cons x spec)) (cdr declaration (values :variable res SYSTEM::LEXICAL CL-USER(8): (compile (defun foo (x) (let ((pie 22/7)) (declare (sys::lexical pie)) (circ x ; While compiling FOO: Warning: Variable PIE is never used. FOO T NIL CL-USER(9): (foo 10) 314.1592653589793d0 CL-USER(10): -- Duane Rettig[EMAIL PROTECTED]Franz Inc. http://www.franz.com/ 555 12th St., Suite 1450 http://www.555citycenter.com/ Oakland, Ca. 94607Phone: (510) 452-2000; Fax: (510) 452-0182 -- http://mail.python.org/mailman/listinfo/python-list