On Fri, 2003-10-24 at 16:32, Louis Kruger wrote:

> Actually, I really meant "throws an exception", but thats a discussion 
> for another day.  ;)

Heh.  Definitely another day.  I like exceptions, but putting them
into Unicon in a clean fashion is a *big* task...

> There's another possibility I thought of after sending my last message,
> and that is to have the compiler detect when a local variable has a 
> reference operation applied it to it while its in scope, and allocate it 
> on the heap in that case.  It could then be thrown away by the GC when 
> its last reference disappears.  This allows you to return a reference to 
> a variable from a function, and not worry about its safety, and also 
> eliminates the performance penalty of checking every dereference.

Not quite.  There are a few 'gotchas' with this approach, though I think
it's the best proposal I've seen so far.

(1) Right now, you can't put scalar values into the heap (not enough
     room in the descriptor for the mark used for mark-and-reclaim GC).
     So, you have to embed it into an internal 'heap' structure [as
     statics are now].  Once, you do that, have you really gained
     anything over putting things you want references to into Unicon
     structures?

(2) It doesn't help with references to list elements.  There's still
     some semantics to work out here, for example, consider:

     (a)  L := [x,y,z]
           lRef := `L[1]
           pop(L)

           is lRef still valid?  What does it reference?  What about:

     (b)  lRef := `L[1]
           pop(L)
           push(L,w)

           (I think a reference to a list element has to refer to that
           element and *not* it's position in the list, but that strikes
           me as a *bear* to implement!)


> Circumventing call by value is one use, but there are others.  Being 
> able to save and reuse lvalues from functions and generators would help 
> work around the brilliant, but ugly hacks people have come up with.  You 
> can also imagine creating data structures of references.

Yes, that's true, but I wonder if it's really that important.  After
all, there are other ways to code those (admittedly less terse, but
perhaps clearer in meaning...).  That is, rather than trying to write
these as single expressions it might just be better to go ahead and
stick a few control structures in there.  After all, you can hide the
code in a procedure and never have to look at it again!

     procedure forceNonNegative(L, v)
          every L[i := 1 to *L] < 0 do L[i] := v
          return L
     end

I refuse to believe it's a performance issue: (a) this is Unicon,
(b) a good optimizing compiler should be able to wonderful things
with code like the above (and reference types are a real pain for
good optimizing compilers), and (c) these days, it seems that the
best way to optimize code is to wait three months and buy a faster
computer!  [I know there's no good optimizing compiler for Unicon,
but I keep hoping someone will look at a ucode optimizer....]

> Well, I program 90% in Java, and I certainly would make use of 
> references there.  I cringe every time I have to create a special class 
> or array just because I want to return more than one value from a 
> function.  Other examples that motivate having references in Icon don't 
> apply to Java, because Java isn't as rich in other ways.

Interesting - I'm in pretty much the same boat - Java programming is
what pays my bills.  However, I've never found myself cursing Java
for that flaw (there are others...).  I wonder what the difference is?
It may be because I learned Icon before C (C was still hidden in Bell
Labs back then) and so by 'baby duck' tend not to think of thinks like
pointers and explicit references.)  The (related) thing I curse Java
for is for not providing an explicit, clean syntax for classes without
methods - i.e. records [though I understand why they don't].

I guess I'll argue that functions that want to return more than
one value really want to return a structure - that these values *must*
be in someway related [or else computing them in a common function
is a mistake!] and should be related that way explicitly - and *not*
just for passing to a function, but throughout the program.  This
requires a shift in how one thinks about the problem being addressed.
Whether or not this shift is desirable is probably more personal taste
than anything else, of course.

Take for example, Kazimir's local_min() example.  Another approach is
to recognize that what's really wanted is a function that takes another
function f and three parameters x,y,z and computes the local mininum for
based on that function and those parameters.  I see no reason to force
that local minimum back into the same variables as x,y,z, so why not:

    p := local_min(f, [x1,   x2,   x3])
    q := local_min(f, local_min(f, [p[1], p[3], x4])
    r := local_min(f, [p[2], q[2], q[3])
    write(q[1], r[1], r[2], r[3])

which, while not as terse as in Pascal, isn't that far off
and offers the advantage of making it easier to trace where
values are coming from!  [The duplicate 'local_min(x1,x3,x4)' in
Kazimir's example through me for a moment...though I think it's
redundant, if local_min works as advertised.  I left it in the above
code.]  And it may well be advantageous later to have not distroyed the
original values.  (To be fair, I'd probably personally represent
the local minumum as a triple (record) than as a list, but that's
also personal taste.)

-- 
Steve Wampler <[EMAIL PROTECTED]>


-------------------------------------------------------
This SF.net email is sponsored by: The SF.net Donation Program.
Do you like what SourceForge.net is doing for the Open
Source Community?  Make a contribution, and help us add new
features and functionality. Click here: http://sourceforge.net/donate/
_______________________________________________
Unicon-group mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/unicon-group

Reply via email to