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

[superseded] new syntax for lvalue references: byaddr x = expr #13342

Closed

Conversation

timotheecour
Copy link
Member

@timotheecour timotheecour commented Feb 6, 2020

byaddr foo = bar produces this AST:

  CustomDefSection
    Ident "byaddr"
    IdentDefs
      Ident "foo"
      Empty
      Ident "bar"

thanks to nkCustomDefSection, we can easily extend to additional keywords without changing much else in the compiler/parser/lexer, and more importantly user code, for example it'd be easy to add (if one wanted to):
alias foo = bar

example

var x = @[1,2,3]
byaddr x1=x[1]
x1+=10
doAssert type(x1) is int and x == @[1,12,3]

# the expression is evaluated exactly once, which matters in case of expensive computation or side effects:
byaddr x1 = x.foo(2)[3].bar  # evaluated here
echo x1
echo x1

# unlike with:
template x1(): untyped = x.foo(2)[3].bar
echo x1 # evaluated here
echo x1 # evaluated here

@Araq
Copy link
Member

Araq commented Feb 6, 2020

Things like these must go through the RFC process, if only so that people have a better chance to vote on them. And personally I would have used let/var x {.view.} = someLocation. Adding a new pragma before a new keyword seems good and so does keeping the let vs var distinction.

@timotheecour
Copy link
Member Author

well that was the conclusion from #11824 (comment)

Well we can add a keyword to the language. Or maybe we can/should do let x {.byAddr.} = y

(and I've opted for add a keyword to the language instead of let x {.byAddr.} = y given that let x {.byAddr.} = y is long, ugly, confusing and that I expect to use this feature a lot)

@Araq
Copy link
Member

Araq commented Feb 6, 2020

Well I'm sorry, but not everything I say has a chance of being accepted immediately. Sometimes I'm just throwing ideas around.

@zah
Copy link
Member

zah commented Feb 6, 2020

I believe this capability is present in the more comprehensive proposal here:
nim-lang/RFCs#178

Due to the way type classes interact with type inference, once the proposal is implemented you'll be able to write code like the following:

let x: lent = foo()
var y: var = bar()

@Araq
Copy link
Member

Araq commented Feb 6, 2020

Note that I cannot stand

let x: lent = foo()
var y: var = bar()

Nim is about type inference. However, something like this:

let x = lent foo()
var y = var bar()

is perfectly fine. IMHO anyway.

@timotheecour
Copy link
Member Author

timotheecour commented Feb 6, 2020

let x0 = @[1,2]
var y0 = @[1,2]
let x = lent x0[0]
var y = var y0[0]
y+=10
doAssert y0 == @[11, 2] 
doAssert type(x) is int
doAssert type(y) is int
  • do the asserts pass ?

@cooldome
Copy link
Member

cooldome commented Feb 6, 2020

IMO, lent/var is determined by return type of foo() / bar () / not by the caller of the function. Caller then can unwrap lent T to T if he likes. I would suggest call it copy as unwrapping produces copy.

@Araq
Copy link
Member

Araq commented Feb 6, 2020

IMO, lent/var is determined by return type of foo() / bar () / not by the caller of the function.

Yes but the caller can extend the "var/lent-ness" via my proposed annotations.

@Varriount
Copy link
Contributor

What does this do? Create expression aliases?

@timotheecour
Copy link
Member Author

timotheecour commented Feb 7, 2020

What does this do? Create expression aliases?

analog of C++ references in auto& a = expr
I've already discussed in top-post (and in #11824) why current alternatives are not good enough:
template a: untyped = expr => will evaluate each time (even if costly/side effect)
let a = expr => not a reference, does a copy

@zah in your proposal, would the asserts pass in #13342 (comment) ?
in any case I think this (and especially original version i had in #11824) is much simpler, and #11824 in particular doesn't require any language change; also it's not clear when the proposal you're suggesting is to be implemented.

also byaddr is simpler to use:

byaddr y = expr
vs:
var y = var expr # double var is awkward

@zah
Copy link
Member

zah commented Feb 20, 2020

@timotheecour, yes, these asserts should pass. The type equivalences are slightly more dubious, but that's what Nim currently does:

type Foo = object

proc bar(x: Foo, y: var Foo) =
  echo x is Foo # true
  echo y is Foo # true

Here, the types of x and y will be precisely lent Foo and var Bar, just like in your example.

@zah
Copy link
Member

zah commented Feb 20, 2020

The main idea of the other proposal is that it comes with a set of rules that make these short-lived aliases safe. Enforcing the rules is the most significant challenge here. The syntax is less important, but again, the other proposal is a bit more versatile covering the full spectrum of var, lent and openarray pointers. If we accept the feature without enforcing the rules, we'll need to either stick with unsafe code forever or introduce a breaking change in the future.

@timotheecour
Copy link
Member Author

superseded by #13508

@timotheecour timotheecour changed the title new syntax for lvalue references: byaddr x = expr [superseded] new syntax for lvalue references: byaddr x = expr Mar 23, 2020
@timotheecour timotheecour deleted the pr_parser_customasgn branch March 23, 2020 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants