Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

please remind me why "alias" rather than "rename" #62

Closed
kjx opened this issue Feb 19, 2016 · 18 comments
Closed

please remind me why "alias" rather than "rename" #62

kjx opened this issue Feb 19, 2016 · 18 comments

Comments

@kjx
Copy link
Contributor

kjx commented Feb 19, 2016

The point of alias is to allow super-requests to overridden methods. If the super-method is always going to be redefined in the sub-object, why does the old one need to be there?

The main reason I'm asking is that aliasing variables and defs makes aliasing and exclusions more complex.

@KimBruce
Copy link
Contributor

It needs to be there to use the super class's method in defining the overriding method. It need not persist (which is why I hoped to make it “private”

On Feb 19, 2016, at 1:48 PM, kjx notifications@github.com wrote:

The point of alias is to allow super-requests to overridden methods. If the super-method is always going to be redefined in the sub-object, why does the old one need to be there?

The main reason I'm asking is that aliasing variables and defs makes aliasing and exclusions more complex.


Reply to this email directly or view it on GitHub #62.

@kjx
Copy link
Contributor Author

kjx commented Feb 19, 2016

What "needs to be there"? the alias or the original method?

class top {
  method m { }
}
class bot {
  inherit top
    alias n = m
  method m { n }
}

We rename top.m as bot.n; why does top.m needs to be in copied into bottom and then overriden?

@kjx
Copy link
Contributor Author

kjx commented Feb 21, 2016

There reason I'm asking is that renaming makes the semantics of defs & vars a bit easier, as there is always 0 or 1 name for the state.

@kjx kjx added the 1:now label Feb 21, 2016
@kjx
Copy link
Contributor Author

kjx commented Feb 22, 2016

Talking to Tim, he said, "the advantage is that the remaining superclass code might call the method, so taking it away breaks the superclass". Well OK, but in that case, why not replace the renamed method with an abstract method, not leave the old one there?

@apblack
Copy link
Contributor

apblack commented Feb 22, 2016

I think that the name of this issue is wrong. You are asking why we have alias and not aliasAndExclude.

