Re: What is Expressiveness in a Computer Language

2006-06-23 Thread Duane Rettig
"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

2006-06-23 Thread Duane Rettig
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

2006-06-27 Thread Duane Rettig
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

2006-12-08 Thread Duane Rettig
"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?

2007-05-01 Thread Duane Rettig
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

2006-05-12 Thread Duane Rettig
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

2006-05-12 Thread Duane Rettig
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

2006-05-13 Thread Duane Rettig
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