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

Non-positional object construction (as well as positional) shorthand #550

Open
ASVIEST opened this issue Feb 2, 2024 · 5 comments
Open

Comments

@ASVIEST
Copy link

ASVIEST commented Feb 2, 2024

Abstract

Non-positional match object fields and identifies in object constructor in general and positional with {.positional.} pragma

Motivation

Same as
#517
#418

Description

Main idea is match object fields and it's names (i.e it not positional)
Rules:

ident --> ident: ident
sth.ident --> ident: sth.ident
Obj(sth.a, b, c: 0) --> Obj(a: sth.a, b: b, c: 0)

positional pragma

positional pragma is pragma that can set common (proc like) object calling, it useful for example when different fields have the same meaning (vectors, matrices, etc.)

type
  Vec {.positional.} = object
    x: int
    y: int
    z: int

let vec = Vec(x, vec.y, 42)

Code Examples

type
  Vec2 = object
    x: int
    y: int

  Vec1 = object
    Y: int

let x = 42
let vec = Vec1(y: 42)

# New syntax
let _ = Vec2(x, vec.y)
let _ = Vec2(vec.y, x) # also work

type
  Vec3 = object
    x: int
    y: int
    z: int

let _ = Vec2(vec.y, z: 15, x)

# positional pragma

type
  PosVec {.positional.} = object
    x: int
    y: int
    z: int

let _ = PosVec(x, vec.y, 42)

Backwards Compatibility

No response

@Araq
Copy link
Member

Araq commented Feb 3, 2024

You can't have it both ways so that the meaning of Vec(x, z, y) depends on whether Vec was declared positional or not. It's a bad idea. We only should have positional as the non-positional way plays havoc with my understanding of Nim's scope rules so I would veto it.

@Araq
Copy link
Member

Araq commented Feb 3, 2024

Furthermore the non-positional thing is trivally doable with a macro anyway and then it's explicit: inferFields Vec(x, y, z) can turn it to Vec(x: x, y: y, z: z).

@ASVIEST
Copy link
Author

ASVIEST commented Feb 3, 2024

You can't have it both ways so that the meaning of Vec(x, z, y) depends on whether Vec was declared positional or not. It's a bad idea. We only should have positional as the non-positional way plays havoc with my understanding of Nim's scope rules so I would veto it.

What's wrong with Nim's scope rules ?

@arnetheduck
Copy link

arnetheduck commented Feb 3, 2024

I'm fine without positional, so many pitfalls on the caller side - name-matching shortcuts however, quite nice 👍👍 the scope of the name matching lookup is the object being constructed, of course.

This is something that could also be expanded to function calls - ie for proc f(a, b, c: int), if I call it with f(a, c, b) the language could issue a warning which would be disabled by f(a, b=c, c=b), ie if the name doesn't match, use explicit parameter names.

A macro for this defeats the purpose - the aim is to avoid extra ceremony when it's obvious what is meant (ie when name matches). This is not the case for positional arguments which are never explicitly numbered so by looking at the code, one cannot tell if the ordering is deliberate or not. Naming is always deliberate.

@ASVIEST
Copy link
Author

ASVIEST commented Feb 3, 2024

You can't have it both ways so that the meaning of Vec(x, z, y) depends on whether Vec was declared positional or not.

It's problem ? Vec must be positional by it's mearning: ordered couple of values.
Why caller side must know that uses positional or not ? This should be done in the object's design, not in the constructor.

You shouldn't declare object whose field initilizing order is important without {.positional.}

I think it should just be in nep1:
when you object order of the fields is important i.e.

type Vec = object
  x: int
  y: int
  z: int

and

type Vec = object
  y: int
  x: int
  z: int

must be not same decl, then mark object as {.positional.}

I’m not at all sure that positional is needed somewhere other than pattern matching. For pattern matching {.positional.} is quite useful.

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

No branches or pull requests

3 participants