HaxeFoundation / haxe-evolution

Repository for maintaining proposal for changes to the Haxe programming language
111 stars 58 forks source link

Notation for native optional arguments #81

Closed vonagam closed 3 years ago

vonagam commented 3 years ago

Proposed notation for native optional non-nullable arguments that should always be at the end of an argument list, cannot be skipped with nulls in bindings (or with exotic haxe's type skipping), cannot be null-padded, does not require providing a default value that may go out of sync with described extern, does work clearly with old function notation:

?!Int->Void

function(?!value: Int): Void;

Render.

Relevant issues: 3826 7925

Alternative syntax can be single postfix question mark instead of prefix one:

Int?->Void

function(value?: Int): Void;
vonagam commented 3 years ago

Alternative without additional notation - some short typedef. Opt<T> for example.

More drastic change of course is to go back to the original design and treat ?Int argument as native non-nullable one. Which is cleaner/proper, but don't know about whenever it is considered possible at this point.

hughsando commented 3 years ago

I prefer the 'inline' keyword and make it work across all functions on all targets as call-site inlining, eg:

     function f(inline a:Int=1):Int;

the intention of the substitution is completely clear here - no problems with inheritance or overloading.

The optional-externs can already be accurately represented using overload:

@:cppFileCode('
const char * stringDup(const char *ptr, int len=-1)
{
   if (len==-1)
      for(len=0;ptr[len];len++);
   char *result = new char[len+1];
   for(int i=0;i<len;i++)
      result[i] = ptr[i];
   result[len] = 0;
   return result;
}

')
class Test
{
   @:native("::stringDup")
   @:overload(function (s:cpp.ConstCharStar) : cpp.ConstCharStar{ })
   extern public static function stringDup(s:cpp.ConstCharStar, len:Int) : cpp.ConstCharStar;

   public static function main()
   {
      trace( stringDup("hello",4) );
      trace( stringDup("hello") );
   }
}

So this case is maybe not so important. Also, the first 'inline' case should work too, but requires the "magic" -1 constant to be replicated, which just an unfortunate implementation detail.

vonagam commented 3 years ago

How would such inline optional parameter be represented in a function notation?

The optional-externs can already be accurately represented using overload

How do you override an external method with optional arguments?

hughsando commented 3 years ago

For a full haxe solution, the functional type is going to need to contain the default, so something like:

var func: (name:String, inline topScore:Int = 0)->Void = null;

I guess here, you can redefine the default value or even apply it to a function that does not have a optional argument because the default is in the signature, not the function call. Mostly though, type inference can copy this value.

You can't override native functions. If you want to do that, you could do something like make a haxe function call the native function, and then override the haxe function. Here, you would be using the haxe defaulting methods so existing logic would apply.

vonagam commented 3 years ago

Just to be clear this inline thing is only for standalone functions, not class methods, right?

You can't override native functions.

Why not?

hughsando commented 3 years ago

Perhaps post an example of what you are trying to achieve - it would be most helpful for discussions.

vonagam commented 3 years ago

Opened #9840, depending on how it go will update (or close) the PR.

Thanks for inline proposal, it might become handy later.