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

Syntactic sugar for ignoring a type parameter #29875

Open
KristofferC opened this issue Oct 31, 2018 · 16 comments
Open

Syntactic sugar for ignoring a type parameter #29875

KristofferC opened this issue Oct 31, 2018 · 16 comments
Labels
parser Language parsing and surface syntax

Comments

@KristofferC
Copy link
Member

KristofferC commented Oct 31, 2018

Consider

struct Foo{A, B, C, D}
end

and we want to write a binary function where D has to match.

Possibilities:

foo(A::Foo{A1, B1, C1, D}, B::Foo{A2, B2, C2, D}) where {A1, A2, B1, B2, C1, C2, D} = ...
foo(A::Foo{<:Any, <:Any, <:Any, D}, B::Foo{<:Any, <:Any, <:Any, D}) where {D} = ...

How about:

foo(A::Foo{_, _, _, D}, B::Foo{_, _, _, D}) where {D} = ...

?

Using _ as an rvalue is deprecated so could this should be available?

@KristofferC KristofferC added parser Language parsing and surface syntax triage This should be discussed on a triage call labels Oct 31, 2018
@StefanKarpinski
Copy link
Member

Related: #24990. These don't necessarily conflict since we can special case the interior of T{...} but it's worth paying attention to.

@JeffBezanson JeffBezanson removed the triage This should be discussed on a triage call label Nov 1, 2018
@KristofferC
Copy link
Member Author

Triage: Will wait a bit for the eventual resolution of #24990

@o314
Copy link
Contributor

o314 commented Oct 13, 2019

This is a very good proposal. I am impatient to see this in Base !

After years of discussion, 214 comments over there, what about unsyncing of #24990 to follow its own way...

@StefanKarpinski
Copy link
Member

As I wrote over there, #24990 is

Designed and I think largely agreed upon but requires a different implementation

so it's not as if no progress has been made and this proposal conflicts with that one.

@o314
Copy link
Contributor

o314 commented Oct 14, 2019

Thanks for your feedback. I have read your comment before previously posting,
and have seen it has occured monthes ago, nearly quarters ago now.
I must confess i find it's very hard to track the state of major proposal on github issues / discourse.
214 comments! Good if consensus is reached and momentum is kept.

@o314
Copy link
Contributor

o314 commented Oct 23, 2019

You will now have

Foo{_, _, _, D} where {D} rather than Foo{A,B,C,D} where {A,B,C,D}. Much leaner

I also suggest to consider

  • Foo{_, _, _, <:Baz} equivalent to Foo{_, _, _, _<:Baz}
  • Foo{_, _, _, >:Bar} equivalent to Foo{_, _, _, _>:Bar}

bonus

  • Foo{_, _, _, Bar<:_<:Baz} no equivalent in short form nowaday, neither later

That will consolidate short forms and bring them to same level of capabilities than long where ones.
where can become a kind of scope expander (to function body), factorizer (your first proposal with constraint on D will better fit a factorized clause in where rhs rather than redeveloped @ A::, B::).

@StefanKarpinski
Copy link
Member

This is certainly a nice feature, but again, the syntax collides with #24990. The question is which feature is more useful/important and worth getting this bit of syntax? You can already use <:Any for many of these.

@o314
Copy link
Contributor

o314 commented Oct 23, 2019

I understand your concern about the timeframe and mutual impact.
You have been clear enough. The point is not to discuss this anymore.

This is just a note to consider when time of choice and/or implementation will come.
Cordially

--
My point of view is that there will be some echo, for sure, but not necessarly insuperable conflict

@o314
Copy link
Contributor

o314 commented Dec 13, 2019

Another case to consider (coming from porting of rust code to julia)

abstract type Result{O,E} end
struct OK{O} <: Result{O,_}; value::O end
struct Err{E} <: Result{_,E}; value::E end

seems clearer than

abstract type Result{O,E} end
struct OK{O,E} <: Result{O,E}; value::O end
struct Err{O,E} <: Result{O,E}; value::E end

@tkf
Copy link
Member

tkf commented Dec 13, 2019

Why not save _ for #24990 and use

foo(A::Foo{, , , D}, B::Foo{, , , D}) where {D} = ...

? Not having placeholders like _ is probably not the most elegant syntax. But I guess it's at least not ambiguous?

@o314
Copy link
Contributor

o314 commented Dec 13, 2019

Quoting big boss JeffBezanson

That's the problem with special syntax; there's never enough of it.
#19198 (comment)

Code is 90% reading, 10% writing, and sorry, but special form are childhood diseases there.
The proper way to go is to handle context properly in parsing. We have the chance to deal with context-free grammar in programming language (eg. choosen and explicit context only), it should be used and abused. That's really lucky, NLP practitioner in lisp could have experience the shift in mindset.

@o314
Copy link
Contributor

o314 commented Dec 13, 2019

About #24990. Nothing personal there but, engineers have to consider some facts about it:

  • LOC: 83 lines
  • Forum posts: 214
  • Duration : 726 d

Giving the following ratio

  • Forum post per 10 loc : 26
  • LOC per month: 3.5

Neither a good way to contribute to foss, neither a foundational work in any way at this stage.

@KristofferC
Copy link
Member Author

Code is 90% reading, 10% writing, and sorry, but special form are childhood diseases there.

None of the current ways of doing this

foo(A::Foo{A1, B1, C1, D}, B::Foo{A2, B2, C2, D}) where {A1, A2, B1, B2, C1, C2, D} = ...
foo(A::Foo{<:Any, <:Any, <:Any, D}, B::Foo{<:Any, <:Any, <:Any, D}) where {D} = ...

seem easy to read so not sure what point you are trying to make?

Neither a good way to contribute to foss, neither a foundational work in any way at this stage.

A metric like number of lines per month a PR has been opened seems like a bad way to measure progress. Not all lines of code are equal.

@stev47
Copy link
Contributor

stev47 commented May 2, 2020

Contrary to #24990 this proposal is actually consistent with the current meaning of _ being a sink to function arguments, extending it to function argument types.

@uniment
Copy link

uniment commented Feb 1, 2023

Wouldn't this idea work better if : is used instead? Using it here feels more congruent anyway with its existing meaning [to access everything along this dimension] than _ [to discard a value].

To illustrate,

foo(A::Foo{:, :, :, D}, B::Foo{:, :, :, D}) where {D}

seems more ergonomic and isn't conditional on the resolution of 24990. It would be defined to work as:

Foo{:} == Foo{<:Any} == Foo{>:Union{}}

(Also possible to construct type ranges as @o314 alludes to above, e.g. Integer:Number, though I'm not sure how useful that is.)

@nsajko
Copy link
Contributor

nsajko commented Oct 31, 2024

Coming from the Discourse topic by @frankwswang: https://discourse.julialang.org/t/adding-a-type-parameter-annotation-symbol-that-preserves-the-original-bound/122015

The above proposal doesn't make it clear what should happen in a case when some of the parameters of struct Foo have constraints. For example:

struct Foo{A <: P, B, C, D}
end

Which one of these should it be:

  1. Foo{_, _, _, D} == Foo{<:Any, <:Any, <:Any, D}
  2. Foo{_, _, _, D} == Foo{<:P, <:Any, <:Any, D}

The second option seems like a much safer default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
parser Language parsing and surface syntax
Projects
None yet
Development

No branches or pull requests

8 participants