[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: orthogonality and generalized references (was Re: Zen of Python)

Hi, Matthias.  Actually, it's precisely my point that anybody versed in
Icon will immediately recognize the sequence of success and failure
computations because success/failure is central to Icon.  By learning to
reason about success and failure as primitive/essential/fundamental
notions, an Icon programmer feels comfortable with them and can exploit
them to their advantage.

(I would guess that you'd argue something similar about explicit
higher-order programming, continuations, etc.  Once you feel comfortable
with them, their power is yours to exploit.)

You can obviously argue that one *can* synthesize success/failure
computations from other primitives in Scheme.  Absolutely correct.  But,
I'd argue that the unfortunate thing is that one *must* synthesize them
to have them, thereby raising the cost of exploiting the concept.  I
simply think that it's unfortunate that success/failure computations
must be synthesized in non-goal-directed languages, thereby minimizing
the likelihood of them being used effectively.


-----Original Message-----
From: Matthias Felleisen [mailto:matthias@ccs.neu.edu] 
Sent: Monday, May 27, 2002 6:25 PM
To: Todd Proebsting
Cc: Kragen Sitaker; ll1-discuss@ai.mit.edu
Subject: RE: orthogonality and generalized references (was Re: Zen of

Todd, is Icon's symmetry of success and failure really the proper path
here? Isn't it the case that you want something like 

 (hash-table-get HT 'foo
   ; failure thunk: 
   (lambda () (hash-table-put! HT 'foo 42))

so that the reader recognizes the sequence of success and fail

-- Matthias

At Mon, 27 May 2002 17:57:55 -0700, "Todd Proebsting" wrote:
> Ages ago I posted to this list about goal-directed evaluation in Icon.

> This "ifAbsentPut" discussion will, I hope, allow me to express 
> another advantage of goal-directed evaluation.  In Icon, the 
> ifAbsentPut idiom is the following simple expression---Icon has only 
> expressions, and not statements.
> /dict["foo"] := 42
> To understand this statement, you must understand the unary '/' 
> operator and the notion of goal-directed evaluation.  The '/' operator

> computes the l-value (if one exists, otherwise the r-value) of its 
> operand IFF the r-value is not null.  If the r-value is null, then the

> operation fails.  With goal-direction, an operand failing causes its 
> parent operation to do whatever it is supposed to do when the operand 
> fails. (The rules for what to do are simple and regular, but I'm not 
> going to go into them here.)
> In this case the parent is the assignment operator, which itself will 
> fail when its left operand fails.  If and when the right operand and 
> left operands have both succeeded, the assignment takes place and the 
> r-value is produced as a value.
> So, the assignment above will assign the value 42 to dict["foo"] when 
> dict["foo"] is null and simply fail when dict["foo"] is non-null.  
> Note that the l-value is computed only once.
> The '/' operator can, of course, be applied to any expression.  Any 
> Icon programmer would recognize the idiomatic use of '/' above.  I 
> find it superior to the other schemes that I've seen.
> I wish other languages exploited the fundamental difference between 
> success and failure that is essential to Icon.  It's awkward to code 
> your way around their absence in other languages.
> Todd
> -----Original Message-----
> From: Kragen Sitaker [mailto:kragen@pobox.com]
> Sent: Monday, May 27, 2002 4:56 PM
> To: ll1-discuss@ai.mit.edu
> Subject: orthogonality and generalized references (was Re: Zen of
> Python)
> Avi Bryant writes:
> > [in Ruby]
> > dict['foo'] ||= 42
> > [in Smalltalk, "extremely regular and explicit"]
> > dict at: 'foo' ifAbsentPut: [42].
> > ...
> > What's the equivalent Python idiom?  My guess is that it will be
> > either less regular, or less explicit, or both.  I'm not trying to 
> > pick on Python, I'm just trying to point out that there is no simple

> > relationship between regularity, explicitness, and succinctness;
> > entirely possible to have all three.
> Python uses roughly the Smalltalk approach, although (like Perl) it 
> doesn't provide a convenient way for you to avoid evaluating the 
> default value in the case that the value is already present:
>     dict.setdefault('foo', 42)
> I don't quite understand what you mean by "regular" or "explicit"; the

> Ruby/Perl idiom is less explicit, I agree, but it appears to me to be 
> more regular --- the Smalltalk/Python idiom here is to use a 
> special-purpose method, while the Ruby/Perl idiom is a combination of 
> three orthogonal language features that have nothing to do with 
> dictionaries or hashes: the boolean 'or' operator's return value, the 
> false result of looking up a nonexistent index in a dictionary or 
> hash, and the augmented assignment operators.  As a result, you can 
> also say (in Perl):
> $x ||= 42;    # ordinary variable
> $y[3] ||= 42; # list reference
> Common Lisp has the notion of a "generalized reference", such as 
> (gethash "foo" dict), which can be set with setf or read by 
> evaluation; and it has boundp and makunbound, but they only work on 
> symbols, not generalized references.  In a CL dialect where boundp and

> makunbound (somehow --- they standardly evaluate their arguments, so 
> (boundp (gethash "bar" x)) will tell you whether the symbol (gethash 
> "bar" x) returns is bound or not) worked on generalized references, 
> you could write a setdefault macro that would allow you to say things 
> like this:
> (setdefault (gethash "foo" dict) 42)
> (setdefault x 42)
> (setdefault (nth 3 y) 42)
> giving you the same level of regularity and orthogonality you have in 
> Perl and Ruby, along with the same level of explicitness you have in 
> Python (and, arguably, Smalltalk, although I think at:ifAbsentPut: is 
> more explicit than setdefault).
> (I don't know Common Lisp; apologies for any mistakes.)
> I wish I had a language where I could define this "setdefault" 
> operation; it requires Common Lisp's ability to define new operations 
> on generalized references (for example, with macros; you can do it 
> crudely in C++ with a reference or in Forth with a raw memory address)

> along with Python's ability to get, set, undefine, or check 
> definedness of generalized references. [0] Is there such a language?
> [0] Python conflates providing an initial value and replacing an 
> existing value with a new value, unfortunately, and provides 'check 
> definedness' by raising an exception when you try to get an undefined 
> value.  Also, Python's generalized references are variables, object 
> attributes (x.y), and indexing expressions (x[y]), not general 
> function calls; this sounds more limiting than it is.
> --
> /* By Kragen Sitaker, http://pobox.com/~kragen/puzzle2.html */ char
> a[99]="  KJ",d[999][16];main(){int
> s=socket(2,1,0),n=0,z,l,i;*(short*)a=2;
> =0;i<n;
> i++){z=(memcmp(d[i],d[n],8))?z:0;while(sendto(s,a,l,0,d[i],16)&0);}z?n
> i++++
> i++:0;}}}