(rename means something different: it implies doing the renaming refactoring consistently on the used trait or inherited superobject. This means, amongst other things, re-writing the code of all methods in that trait or superobejct that mention the old name so that they mention the new name instead. We don't want to do that, do we?)

The answer to the issue that you meant to raise is that alias is a primitive. If you want to both alias and exclude, you can get that effect with two primitives, both of which are available. If you want alias, but all you have is aliasAndExclude, what do you do?

I also don't see why your premise — that implementing aliasAndExclude is easier than implementing alias — should be true. I found it really easy to implement alias: just add another entry in the method dictionary that refers to the same method body. What Am I missing?

@kjx
Copy link
Contributor Author

kjx commented Feb 22, 2016

rename ... implies doing the renaming ... We don't want to do that, do we?

No we don't or at least I really don't! I'd been calling that "deep renaming" to distinguish between that and "shallow renaming" or "shallow aliasing" which don't go recursively. Eiffel has "deep renaming".
The difference between "shallow renaming" and "shallow aliasing" is just that "shallow aliasing" as you say below, just puts in a new entry in the method table, while "shallow renaming" also replace the old entry with an abstract method.

If you want alias, but all you have is aliasAndExclude, what do you do?

you do nothing with inheritance/uses, rather you write a forwarding method in the sub-object.
There's only a difference when you're not overriding the method you're aliasing or renaming: but if you're not overriding it, why should you be using alias?

What Am I missing?

what i think you're missing is that this only works when var and defs (or reader and writer methods of that primitive state --- and I guess once methods aka lazy defs) have slots in objects that are handled completely separately from the names.

If we have a [0..1]-1 relationship between names and definitions (shallow renaming), it's quite easy to keep that state around with the "seed" definition; if can get renamed, fine, if it gets excluded we remove the name but keep the definition around to run the initialisation code; the variable is dead after initialisation. There's never more than one name in any one object for one body or one bit of state.

If we have a [0..n]-1 relationship between names and definitions (shallow aliasing), then we really need to track each slot of state independently, inject each slot into the top of the semantics, and track them through aliases and excludes. So a def a could be aliased in several steps o b, c, and d, all those names excluded, and it's still hard to tell e.g. if the original "a" variable is dead, or if there are three names referring to it, or what.

Unfortunately, I figured out last night that addressing this properly would mean me rewriting my semantic model from scratch, which I won't get to before tomorrows meeting...

@kjx
Copy link
Contributor Author

kjx commented Feb 22, 2016

A clarifying example - should this be a error?

class top2 { 
  var v := 12 
} 
class bot2 { 
  alias v = w 
} 

bot2.v     
  • existing aliasing semantics, no, because bot2 has methods v and w both of which read the state slot for v coming down from top2
  • shallow renaming semantics, this would be an error, because bot2 only has access to that state via the name w;

@apblack
Copy link
Contributor

apblack commented Feb 22, 2016

Class top2 looks ok, but is completely useless. class bot2 is a syntax error, because alias is not a statement, but a modifier on inherits and uses.

@kjx
Copy link
Contributor Author

kjx commented Feb 22, 2016

trying again:

class top3 { 
  print "top3 {v}"
  var v := 12 
} 
class bot3 { 
  inherits top3
     alias v = w 
} 

bot3.v     

@KimBruce
Copy link
Contributor

Fixing the errors in the code (leaving out the inherits and making v readable), I believe this code should execute normally.

However, it’s weird code because the whole point of alias is to give an alternative name for a method that can be used when it is being redefined.

Kim

On Feb 22, 2016, at 2:19 PM, kjx notifications@github.com wrote:

A clarifying example - should this be a error?

class top2 {
var v is readable := 12
}
class bot2 {
inherits top2
alias v = w
}

bot2.v
existing aliasing semantics, no, because bot2 has methods v and w both of which read the state slot for v coming down from top2
shallow renaming semantics, this would be an error, because bot2 only has access to that state via the name w;

Reply to this email directly or view it on GitHub #62 (comment).

@apblack
Copy link
Contributor

apblack commented Feb 22, 2016

what i think you're missing is that this only works when var and defs (or reader and writer methods of that primitive state --- and I guess once methods aka lazy defs) have slots in objects that are handled completely separately from the names.

I was assuming that we have closures. The methods generated by the var and def declarations access state captured by the closure. Aliasing these methods causes no problems, and works just as well if the state is not in a field, but in an enclosing scope.

How do we implement closures efficiently? In JavaScript, it seems to be the case that we need to refer to the captured state by a gensym'd name in the object. This is much faster than relying on JavaScript's closures.

Once's are similar: the object has a gensym'd name that is used to cache the result of the once.

@kjx
Copy link
Contributor Author

kjx commented Feb 22, 2016

AND AGAIN:

class top4 { 
  method m {print "top4 {v}"}
  var v := 12 
} 
class bot4 { 
 inherits top4
  alias w = v 
} 

bot4.m    

However, it’s weird code because the whole point of alias is to give an alternative name for a method that can be used when it is being redefined.

right, that's my (other) point. This runs fine in both amg & Kernan, but should it?

@apblack
Copy link
Contributor

apblack commented Feb 22, 2016

Yes. Why not? Your second version didn't work because you were defining v to be an alias for a non-existent method, and my toy implementation correctly says "Syntax error: can't define alias for w because it is not present in the inherited object"

The version above looks like it should print "top4 12".

We can't stop you from writing weird code. We can give it the simple, obvious semantics.

@KimBruce
Copy link
Contributor

I don’t understand the problem with invoking m on bot4. The variable v does not disappear just because you have an alias to it. You simple have an extra name for the inherited feature. (And, again, I would prefer not to have the alias visible outside the object, but capitulated to the objections that we would have to create a new feature. But that is not relevant here.)

The point that I believe Andrew made a while ago is that just because you may no longer see something (e.g., via exclude) doesn’t mean it has actually gone away. It has just gone out of scope and you can no longer access it directly.

On Feb 22, 2016, at 3:11 PM, kjx notifications@github.com wrote:

AND AGAIN:

class top4 {
method m {print "top4 {v}"}
var v := 12
}
class bot4 {
inherits top4
alias w = v
}

bot4.m
However, it’s weird code because the whole point of alias is to give an alternative name for a method that can be used when it is being redefined.

right, that's my (other) point. This runs fine in both amg & Kernan, but should it?


Reply to this email directly or view it on GitHub #62 (comment).

@kjx
Copy link
Contributor Author

kjx commented Feb 22, 2016

The variable v does not disappear just because you have an alias to it. You simply have an extra name for the inherited feature.

yes, that's the current design.

(And, again, I would prefer not to have the alias visible outside the object,

it's not; aliases become confidential.

@kjx
Copy link
Contributor Author

kjx commented Feb 24, 2016

no-one seems minded to change this. I propose to close the issue, meaning it goes off the list.

@apblack
Copy link
Contributor

apblack commented Feb 26, 2016

Agreed: close this issue, and leave the meaning of alias as before.

@kjx kjx added 4:abandoned and removed 1:now labels Feb 26, 2016
@kjx kjx closed this as completed Feb 26, 2016
@kjx
Copy link
Contributor Author

kjx commented Mar 7, 2016

We can't stop you from writing weird code. We can give it the simple, obvious semantics.

I really like this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants