On Fri, Aug 17, 2012 at 12:24 PM, john skaller <
skal...@users.sourceforge.net> wrote:
>
> On 18/08/2012, at 4:28 AM, Dobes Vandermeer wrote:
>
> >
> > It's even wuss dan dat! Consider:
> >
> > val x = if a then b else c endif
> >
> > That reduces (internally) to
> >
> > val x;
> > if a then x = b;
> > else x = c;
> >
> > so the optimiser actually sees two initialisations of the one variable.
> > Only one gets executed (on a single control sweep).
> >
> > Is that desirable, or accidental?
>
> Neither: its appears to be necessary: how else can you
> implement it?
>
> Felix reduces stuff to "three-address" assembler code
> or the moral equivalent of it. So actually what you get is
> even worse that what I wrote:
>
> if (!a) goto label;
> x = c;
> goto endoff;
> label:>
> x = b;
> endoff:>
>
> Felix has goto, conditional goto as primitives. (It also has halt, call,
> return, jump, yield, and a few other such things).
>
> There are no high level control structures like for loops,
> while loops, blocks, or anything else: these have to be
> implemented in the library (typically directly in the
> grammar, which, remember, is in user space so its
> part of the library).
>
What are you saying, is that your internal representation makes it
difficult or impossible. However, this isn't the only representation
available, so really what you are saying is that you don't want to change
your representation.
> > Because the point of initialisation is not well defined, deliberately.
> > If you write:
> >
> > var x = 1;
> > val y = x;
> > ++x;
> > println$ y;
> >
> > you might get 1 or 2. You will get 1 with eager evaluation and 2 with
> lazy evaluation.
> >
> > Well, who exactly benefits from this unpredictable behavior?
>
> You do. Most of the time it makes no difference to the semantics,
> and it allows generation of blindingly fast Hyper Light Speed code.
>
> > What's point in spending all this effort with a strict type system that
> prevents type errors, and yet add some lazy evaluation system that
> introduces unexpected semantic errors?
>
> The point is to get performance first at all costs.
> As it turns out, the existing semantics rarely cause trouble.
>
I guess performance isn't THAT important to me. There's this idea that
programmer time is more important than program runtime, so one should avoid
things that confuse the programmer. If the runtime behavior depends
heavily on optimizer decisions, that's confusing and can lead to hard to
find bugs.
However this is really the point of wanting to add "const".
> There's nothing wrong with val semantics, it just isn't enough.
> Indeterminacy is good, its precisely where performance optimisations
> come from.
>
I think it's important that programmers can understand easily how their
code will behave BEFORE they run it.
>
> >
> > > Do not allow a val to be initialized more than once or be used before
> it is initialized.
> >
> > How do i stop it? Don't allow vals at all after a label?
> >
> > A lexical approach seems fine - if the val is used in a statement that
> comes earlier than it's declaration, report an error "val x used before it
> was defined". Same for vars.
>
> That's hard to determine! Did you forget nested functions?
> What about closures?
>
> For vars: pointers.
>
Lexical ordering seems relatively simple to me, maybe I'm missing something:
Nested function:
fun x() {
fun y() => x; // Error
val x;
fun z() => x; // OK
}
Closures:
fun x() {
proc inc1() => x+=1; // Error
var x = 0;
proc dec1() => x -= 1; // OK
}
Pointers:
val y = &x; // Error
var x = 0;
val z = &x; // OK
You also have to consider blocks:
proc x() = {
print x; // Error!
print y; // Error!
if true do
val x = 1;
print y; // Error!
else
val y = 2;
print x; // Error!
val z = x + y; // Error!
endif
print x; // Error!
print y; // Error!
}
> >
> > This information came as a suprise to me, so I did a test:
> >
> > proc b(i:int)() = {
> > println$ "b, i = "+i;
> > }
> > proc a() {
> > var i = 0;
> > bb := b(i);
> > i = 10;
> > bb;
> > }
> > a();
> > // prints b, i = 10
> >
> > You complain about the dangers of downcasting in other languages, and
> yet this doesn't flabbergast you?
> >
> > It's a programming language boobytrap! It's actually breaking the
> contract of how parameters and closures are understood to work. That is,
> parameters are your own private immutable copy, and creating a closure of
> them captures the value at the time of the original call.
>
> No it doesn't. You just misunderstood the contract. You have not captured
> a value, you captured a variable. A variable is logically a pointer.
>
So are you saying that parameters are always passed by reference in Felix?
That might be acceptable if it's clear to people who use the language (it
certainly isn't and wasn't for me!). Personally this seems confusing and I
strongly recommend changing the policy on that.
Changing the semantics of val is not an option. I have looked at this
> and it would disable a huge number of significant optimisations,
> and 99% of the time there is no semantic impact.
>
I suspect that 99% of the time that 99% of optimisations have no material
performance impact on real world applications. For the few bits of "hot"
code that would make a difference, people can read the optimiser's guide to
Felix and learn out how to change variables to use lazy evaluation, stuff
like that.
If you ran the above program in Ocaml with a ref instead of the var
> (an Ocaml ref that is) you'd get the same answer as Felix.
>
Right, but that's explicit, this isn't. In fact it wasn't desired in this
case.
> This is why i suggest "const": it's referentially transparent
> so it necessarily cant produce different values.
>
I don't have a problem with that syntax but I think val is supposed to do
that job.
However we're not finished, because, unfortunately,
> even transparent expressions don't need to be total!
> That is: division is pure, but it isn't total. So it STILL
> matters when you evaluate it.
>
I guess what you are referring to is that if you divide by zero the program
may crash or throw an exception. There are many operations that have this
property, such as dereferencing an uninitialized val of a pointer type
(???) (you might want to address that gaping hole first) but I'm not sure
it is quite as important to address them at this level.
A strict approach to this case would be to have division return an option
value of some kind instead of a numeric result. Otherwise you're back to
doing exception handling which you've already pointed out the problems with.
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language