Jump to content


Photo

passing parameters by name


  • Please log in to reply
14 replies to this topic

#1 tinku99

tinku99
  • Members
  • 560 posts

Posted 09 July 2009 - 02:17 AM

Instead of evaluating then silently discarding extra parameters, it might be more useful to use them as local variables instead. This would allow calling parameters by name.

So instead of the following workaround inolving a global,
x = fx       
%x%(x := 3)
fx()
{
global x
msgbox % x ;  x is 3
}
you could do this:
; proposed syntax
x = fx   
%x%(a := 3)  ; a becomes a local variable automatically
fx()
{   
msgbox % a ;  a is 3
}


#2 HotKeyIt

HotKeyIt
  • Fellows
  • 6132 posts

Posted 09 July 2009 - 05:04 AM

What is the reason for that? Is it just to omit variables?
I think you would get confused very quickly.

If I have to pass many different variables I use that technique :)
x = fx   
%x%("a3")  ; a becomes a local variable in loop below.
fx(options="")
{
 global
 local a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,option
 If (options){
		Loop,Parse,options,%A_Space%
			If (option:= SubStr(A_LoopField,1,1))
				%option%:= SubStr(A_LoopField,2)
 }
 msgbox % a ;  a is 3
}


#3 Lexikos

Lexikos
  • Administrators
  • 8845 posts

Posted 09 July 2009 - 07:44 AM

1) What's it got to do with dynamic function calls?
2) The proposed syntax conflicts with assignment.

#4 tinku99

tinku99
  • Members
  • 560 posts

Posted 09 July 2009 - 01:16 PM

1) What's it got to do with dynamic function calls?
2) The proposed syntax conflicts with assignment.

Only dynamic function calls support more than necessary parameters currently. Actually maybe nondynamic function calls should also support unnecessary parameters.

perhaps a different syntax to accomplish the same thing to avoid the conflict with assignment.
such as
fx(x as 4)...

yes, it would allow you to omit variables... that's what makes it named parameters different from just optional parameters at the end, like what is currently allowed.

Edit:
Actually, I don't see the conflict with assignment. Lexikos could you please explain?

#5 Lexikos

Lexikos
  • Administrators
  • 8845 posts

Posted 09 July 2009 - 09:14 PM

Try this code.
F(x := 3)
MsgBox % x
F(ByRef A) {
    A += 1
}


#6 tinku99

tinku99
  • Members
  • 560 posts

Posted 09 July 2009 - 09:54 PM

byref parameters are not local anyways.
The proposed syntax is for non-byref parameters.

#7 Sean

Sean
  • Members
  • 2462 posts

Posted 09 July 2009 - 11:56 PM

In a related note, I'm wondering if it's hard to implement to allow missing/omitting optional parameters.
f(p1 = 1, p2 = 2, p3 = 3, p4 = 4){
...
}

f(p1, , p3)


#8 Tuncay

Tuncay
  • Members
  • 1943 posts

Posted 10 July 2009 - 07:41 AM

Another syntax suggestion:
fx([color=red]local[/color] x := 4)
Extending the local keyword at function calls.

And for seans suggestion
f(p1 = 1, p2 = 2, p3 = 3, p4 = 4){
...
}

f(p1, [color=red]A_Default[/color], p3)
introducing new variable for use in different situations (universal). In example it holds a special content, everytime Ahk see this content it does appropriate action to current context.

#9 Lexikos

Lexikos
  • Administrators
  • 8845 posts

Posted 10 July 2009 - 08:44 AM

In a related note, I'm wondering if it's hard to implement to allow missing/omitting optional parameters.

I implemented it in a private build a while back, but was reluctant to add it to AutoHotkey_L. Basically I did this:
[*:2qnik7te]Change load-time validation to allow empty parameters. (I chose to disallow blank parameters at the end of the parameter list since it wasn't useful; there may have also been technical reasons.)
[*:2qnik7te]Change the infix to postfix conversion phase to put blank_token into the postfix array when a comma is encountered in a function's parameter list, directly preceded by another comma. blank_token represented an empty string, but was also a unique (pointer) value used to identify "omitted" parameters.
[*:2qnik7te]Change script function-calling at run-time to assign a parameter its default value if the corresponding token on the stack == &blank_token (i.e. the parameter was ,, omitted).There didn't seem to be any simple way to disallow it for required parameters, so in that case (or for built-in functions), ,, was treated as ,"",.

If the actual function were known at the point the comma is processed, it could prevent omitting of required parameters and also insert the actual default value instead of requiring the '== &blank_token' check for every parameter of every function call.

byref parameters are not local anyways.
The proposed syntax is for non-byref parameters.

It was just an example of why you'd want to perform assignment in-line. It is perfectly legitimate to do that when the parameter is not ByRef. There are also other, less important reasons not to implement syntax which can apply only to non-ByRef parameters.

Why should named ByRef parameters be excluded?

There is an easy way to avoid any conflicts with existing valid syntax: omit =.
fx(x: 4)
(This has probably been suggested before.)

#10 Sean

Sean
  • Members
  • 2462 posts

Posted 10 July 2009 - 04:32 PM

I implemented it in a private build a while back, but was reluctant to add it to AutoHotkey_L.

OK, fine, my query was a casual one anyway as the workaround is quite simple, just set simple one like "" as the default value then redirect it to the genuine one inside the function. I asked it nevertheless 'cause I sometimes felt ridiculous about I was doing.

#11 majkinetor

majkinetor
  • Fellows
  • 4511 posts

Posted 10 July 2009 - 06:26 PM

I presented my workaround here and also suggested this around 2 years ago on Developers forum.

f(p1, , p3)

I sometimes wish this, but named parameters are much much better idea. The problem with above is that you will soon have "InputBox" symptom:
InputBox(txt,,,,,,,,,,,title)

About named parameters the problem with assignment can be fixed with literals:
Fun("Name" := Name, "Pos":=6 )

since you cant assign to literal.

There are dozens of ways to do it, lets give examples on:

Declare:
1.  f(p1,p2="",Name:,Pos:=6)
2.  f(p1,p2="","Name","Pos"=6)
3.  f(p1,p2="") {					
	  params Name, Pos=6		;position is important.
   }
Use

1.  f(1,2,Name:A_Script)
2.  f(1,2,"Name"=A_Script)
3.  Can use either 1 or 2

To me, the best looking are 3+1 or 1+1

Here are some examples on 1+1:
f(p1,p2="",Name:,Pos:=6){
		if Name=
	        ;some code here
	 }
	
	f(1), f(1,2)		;as usual

   f(1, Pos:6)			;valid, p2 will take default
	f(Pos:6)			;invalid, p1 is mandatory

	f(1, Name: x ? v:k, Pos:A_Index+1)

	f(1, 2, Name, Pos)	;not using named params
	f(1, 2, Pos)		;mistake, Name is defined on third position 
	
	f(1, 2, "My Name", 6)	;all literals
	f(1, 2, "My Name", Pos:3) ;mixed, first named parameter by position, second by name.
	f(1, 2, Pos:3, Name:"My Name", Pos:6)  ;although it could be done so that last pos overrides first one, perhaps error is better idea.

	name=Pos
	value= My Name
	f(1, %Name%:Value)           ;dynamic

	InputBox, param
	fun = f
	%f%(j, %Param%:Value)      ;dynamic function with dynamic parameter


So, in short, function argument list consist of 2 parts, unnamed part that is determined by position and named part. Parts can not be mixed as constructs like the following are meaningless:
f(1,2,Name:55, 7) ; error , positional parameter after named


#12 HotKeyIt

HotKeyIt
  • Fellows
  • 6132 posts

Posted 10 July 2009 - 09:38 PM

How about that?
f("time""" . A_Now . """tick""" . A_TickCount . """var""1")

f(v=""){
	If (v)
		Loop,Parse,v,% """"
			o:= !o ? A_LoopField : ((1 and %o%:=A_LoopField ) ? "")
	MsgBox % time "`n" tick "`n" var
}
The only disadvantage is you cannot use literal "" inside your variables.
var:="test""1"
f("var""" . var) ;[color=Red]will set var to test instead test"1[/color]


#13 Sean

Sean
  • Members
  • 2462 posts

Posted 11 July 2009 - 01:00 AM

I sometimes wish this, but named parameters are much much better idea. The problem with above is that you will soon have "InputBox" symptom:

That depends on the number of parameters, of course. As I myself needed to skip just 1 or 2 parameters mostly, missing parameter is more handy to me. BTW I'm not against named parameter.

#14 SKAN

SKAN
  • Administrators
  • 9062 posts

Posted 11 July 2009 - 02:50 AM

The only disadvantage is you cannot use literal "" inside your variables.


er.. I would term it as "Limitation"

I am rewriting my InternetFileRead() and cooked up the following method ( much similar to yours ) for overriding values of static and local variables.

#SingleInstance, Force

MyFunc( "Val=0, w=1024, Text=The Quick Brown Fox, newVar=I'm New" )

MyFunc( _overrides="" ) {
 Static x=5, y=5, w=100, h=100, Count
 Name:="AutoHotkey", Type:="Scripting", Text:="qwerty", Val:=True
 
 Loop, Parse, _overrides,`,=, %A_Space%  ; Override routine for Local/Static variables
   A_Index & 1  ? (_:=A_LoopField) : (%_%:=A_LoopField)
   
[color=#808080] Listvars
 WinWaitClose, %A_ScriptFullPath%[/color]
}
The limitations are:
Var should not contain = or ,
Var name should not be _overrides or _

:)

#15 Paddy3118

Paddy3118
  • Guests

Posted 24 August 2009 - 03:48 PM

Please update http://rosettacode.o...ters#AutoHotkey with details of all the limitations of the work-alike posted.

Thanks.