Call a function: Difference between revisions
(+Haskell) |
Langurmonkey (talk | contribs) |
||
(245 intermediate revisions by more than 100 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Functions and subroutines]] |
|||
[[Category:Simple]] |
|||
The task is to demonstrate the different syntax and semantics provided for calling a function. This may include: |
|||
{{task}} |
|||
* Calling a function that requires no arguments |
|||
* Calling a function with a fixed number of arguments |
|||
* Calling a function with [[Optional parameters|optional arguments]] |
|||
* Calling a function with a [[Variadic function|variable number of arguments]] |
|||
* Calling a function with [[Named parameters|named arguments]] |
|||
* Using a function in statement context |
|||
* Using a function in [[First-class functions|first-class context]] within an expression |
|||
* Obtaining the return value of a function |
|||
* Distinguishing built-in functions and user-defined functions |
|||
* Distinguishing subroutines and functions |
|||
* Stating whether arguments are [[:Category:Parameter passing|passed]] by value or by reference |
|||
* Is partial application possible and how |
|||
;Task: |
|||
Demonstrate the different syntax and semantics provided for calling a function. |
|||
This may include: |
|||
:* Calling a function that requires no arguments |
|||
:* Calling a function with a fixed number of arguments |
|||
:* Calling a function with [[Optional parameters|optional arguments]] |
|||
:* Calling a function with a [[Variadic function|variable number of arguments]] |
|||
:* Calling a function with [[Named parameters|named arguments]] |
|||
:* Using a function in statement context |
|||
:* Using a function in [[First-class functions|first-class context]] within an expression |
|||
:* Obtaining the return value of a function |
|||
:* Distinguishing built-in functions and user-defined functions |
|||
:* Distinguishing subroutines and functions |
|||
;* Stating whether arguments are [[:Category:Parameter passing|passed]] by value or by reference |
|||
;* Is partial application possible and how |
|||
<br> |
|||
This task is ''not'' about [[Function definition|defining functions]]. |
This task is ''not'' about [[Function definition|defining functions]]. |
||
<br><bR> |
|||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">F no_args() {} |
|||
// call |
|||
no_args() |
|||
F fixed_args(x, y) |
|||
print(‘x=#., y=#.’.format(x, y)) |
|||
// call |
|||
fixed_args(1, 2) // x=1, y=2 |
|||
// named arguments |
|||
fixed_args(x' 1, y' 2) |
|||
F opt_args(x = 1) |
|||
print(x) |
|||
// calls |
|||
opt_args() // 1 |
|||
opt_args(3.141) // 3.141</syntaxhighlight> |
|||
=={{header|360 Assembly}}== |
|||
Due to assembler, argument are passed by reference.<br> |
|||
With: |
|||
<syntaxhighlight lang="360asm">X DS F |
|||
Y DS F |
|||
Z DS F</syntaxhighlight> |
|||
If you do not want to use the CALL macro instruction and for a link-edited object-module: |
|||
<syntaxhighlight lang="360asm"> L R15,=V(MULTPLIC) |
|||
LA R1,PARMLIST address of the paramter list |
|||
BALR R14,R15 branch and link |
|||
ST R0,Z Z=MULTPLIC(X,Y) |
|||
* ... |
|||
PARMLIST DC A(X) |
|||
DC A(Y)</syntaxhighlight> |
|||
If you call a link-edited object-module: |
|||
<syntaxhighlight lang="360asm"> CALL MULTPLIC,(X,Y) call MULTPLIC(X,Y) |
|||
ST R0,Z Z=MULTPLIC(X,Y)</syntaxhighlight> |
|||
If you call an load-module at execution time: |
|||
<syntaxhighlight lang="360asm"> LOAD EP=MULTPLIC load load-module |
|||
LR R15,R0 retrieve entry address |
|||
CALL (R15),(X,Y) call MULTPLIC(X,Y) |
|||
ST R0,Z Z=MULTPLIC(X,Y)</syntaxhighlight> |
|||
=={{header|6502 Assembly}}== |
|||
To call a function, you use <code>JSR</code> followed by the pointer to its beginning. Most of the time this will be a labeled line of code that your assembler will convert to an actual memory address for you during the assembly process. |
|||
<syntaxhighlight lang="6502asm">JSR myFunction</syntaxhighlight> |
|||
Function arguments are often passed in through registers, the zero page, or the stack. Given how awkward it is to work with the stack on the 6502, it's best not to use the hardware stack as a means of parameter passing. CC65 uses a software stack in the upper half of zero page, which is indexed using the X register. |
|||
<syntaxhighlight lang="6502asm">sum: |
|||
;adds the values in zero page address $00 and $01, outputs to accumulator. |
|||
LDA $00 ;load the byte stored at memory address $0000 |
|||
CLC |
|||
ADC $01 ;add the byte at memory address $0001 |
|||
RTS ;return</syntaxhighlight> |
|||
The return value is usually stored in the accumulator if it will fit in 8 bits. If not, it's often stored in a dedicated section of the zero page. Since the 6502 has very few registers and all are 8-bit, it's common to set aside a few zero page memory addresses for holding 16-bit return values. |
|||
Statements like <code>PRINT SIN(45)</code>, or expressions where you assign a variable to a function's output don't exist in assembly. You have to perform the functions individually, working from the inside out, and process them one at a time. In other words, a BASIC statement like <code>PRINT SIN(45)</code> would have to compute <code>SIN(45)</code> first, then pass the return value to <code>PRINT</code>. This is just as true with modern CPUs as it was with the 6502. |
|||
The closest thing 6502 has to true "built-in functions" are the interrupt vectors whose pointers are stored at the very end of memory. They are, in order: Non-maskable interrupt (NMI), reset, and IRQ (Interrupt Request). They are no different than other functions except they end in <code>RTI</code> rather than <code>RTS</code>. With "bare-metal programming" like on the NES this is all you have, but most computers of the 80s had some sort of kernel or operating system that had pre-defined functions you could use simply by <code>JSR</code>ing their memory address. The actual memory locations of these, and what they did, varies by implementation. |
|||
=={{header|8086 Assembly}}== |
|||
A function that requires no arguments is simply <code>CALL</code>ed: |
|||
<syntaxhighlight lang="asm">call foo</syntaxhighlight> |
|||
Functions with a fixed number of arguments have their arguments pushed onto the stack prior to the call. This is how C compilers generate 8086 assembly code. Assembly written by a person can use the stack or registers to pass arguments. Passing via registers is faster but more prone to errors and clobbering, which can cause other functions to not operate correctly. |
|||
<syntaxhighlight lang="asm">push ax ;second argument |
|||
push bx ;first argument - typically arguments are pushed in the reverse order they are listed. |
|||
call foo |
|||
pop bx |
|||
pop ax |
|||
foo: |
|||
push bp |
|||
mov bp,sp |
|||
;now bp+4 = the value pushed from BX, and bp+6 = the value pushed from AX</syntaxhighlight> |
|||
The 8086 cannot support named arguments directly. However it is possible to label a section of RAM, and use that as the argument for a function. |
|||
<syntaxhighlight lang="asm">foo: |
|||
ld ax,word ptr[ds:bar] ;load from bar, which is a 16 bit storage location in the data segment (DS), into AX</syntaxhighlight> |
|||
Built-in functions are typically called using the <code>INT</code> instruction. This instruction takes a numeric constant as its primary argument, and the value in <code>AH</code> as a selector of sorts. This command is used to exit a program and return to MS-DOS: |
|||
<syntaxhighlight lang="asm">mov AH,4Ch |
|||
mov AL,00h |
|||
int 21h</syntaxhighlight> |
|||
=={{header|68000 Assembly}}== |
|||
To call a function, you use <code>JSR</code> followed by the pointer to its beginning. Most of the time this will be a labeled line of code that your assembler will convert to an actual memory address for you during the assembly process. |
|||
<syntaxhighlight lang="68000devpac">JSR myFunction</syntaxhighlight> |
|||
Function arguments are often passed in through the stack. When looking at the function in C or a similar language that compiles to 68000 Assembly, the arguments are pushed in the reverse order they are listed. Return values typically go into the D0 register if they're 32-bit or smaller. The CPU does not enforce this, so it's up to the programmer or compiler to use calling conventions to ensure compatibility between software. |
|||
=={{header|AArch64 Assembly}}== |
|||
{{works with|as|Raspberry Pi 3B version Buster 64 bits}} |
|||
<syntaxhighlight lang="aarch64 assembly"> |
|||
/* ARM assembly AARCH64 Raspberry PI 3B */ |
|||
/* program callfonct.s */ |
|||
/*******************************************/ |
|||
/* Constantes file */ |
|||
/*******************************************/ |
|||
/* for this file see task include a file in language AArch64 assembly*/ |
|||
.include "../includeConstantesARM64.inc" |
|||
/***********************/ |
|||
/* Initialized data */ |
|||
/***********************/ |
|||
.data |
|||
szMessage: .asciz "Hello. \n" // message |
|||
szRetourLigne: .asciz "\n" |
|||
szMessResult: .asciz "Resultat : " // message result |
|||
/***********************/ |
|||
/* No Initialized data */ |
|||
/***********************/ |
|||
.bss |
|||
sZoneConv: .skip 100 |
|||
.text |
|||
.global main |
|||
main: |
|||
ldr x0,=szMessage // adresse of message short program |
|||
bl affichageMess // call function with 1 parameter (x0) |
|||
// call function with parameters in register |
|||
mov x0,#5 |
|||
mov x1,#10 |
|||
bl fonction1 // call function with 2 parameters (x0,x1) |
|||
ldr x1,qAdrsZoneConv // result in x0 |
|||
bl conversion10S // call function with 2 parameter (x0,x1) |
|||
ldr x0,=szMessResult |
|||
bl affichageMess // call function with 1 parameter (x0) |
|||
ldr x0,qAdrsZoneConv |
|||
bl affichageMess |
|||
ldr x0,qAdrszRetourLigne |
|||
bl affichageMess |
|||
// call function with parameters on stack |
|||
mov x0,#5 |
|||
mov x1,#10 |
|||
stp x0,x1,[sp,-16]! // store registers on stack |
|||
bl fonction2 // call function with 2 parameters on the stack |
|||
// result in x0 |
|||
ldr x1,qAdrsZoneConv |
|||
bl conversion10S // call function with 2 parameter (x0,x1) |
|||
ldr x0,=szMessResult |
|||
bl affichageMess // call function with 1 parameter (x0) |
|||
ldr x0,qAdrsZoneConv |
|||
bl affichageMess |
|||
ldr x0,qAdrszRetourLigne |
|||
bl affichageMess |
|||
// end of program |
|||
mov x0, #0 // return code |
|||
mov x8, #EXIT // request to exit program |
|||
svc 0 // perform the system call |
|||
qAdrsZoneConv: .quad sZoneConv |
|||
qAdrszRetourLigne: .quad szRetourLigne |
|||
/******************************************************************/ |
|||
/* call function parameter in register */ |
|||
/******************************************************************/ |
|||
/* x0 value one */ |
|||
/* x1 value two */ |
|||
/* return in x0 */ |
|||
fonction1: |
|||
stp x2,lr,[sp,-16]! // save registers |
|||
mov x2,#20 |
|||
mul x0,x0,x2 |
|||
add x0,x0,x1 |
|||
ldp x2,lr,[sp],16 // restaur 2 registres |
|||
ret // retour adresse lr x30 |
|||
/******************************************************************/ |
|||
/* call function parameter in the stack */ |
|||
/******************************************************************/ |
|||
/* return in x0 */ |
|||
fonction2: |
|||
stp fp,lr,[sp,-16]! // save registers |
|||
add fp,sp,#16 // address parameters in the stack |
|||
stp x1,x2,[sp,-16]! // save others registers |
|||
ldr x0,[fp] // second paraméter |
|||
ldr x1,[fp,#8] // first parameter |
|||
mov x2,#-20 |
|||
mul x0,x0,x2 |
|||
add x0,x0,x1 |
|||
ldp x1,x2,[sp],16 // restaur 2 registres |
|||
ldp fp,lr,[sp],16 // restaur 2 registres |
|||
add sp,sp,#16 // very important, for stack aligned |
|||
ret // retour adresse lr x30 |
|||
/********************************************************/ |
|||
/* File Include fonctions */ |
|||
/********************************************************/ |
|||
/* for this file see task include a file in language AArch64 assembly */ |
|||
.include "../includeARM64.inc" |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
<pre> |
|||
Hello. |
|||
Resultat : +110 |
|||
Resultat : -90 |
|||
</pre> |
|||
=={{header|ActionScript}}== |
=={{header|ActionScript}}== |
||
< |
<syntaxhighlight lang="actionscript"> myfunction(); /* function with no arguments in statement context */ |
||
myfunction(6,b); // function with two arguments in statement context |
myfunction(6,b); // function with two arguments in statement context |
||
stringit("apples"); //function with a string argument</ |
stringit("apples"); //function with a string argument</syntaxhighlight> |
||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
* Ada provides two kinds of subroutines: procedures |
* Ada provides two kinds of subroutines: procedures without return values and functions with return values. The return values of functions must be used by the callers. If you don't want to deal with the return value, call a procedure instead. |
||
* As a rule of thumb, an Ada compiler is free to pass arguments either by value or by reference. Parameters have a mode |
* As a rule of thumb, an Ada compiler is free to pass arguments either by value or by reference. Parameters have a mode however: either 'in' or 'out' or 'in out'. It is prohibited to write anything to an 'in' parameter. The next language Standard, Ada 2012, will support functions with 'out' and 'in out' mode parameters, so far, only procedures could have parameters with non-'in' modes. So any of the following statements for Ada functions holds for Ada procedures as well. |
||
* There are no differences |
* There are no differences between calling built-in vs. user defined functions. |
||
* Functions without parameters can be called by omitting the parameter list (no empty brackets!):<lang |
* Functions without parameters can be called by omitting the parameter list (no empty brackets!):<syntaxhighlight lang="ada">S: String := Ada.Text_IO.Get_Line;</syntaxhighlight> |
||
* Ada supports functions with optional parameters:< |
* Ada supports functions with optional parameters:<syntaxhighlight lang="ada">function F(X: Integer; Y: Integer := 0) return Integer; -- Y is optional |
||
... |
... |
||
A : Integer := F(12); |
A : Integer := F(12); |
||
B : Integer := F(12, 0); -- the same as A |
B : Integer := F(12, 0); -- the same as A |
||
C : Integer := F(12, 1); -- something different</ |
C : Integer := F(12, 1); -- something different</syntaxhighlight> |
||
* If the number of parameters of F |
* If the number of parameters of F were fixed to two (by omitting the ":= 0" in the specification), then B and C would be OK, but A wouldn't. |
||
* Ada does not support functions with a variable number of arguments. But a function argument can be an unconstrained array with as many values as you want:< |
* Ada does not support functions with a variable number of arguments. But a function argument can be an unconstrained array with as many values as you want:<syntaxhighlight lang="ada">type Integer_Array is array (Positive range <>) of Integer; |
||
function Sum(A: Integer_Array) return Integer is |
function Sum(A: Integer_Array) return Integer is |
||
S: Integer := 0; |
S: Integer := 0; |
||
Line 51: | Line 262: | ||
... |
... |
||
A := Sum((1,2,3)); -- A = 6 |
A := Sum((1,2,3)); -- A = 6 |
||
B := Sum((1,2,3,4)); -- B = 10</ |
B := Sum((1,2,3,4)); -- B = 10</syntaxhighlight> |
||
* One can realize first-class functions by defining an access to a function as a parameter:< |
* One can realize first-class functions by defining an access to a function as a parameter:<syntaxhighlight lang="ada">function H (Int: Integer; |
||
Fun: not null access function (X: Integer; Y: Integer) |
Fun: not null access function (X: Integer; Y: Integer) |
||
return Integer); |
return Integer); |
||
Line 61: | Line 272: | ||
X := H(A, F'Access) -- assuming X and A are Integers, and F is a function |
X := H(A, F'Access) -- assuming X and A are Integers, and F is a function |
||
-- taking two Integers and returning an Integer.</ |
-- taking two Integers and returning an Integer.</syntaxhighlight> |
||
* The caller is free to use either |
* The caller is free to use either positional parameters or named parameters, or a mixture of both (with positional parameters first) <syntaxhighlight lang="ada">Positional := H(A, F'Access); |
||
Named := H(Int => A, Fun => F'Access); |
Named := H(Int => A, Fun => F'Access); |
||
Mixed := H(A, Fun=>F'Access); </ |
Mixed := H(A, Fun=>F'Access); </syntaxhighlight> |
||
=={{header|ALGOL 68}}== |
|||
<syntaxhighlight lang="algol68"># Note functions and subroutines are called procedures (or PROCs) in Algol 68 # |
|||
# A function called without arguments: # |
|||
f; |
|||
# Algol 68 does not expect an empty parameter list for calls with no arguments, "f()" is a syntax error # |
|||
# A function with a fixed number of arguments: # |
|||
f(1, x); |
|||
# variable number of arguments: # |
|||
# functions that accept an array as a parameter can effectively provide variable numbers of arguments # |
|||
# a "literal array" (called a row-display in Algol 68) can be passed, as is often the case for the I/O # |
|||
# functions - e.g.: # |
|||
print( ( "the result is: ", r, " after ", n, " iterations", newline ) ); |
|||
# the outer brackets indicate the parameters of print, the inner brackets indicates the contents are a "literal array" # |
|||
# ALGOL 68 does not support optional arguments, though in some cases an empty array could be passed to a function # |
|||
# expecting an array, e.g.: # |
|||
f( () ); |
|||
# named arguments - see the Algol 68 sample in: http://rosettacode.org/wiki/Named_parameters # |
|||
# In "Talk:Call a function" a statement context is explained as |
|||
"The function is used as an instruction (with a void context), |
|||
rather than used within an expression." |
|||
Based on that, the examples above are already in a statement context. |
|||
Technically, when a function that returns other than VOID (i.e. is not a subroutine) |
|||
is called in a statement context, the result of the call is "voided" i.e. discarded. |
|||
If desired, this can be made explicit using a cast, e.g.: # |
|||
VOID(f); |
|||
# A function's return value being used: # |
|||
x := f(y); |
|||
# There is no distinction between built-in functions and user-defined functions. # |
|||
# A subroutine is simply a function that returns VOID. # |
|||
# If the function is declared with argument(s) of mode REF MODE, |
|||
then those arguments are being passed by reference. # |
|||
# Technically, all parameters are passed by value, however the value of a REF MODE is a reference... #</syntaxhighlight> |
|||
See [http://rosettacode.org/wiki/First-class_functions#ALGOL_68 First-Class Functions] for an example of first-class functions in ALGOL 68.<br> |
|||
See [http://rosettacode.org/wiki/Partial_function_application#ALGOL_68 Partial Function Application] for an example of partial function application in ALGOL 68.<br> |
|||
See [http://rosettacode.org/wiki/Optional_parameters#ALGOL_68 Optional Parameters] for an example of optional parameters in Algol 68.<br> |
|||
See [http://rosettacode.org/wiki/Named_parameters#ALGOL_68 Named Parameters] for an example of named parameters in Algol 68. |
|||
=={{header|ALGOL W}}== |
|||
<syntaxhighlight lang="algolw">% Note, in Algol W, functions are called procedures % |
|||
% calling a function with no parameters: % |
|||
f; |
|||
% calling a function with a fixed number of parameters % |
|||
g( 1, 2.3, "4" ); |
|||
% Algol W does not support optional parameters in general, however constructors for records can % |
|||
% be called wither with parameters (one for each field in the record) or no parameters # |
|||
% Algol W does not support variable numbers of parameters, except for the built-in I/O functions # |
|||
% Algol W does not support named arguments % |
|||
% A function can be used in a statement context by calling it, as in the examples above % |
|||
% First class context: A function can be passed as a parameter to another procedure, e.g.: % |
|||
v := integrate( sin, 0, 1 ) |
|||
% assuming a suitable definition of integrate % |
|||
% Algol W does not support functions returning functions % |
|||
% obtaining the return value of a function: e.g.: % |
|||
v := g( x, y, z ); |
|||
% There is no syntactic distinction between user-defined and built-in functions % |
|||
% Subroutines and functions are both procedures, a subroutine is a procedure with no return type % |
|||
% (called a proper procedure in Algol W) % |
|||
% There is no syntactic distinction between a call to a function and a call to a subroutine % |
|||
% other than the context % |
|||
% In Algol W, parameters are passed by value, result or value result. This must be stated in the % |
|||
% definition of the function/subroutine. Value parameters are passed by value, result and value result % |
|||
% are effectively passed by reference and assigned on function exit. Result parameters are "out" parameters % |
|||
% and value result parameters are "in out". % |
|||
% Algol W also has "name" parameters (not to be confused with named parameters). Functions with name % |
|||
% parameters are somewhat like macros % |
|||
% Partial application is not possible in Algol W %</syntaxhighlight> |
|||
=={{header|AntLang}}== |
|||
AntLang provides two ways to apply a function. |
|||
One way is infix application. |
|||
<syntaxhighlight lang="antlang">2*2+9</syntaxhighlight> |
|||
Infix application is right associative, so x f y g z means x f (y g z) and not (x f y) g z. |
|||
You can break this rule using parenthesis. |
|||
The other way is prefix application. |
|||
<syntaxhighlight lang="antlang">*[2;+[2;9]] |
|||
echo["Hello!"] |
|||
time[]</syntaxhighlight> |
|||
=={{header|ARM Assembly}}== |
|||
{{works with|as|Raspberry Pi}} |
|||
<syntaxhighlight lang="arm assembly"> |
|||
/* ARM assembly Raspberry PI */ |
|||
/* program callfonct.s */ |
|||
/* Constantes */ |
|||
.equ STDOUT, 1 |
|||
.equ WRITE, 4 |
|||
.equ EXIT, 1 |
|||
/***********************/ |
|||
/* Initialized data */ |
|||
/***********************/ |
|||
.data |
|||
szMessage: .asciz "Hello. \n" @ message |
|||
szRetourLigne: .asciz "\n" |
|||
szMessResult: .ascii "Resultat : " @ message result |
|||
sMessValeur: .fill 12, 1, ' ' |
|||
.asciz "\n" |
|||
/***********************/ |
|||
/* No Initialized data */ |
|||
/***********************/ |
|||
.bss |
|||
iValeur: .skip 4 @ reserve 4 bytes in memory |
|||
.text |
|||
.global main |
|||
main: |
|||
ldr r0,=szMessage @ adresse of message short program |
|||
bl affichageMess @ call function with 1 parameter (r0) |
|||
@ call function with parameters in register |
|||
mov r0,#5 |
|||
mov r1,#10 |
|||
bl fonction1 @ call function with 2 parameters (r0,r1) |
|||
ldr r1,=sMessValeur @ result in r0 |
|||
bl conversion10S @ call function with 2 parameter (r0,r1) |
|||
ldr r0,=szMessResult |
|||
bl affichageMess @ call function with 1 parameter (r0) |
|||
@ call function with parameters on stack |
|||
mov r0,#5 |
|||
mov r1,#10 |
|||
push {r0,r1} |
|||
bl fonction2 @ call function with 2 parameters on the stack |
|||
@ result in r0 |
|||
ldr r1,=sMessValeur |
|||
bl conversion10S @ call function with 2 parameter (r0,r1) |
|||
ldr r0,=szMessResult |
|||
bl affichageMess @ call function with 1 parameter (r0) |
|||
/* end of program */ |
|||
mov r0, #0 @ return code |
|||
mov r7, #EXIT @ request to exit program |
|||
swi 0 @ perform the system call |
|||
/******************************************************************/ |
|||
/* call function parameter in register */ |
|||
/******************************************************************/ |
|||
/* r0 value one */ |
|||
/* r1 value two */ |
|||
/* return in r0 */ |
|||
fonction1: |
|||
push {fp,lr} /* save des 2 registres */ |
|||
push {r1,r2} /* save des autres registres */ |
|||
mov r2,#20 |
|||
mul r0,r2 |
|||
add r0,r0,r1 |
|||
pop {r1,r2} /* restaur des autres registres */ |
|||
pop {fp,lr} /* restaur des 2 registres */ |
|||
bx lr /* retour procedure */ |
|||
/******************************************************************/ |
|||
/* call function parameter in the stack */ |
|||
/******************************************************************/ |
|||
/* return in r0 */ |
|||
fonction2: |
|||
push {fp,lr} /* save des 2 registres */ |
|||
add fp,sp,#8 /* address parameters in the stack*/ |
|||
push {r1,r2} /* save des autres registres */ |
|||
ldr r0,[fp] |
|||
ldr r1,[fp,#4] |
|||
mov r2,#-20 |
|||
mul r0,r2 |
|||
add r0,r0,r1 |
|||
pop {r1,r2} /* restaur des autres registres */ |
|||
pop {fp,lr} /* restaur des 2 registres */ |
|||
add sp,#8 /* very important, for stack aligned */ |
|||
bx lr /* retour procedure */ |
|||
/******************************************************************/ |
|||
/* affichage des messages avec calcul longueur */ |
|||
/******************************************************************/ |
|||
/* r0 contient l adresse du message */ |
|||
affichageMess: |
|||
push {fp,lr} /* save des 2 registres */ |
|||
push {r0,r1,r2,r7} /* save des autres registres */ |
|||
mov r2,#0 /* compteur longueur */ |
|||
1: /*calcul de la longueur */ |
|||
ldrb r1,[r0,r2] /* recup octet position debut + indice */ |
|||
cmp r1,#0 /* si 0 c est fini */ |
|||
beq 1f |
|||
add r2,r2,#1 /* sinon on ajoute 1 */ |
|||
b 1b |
|||
1: /* donc ici r2 contient la longueur du message */ |
|||
mov r1,r0 /* adresse du message en r1 */ |
|||
mov r0,#STDOUT /* code pour écrire sur la sortie standard Linux */ |
|||
mov r7, #WRITE /* code de l appel systeme 'write' */ |
|||
swi #0 /* appel systeme */ |
|||
pop {r0,r1,r2,r7} /* restaur des autres registres */ |
|||
pop {fp,lr} /* restaur des 2 registres */ |
|||
bx lr /* retour procedure */ |
|||
/***************************************************/ |
|||
/* conversion registre en décimal signé */ |
|||
/***************************************************/ |
|||
/* r0 contient le registre */ |
|||
/* r1 contient l adresse de la zone de conversion */ |
|||
conversion10S: |
|||
push {fp,lr} /* save des 2 registres frame et retour */ |
|||
push {r0-r5} /* save autres registres */ |
|||
mov r2,r1 /* debut zone stockage */ |
|||
mov r5,#'+' /* par defaut le signe est + */ |
|||
cmp r0,#0 /* nombre négatif ? */ |
|||
movlt r5,#'-' /* oui le signe est - */ |
|||
mvnlt r0,r0 /* et inversion en valeur positive */ |
|||
addlt r0,#1 |
|||
mov r4,#10 /* longueur de la zone */ |
|||
1: /* debut de boucle de conversion */ |
|||
bl divisionpar10 /* division */ |
|||
add r1,#48 /* ajout de 48 au reste pour conversion ascii */ |
|||
strb r1,[r2,r4] /* stockage du byte en début de zone r5 + la position r4 */ |
|||
sub r4,r4,#1 /* position précedente */ |
|||
cmp r0,#0 |
|||
bne 1b /* boucle si quotient different de zéro */ |
|||
strb r5,[r2,r4] /* stockage du signe à la position courante */ |
|||
subs r4,r4,#1 /* position précedente */ |
|||
blt 100f /* si r4 < 0 fin */ |
|||
/* sinon il faut completer le debut de la zone avec des blancs */ |
|||
mov r3,#' ' /* caractere espace */ |
|||
2: |
|||
strb r3,[r2,r4] /* stockage du byte */ |
|||
subs r4,r4,#1 /* position précedente */ |
|||
bge 2b /* boucle si r4 plus grand ou egal a zero */ |
|||
100: /* fin standard de la fonction */ |
|||
pop {r0-r5} /*restaur des autres registres */ |
|||
pop {fp,lr} /* restaur des 2 registres frame et retour */ |
|||
bx lr |
|||
/***************************************************/ |
|||
/* division par 10 signé */ |
|||
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/* |
|||
/* and http://www.hackersdelight.org/ */ |
|||
/***************************************************/ |
|||
/* r0 contient le dividende */ |
|||
/* r0 retourne le quotient */ |
|||
/* r1 retourne le reste */ |
|||
divisionpar10: |
|||
/* r0 contains the argument to be divided by 10 */ |
|||
push {r2-r4} /* save autres registres */ |
|||
mov r4,r0 |
|||
ldr r3, .Ls_magic_number_10 /* r1 <- magic_number */ |
|||
smull r1, r2, r3, r0 /* r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0) */ |
|||
mov r2, r2, ASR #2 /* r2 <- r2 >> 2 */ |
|||
mov r1, r0, LSR #31 /* r1 <- r0 >> 31 */ |
|||
add r0, r2, r1 /* r0 <- r2 + r1 */ |
|||
add r2,r0,r0, lsl #2 /* r2 <- r0 * 5 */ |
|||
sub r1,r4,r2, lsl #1 /* r1 <- r4 - (r2 * 2) = r4 - (r0 * 10) */ |
|||
pop {r2-r4} |
|||
bx lr /* leave function */ |
|||
.align 4 |
|||
.Ls_magic_number_10: .word 0x66666667 |
|||
</syntaxhighlight> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="rebol">printHello: $[][ |
|||
print "Hello World!" |
|||
] |
|||
sayHello: $[name][ |
|||
print ["Hello" name "!"] |
|||
] |
|||
printAll: $[args][ |
|||
loop args [arg][ |
|||
print arg |
|||
] |
|||
] |
|||
getNumber: $[][3] |
|||
; Calling a function that requires no arguments |
|||
printHello |
|||
; Calling a function with a fixed number of arguments |
|||
sayHello "John" |
|||
; Calling a function with a variable number of arguments |
|||
printAll ["one" "two" "three"] |
|||
; Using a function in statement context |
|||
if true [printHello] |
|||
print getNumber |
|||
; Using a function in first-class context within an expression |
|||
if getNumber=3 [print "yep, it worked"] |
|||
; Obtaining the return value of a function: |
|||
num: getNumber |
|||
print num |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Hello World! |
|||
Hello John ! |
|||
one |
|||
two |
|||
three |
|||
Hello World! |
|||
3 |
|||
yep, it worked |
|||
3</pre> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="ahk">; Call a function without arguments: |
||
f() |
f() |
||
Line 107: | Line 638: | ||
; Partial application is impossible. |
; Partial application is impossible. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
The awk interpreter reads the entire script prior to processing, so functions can be called from sections of code appearing before the definition. |
The awk interpreter reads the entire script prior to processing, so functions can be called from sections of code appearing before the definition. |
||
< |
<syntaxhighlight lang="awk">BEGIN { |
||
sayhello() # Call a function with no parameters in statement context |
sayhello() # Call a function with no parameters in statement context |
||
b=squareit(3) # Obtain the return value from a function with a single parameter in first class context |
b=squareit(3) # Obtain the return value from a function with a single parameter in first class context |
||
}</ |
}</syntaxhighlight> |
||
In awk, scalar values are passed by value, but arrays are passed by reference. Note that if a function has no arguments, then empty parentheses are required. |
In awk, scalar values are passed by value, but arrays are passed by reference. Note that if a function has no arguments, then empty parentheses are required. |
||
The awk extraction and reporting language does not support the use of named parameters. |
The awk extraction and reporting language does not support the use of named parameters. |
||
=={{header|Axe}}== |
|||
In Axe, up to six arguments are passed as the variables r₁ through r₆. As with all variables in Axe, these exist in the global scope, which makes nested function calls and recursion quite difficult. |
|||
<syntaxhighlight lang="axe">NOARG() |
|||
ARGS(1,5,42)</syntaxhighlight> |
|||
Since arguments are simply global variables, they are always optional and can be omitted from right to left. |
|||
<syntaxhighlight lang="axe">OPARG(1,2,3,4,5,6) |
|||
OPARG(1,2,3) |
|||
OPARG()</syntaxhighlight> |
|||
Somewhat similar to [[TI-83 BASIC]], the last evaluated expression becomes the return value of the function. However, this is distinct from the Ans variable. Return values can be captured just like any other expression. |
|||
<syntaxhighlight lang="axe">MATHS(2,4)→A |
|||
Disp GETSTR()</syntaxhighlight> |
|||
User-defined functions can be distinguished from language-defined functions by the fact that language-defined function names are composed of atomic tokens (usually with built-in parentheses) whereas user-defined function names are composed of individual characters. Also, because only uppercase letters are available by default in the OS, most user-defined names are all uppercase while language-defined names are mixed case. |
|||
<syntaxhighlight lang="axe">USER() |
|||
axeFunc()</syntaxhighlight> |
|||
=={{header|BASIC}}== |
|||
==={{header|BASIC256}}=== |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="basic256">function Copialo$ (txt$, siNo, final$) |
|||
nuevaCadena$ = "" |
|||
for cont = 1 to siNo |
|||
nuevaCadena$ += txt$ |
|||
next cont |
|||
return trim(nuevaCadena$) + final$ |
|||
end function |
|||
subroutine Saludo() |
|||
print "Hola mundo!" |
|||
end subroutine |
|||
subroutine testCadenas (txt$) |
|||
for cont = 1 to length(txt$) |
|||
print mid(txt$, cont, 1); ""; |
|||
next cont |
|||
end subroutine |
|||
subroutine testNumeros (a, b, c) |
|||
print a, b, c |
|||
end subroutine |
|||
call Saludo() |
|||
print Copialo$("Saludos ", 6, "") |
|||
print Copialo$("Saludos ", 3, "!!") |
|||
print |
|||
call testNumeros(1, 2, 3) |
|||
call testNumeros(1, 2, 0) |
|||
print |
|||
call testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \#incluye texto\#") |
|||
end</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Igual que la entrada de FreeBASIC. |
|||
</pre> |
|||
=={{header|Batch File}}== |
|||
Batch files do not have a traditional "function" system like OOP languages, however this is the closest thing to it. The only difference between a block of code and a function is the way method you choose to invoke it. It's also worth noting that all batch files can be called from any other batch file, performing a function. A function should be put somewhere in the code where it will not be parsed unless the script is redirected there. |
|||
<syntaxhighlight lang="dos"> |
|||
:: http://rosettacode.org/wiki/Call_a_function |
|||
:: Demonstrate the different syntax and semantics provided for calling a function. |
|||
@echo off |
|||
echo Calling myFunction1 |
|||
call:myFunction1 |
|||
echo. |
|||
echo Calling myFunction2 11 8 |
|||
call:myFunction2 11 8 |
|||
echo. |
|||
echo Calling myFunction3 /fi and saving the output into %%filecount%% |
|||
call:myFunction3 /fi |
|||
echo.%filecount% |
|||
echo. |
|||
echo Calling myFunction4 1 2 3 4 5 |
|||
call:myFunction4 1 2 3 4 5 |
|||
echo. |
|||
echo Calling myFunction5 "filename=test.file" "filepath=C:\Test Directory\" |
|||
call:myFunction5 "filename=test.file" "filepath=C:\Test Directory\" |
|||
echo. |
|||
echo Calling myFunction5 "filepath=C:\Test Directory\" "filename=test.file" |
|||
call:myFunction5 "filepath=C:\Test Directory\" "filename=test.file" |
|||
echo. |
|||
pause>nul |
|||
exit |
|||
:: Requires no arguments |
|||
:myFunction1 |
|||
echo myFunction1 has been called. |
|||
goto:eof |
|||
:: Fixed number of arguments (%a% & %b%) |
|||
:myFunction2 |
|||
:: Returns %a% + %b% |
|||
setlocal |
|||
set /a c=%~1+%~2 |
|||
endlocal & echo %c% |
|||
goto:eof |
|||
:: Optional arguments |
|||
:myFunction3 |
|||
:: Returns the amount of folders + files in the current directory |
|||
:: /fi Returns only file count |
|||
:: /fo Returns only folder count |
|||
setlocal |
|||
set count=0 |
|||
if "%~1"=="" set "command=dir /b" |
|||
if "%~1"=="/fi" set "command=dir /b /A-d" |
|||
if "%~1"=="/fo" set "command=dir /b /Ad" |
|||
for /f "usebackq" %%i in (`%command%`) do set /a count+=1 |
|||
endlocal & set filecount=%count% |
|||
goto:eof |
|||
:: Variable number of arguments |
|||
:myFunction4 |
|||
:: Returns sum of arguments |
|||
setlocal |
|||
:myFunction4loop |
|||
set sum=0 |
|||
for %%i in (%*) do set /a sum+=%%i |
|||
endlocal & echo %sum% |
|||
goto:eof |
|||
:: Named Arguments (filepath=[path] & filename=[name]) |
|||
:myFunction5 |
|||
:: Returns the complete path based off the 2 arguments |
|||
if "%~1"=="" then goto:eof |
|||
setlocal enabledelayedexpansion |
|||
set "param=%~1" |
|||
for /l %%i in (1,1,2) do ( |
|||
for /f "tokens=1,2 delims==" %%j in ("!param!") do set %%j=%%k |
|||
set "param=%~2" |
|||
) |
|||
endlocal & echo.%filepath%%filename% |
|||
goto:eof |
|||
</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
Calling myFunction1 |
|||
myFunction1 has been called. |
|||
Calling myFunction2 11 8 |
|||
19 |
|||
Calling myFunction3 /fi and saving the output into %filecount% |
|||
1 |
|||
Calling myFunction4 1 2 3 4 5 |
|||
15 |
|||
Calling myFunction5 "filename=test.file" "filepath=C:\Test Directory\" |
|||
C:\Test Directory\test.file |
|||
Calling myFunction5 "filepath=C:\Test Directory\" "filename=test.file" |
|||
C:\Test Directory\test.file |
|||
</pre> |
|||
=={{header|BBC BASIC}}== |
|||
BBC BASIC distinguishes between functions (which return one value), procedures (which may return an arbitrary number of values including zero), and subroutines. Functions can be built-in or user-defined. |
|||
A call to a <b>built-in function</b> (for example, the square root function) is an expression: |
|||
<syntaxhighlight lang="bbcbasic">PRINT SQR(2)</syntaxhighlight> |
|||
The parentheses can often be omitted: |
|||
<syntaxhighlight lang="bbcbasic">PRINT SQR 2</syntaxhighlight> |
|||
The name of a <b>user-defined function</b> must begin with <tt>FN</tt>. A call to it is also an expression: |
|||
<syntaxhighlight lang="bbcbasic">PRINT FN_foo(bar$, baz%)</syntaxhighlight> |
|||
(The sigils <tt>$</tt> and <tt>%</tt> identify the variables' types.) |
|||
A function that takes no arguments can be called omitting the parentheses: |
|||
<syntaxhighlight lang="bbcbasic">PRINT FN_foo</syntaxhighlight> |
|||
The name of a <b>procedure</b> must begin with <tt>PROC</tt>. A call to it is a statement, not an expression: |
|||
<syntaxhighlight lang="bbcbasic">PROC_foo</syntaxhighlight> |
|||
If it has arguments, they come in parentheses just as with a function: |
|||
<syntaxhighlight lang="bbcbasic">PROC_foo(bar$, baz%, quux)</syntaxhighlight> |
|||
Note that you <i>cannot tell from this syntax</i> which of the variables <tt>bar$</tt>, <tt>baz%</tt>, and <tt>quux</tt> are arguments provided to the procedure and which of them are return values from it. You have to look at where it is defined: |
|||
<syntaxhighlight lang="bbcbasic">DEF PROC_foo(a$, RETURN b%, RETURN c)</syntaxhighlight> |
|||
<b>Subroutines</b> are provided for compatibility with older, unstructured dialects of BASIC; otherwise they are never really used. They require statements to be numbered, and they can neither receive arguments nor return values: they can only manipulate global variables. The <tt>GOSUB</tt> and <tt>RETURN</tt> statements in fact mirror assembly language 'jump to subroutine' and 'return from subroutine' instructions quite closely. |
|||
<syntaxhighlight lang="bbcbasic">200 GOSUB 30050</syntaxhighlight> |
|||
=={{header|Binary Lambda Calculus}}== |
|||
Function calling is the sole primitive in the Lambda Calculus. The application of function f on argument a is denoted 01 f a in Binary Lambda Calculus. Multi argument functions are achieved by currying, i.e. a function of the first argument returns a function of the 2nd argument, etc. A good example is the Church numeral 2, which given a function f and an argument x, applies f twice on x: C2 = \f. \x. f (f x). This is written in BLC as |
|||
<pre>00 00 01 110 01 110 01</pre> |
|||
=={{header|BQN}}== |
|||
BQN's functions take one or two arguments, and the behave like the primitive functions of the language. |
|||
'''Calling a function that requires no arguments:''' BQN does not have zero argument functions. Having a function that does so is done with the help of a dummy argument, like so: |
|||
<syntaxhighlight lang="bqn">{𝕊 ·: 1 + 1}0</syntaxhighlight> |
|||
The dot symbol <code>·</code> indicates that the argument is nothing, and hence is discarded. Hence, the zero provided to it is discarded, and 1 + 1 = 2 is returned. |
|||
'''Calling a function with a fixed number of arguments:''' BQN functions always take 1 or two arguments, and their names must always start with a capital letter. A function is called like a primitive function, by writing its name or the function itself between the arguments. For example, given a function named <code>F</code>: |
|||
<syntaxhighlight lang="bqn">F 1</syntaxhighlight> is an example of a single argument call. |
|||
<syntaxhighlight lang="bqn">2 F 1</syntaxhighlight> is an example of a two argument call. |
|||
'''Calling a function with optional arguments:''' optional arguments are not supported by BQN. |
|||
'''Calling a function with a variable number of arguments:''' A function supporting variable arguments can be made by taking an array as any of the arguments. |
|||
'''Calling a function with named arguments:''' BQN has block headers, which destructure an input array into given variables using pattern matching. These can then be referenced later by the names given. |
|||
<syntaxhighlight lang="bqn">{ |
|||
𝕊 one‿two‿three: |
|||
one∾two∾three |
|||
}</syntaxhighlight> |
|||
Given a three element array, the above example will concatenate them all together. |
|||
'''Using a function in statement context:''' BQN user defined functions have the same syntactic roles as primitive functions in an expression, so they can be used like any primitive. |
|||
<syntaxhighlight lang="bqn">1 {𝕨+𝕩} 2</syntaxhighlight> |
|||
is the same as |
|||
<syntaxhighlight lang="bqn">1 + 2</syntaxhighlight> |
|||
'''Using a function in first-class context within an expression:''' BQN supports lisp-style functional programming, and hence supports first class usage of functions. |
|||
<syntaxhighlight lang="bqn">⟨+, -, ∾⟩</syntaxhighlight> |
|||
is an example of a list of functions, which can later be called with the help of a higher order function. |
|||
'''Obtaining the return value of a function:''' A block function will always return the value of the last statement within it. To obtain the return value of a function, you can assign it to a variable, or modify an existing variable with the return value. |
|||
<syntaxhighlight lang="bqn">var ← Func # insert arg here</syntaxhighlight> |
|||
Arguments are passed to BQN functions by value only. |
|||
'''Partial Application:''' BQN has two combinators for this purpose. Before (<code>⊸</code>) returns a function with a constant left argument, and After (<code>⟜</code>) returns a function with a constant right argument. |
|||
<syntaxhighlight lang="bqn">+⟜2</syntaxhighlight> will add two to the number given to it. |
|||
<syntaxhighlight lang="bqn">2⊸-</syntaxhighlight> will subtract its input from two. |
|||
=={{header|Bracmat}}== |
|||
* Calling a function that requires no arguments: |
|||
Strictly speaking, all Bracmat functions receive at least one argument. But empty strings are valid expressions, so you can do |
|||
<syntaxhighlight lang="bracmat">aFunctionWithoutArguments$</syntaxhighlight> |
|||
or |
|||
<syntaxhighlight lang="bracmat">aFunctionWithoutArguments'</syntaxhighlight> |
|||
Both function calls pass the right and side of the <code>$</code> or <code>'</code> operator. This is in fact still something: an empty string. |
|||
The <code>$</code> operator always evaluates its right hand side before passing it to the function, while the <code>'</code> does not. Therefore it is slightly faster to use the <code>functionName'</code> variant. |
|||
* Calling a function with a fixed number of arguments: |
|||
Bracmat passes exactly one argument to a function, called <code>arg</code>. The argument can be any Bracmat expression. In patterns, if a function call expression is a pattern component, a second argument <code>sjt</code> is added, the part of the subject that the pattern component is going trying to match. |
|||
* Calling a function with optional arguments |
|||
There is no special syntax for that. It is up to the programmer to define a datastructure with a variable part, e.g., a list. |
|||
* Calling a function with a variable number of arguments |
|||
Same answer. |
|||
* Calling a function with named arguments |
|||
There is no special syntax for that. You could pass a list of (name.value) pairs. |
|||
* Using a function in statement context |
|||
A f... |
|||
You can do |
|||
<syntaxhighlight lang="bracmat">func$!myargument;</syntaxhighlight> |
|||
The <code>;</code> marks the end of a Bracmat statement. |
|||
* Using a function in first-class context within an expression |
|||
(Copied from JavaScript:) Bracmat functions are first-class citizens; they can be stored in variables and passed as arguments. Assigning to a variable <code>yourfunc</code> can be done in a few ways. The most common one is |
|||
<syntaxhighlight lang="bracmat">(yourfunc=local vars.function body)</syntaxhighlight> |
|||
If there is already a function <code>myfunc</code> that you want to assign to <code>yourfunc</code> as well, do |
|||
<syntaxhighlight lang="bracmat">('$myfunc:(=?yourfunc))</syntaxhighlight> |
|||
* Obtaining the return value of a function |
|||
<syntaxhighlight lang="bracmat">myfunc$!myarg:?myresult</syntaxhighlight> |
|||
Notice that the returned value can be any evaluated expression. |
|||
* Distinguishing built-in functions and user-defined functions |
|||
You cannot list built-in functions that are implemented directly in C. Nor can such functions be passed as arguments or assigned to variables. There are also a number of built-in functions that are written in Bracmat. They are nothing special and can be deleted or redefined. You can see a list of all currently defined functions that are written in Bracmat with the function call <code>cat'</code>. |
|||
* Distinguishing subroutines and functions |
|||
You can ignore the return value of a function <code>myfunc</code> as follows: |
|||
<syntaxhighlight lang="bracmat">myfunc$!myarg&yourfunc$!yourarg</syntaxhighlight> |
|||
But notice that if <code>myfunc</code> fails, the above expression returns the value produced by <code>myfunc</code>! To also ignore the success/failure of a function, do |
|||
<syntaxhighlight lang="bracmat">`(myfunc$!myarg)&yourfunc$!yourarg</syntaxhighlight> |
|||
* Stating whether arguments are passed by value or by reference |
|||
Values are passed by reference, or by value if the reference counter, which is a very small integer, overflows. Most values are immutable, so for those there is no practical difference between passing by reference or value. The single exception of a mutable value is always passed by reference, and has an enormous reference counter. (The binary operator <code>=</code> introduces a mutable value and can be used for an object oriented style of programming.) |
|||
* Is partial application possible and how |
|||
There is no special syntax for that, but you can write a function that e.g., can take a list with one or with two elements and that returns a function in the first case. |
|||
<syntaxhighlight lang="bracmat">( ( plus |
|||
= a b |
|||
. !arg:%?a ?b |
|||
& !b: |
|||
& '(.!arg+$a) |
|||
| !a+!b |
|||
) |
|||
& out$("1+2, not partial:" plus$(1 2)) |
|||
& out$("1+2, partial:" (plus$1)$2) |
|||
);</syntaxhighlight> |
|||
Output: |
|||
<pre>1+2, not partial: 3 |
|||
1+2, partial: 3</pre> |
|||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">/* function with no argument */ |
||
f(); |
f(); |
||
Line 155: | Line 1,019: | ||
h(1, 2, 3, 4, "abcd", (void*)0); |
h(1, 2, 3, 4, "abcd", (void*)0); |
||
/* named arguments: |
/* named arguments: this is only possible through some pre-processor abuse |
||
*/ |
|||
/* statement context: is that a real phrase? */ |
|||
struct v_args { |
|||
int arg1; |
|||
int arg2; |
|||
char _sentinel; |
|||
}; |
|||
void _v(struct v_args args) |
|||
{ |
|||
printf("%d, %d\n", args.arg1, args.arg2); |
|||
} |
|||
#define v(...) _v((struct v_args){__VA_ARGS__}) |
|||
v(.arg2 = 5, .arg1 = 17); // prints "17,5" |
|||
/* NOTE the above implementation gives us optional typesafe optional arguments as well (unspecified arguments are initialized to zero)*/ |
|||
v(.arg2=1); // prints "0,1" |
|||
v(); // prints "0,0" |
|||
/* as a first-class object (i.e. function pointer) */ |
/* as a first-class object (i.e. function pointer) */ |
||
Line 170: | Line 1,051: | ||
/* Scalar values are passed by value by default. However, arrays are passed by reference. */ |
/* Scalar values are passed by value by default. However, arrays are passed by reference. */ |
||
/* Pointers *sort of* work like references, though. */</ |
/* Pointers *sort of* work like references, though. */</syntaxhighlight> |
||
=={{header|C sharp|C#}}== |
|||
<syntaxhighlight lang="c sharp"> |
|||
/* a function that has no argument */ |
|||
public int MyFunction(); |
|||
/* a function with a fixed number of arguments */ |
|||
FunctionWithArguments(4, 3, 2); |
|||
/* a function with optional arguments */ |
|||
public void OptArg(); |
|||
public static void Main() |
|||
{ |
|||
OptArg(1); |
|||
OptArg(1, 2); |
|||
OptArg(1, 2, 3); |
|||
} |
|||
public void ExampleMethod(int required, |
|||
string optionalstr = "default string", |
|||
int optionalint = 10) |
|||
/* If you know the first and the last parameter */ |
|||
ExampleMethod(3, optionalint: 4); |
|||
/* If you know all the parameter */ |
|||
ExampleMethod(3, "Hello World", 4); |
|||
/* Variable number of arguments use array */ |
|||
public static void UseVariableParameters(params int[] list) |
|||
/* Obtain return value from function */ |
|||
public internal MyFunction(); |
|||
int returnValue = MyFunction(); |
|||
</syntaxhighlight> |
|||
=={{header|C++}}== |
|||
<syntaxhighlight lang="c++"> |
|||
/* function with no arguments */ |
|||
foo(); |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="c++"> |
|||
/* passing arguments by value*/ |
|||
/* function with one argument */ |
|||
bar(arg1); |
|||
/* function with multiple arguments */ |
|||
baz(arg1, arg2); |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="c++"> |
|||
/* get return value of a function */ |
|||
variable = function(args); |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="c++"> |
|||
#include <iostream> |
|||
using namespace std; |
|||
/* passing arguments by reference */ |
|||
void f(int &y) /* variable is now passed by reference */ |
|||
{ |
|||
y++; |
|||
} |
|||
int main() |
|||
{ |
|||
int x = 0; |
|||
cout<<"x = "<<x<<endl; /* should produce result "x = 0" */ |
|||
f(x); /* call function f */ |
|||
cout<<"x = "<<x<<endl; /* should produce result "x = 1" */ |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Clojure}}== |
|||
Note: I ran all these examples in the REPL so there is no printed output; instead I have denoted the value of each expression evaluated using `;=>'. |
|||
'''Calling a function that requires no arguments''' |
|||
<syntaxhighlight lang="clojure"> |
|||
(defn one [] |
|||
"Function that takes no arguments and returns 1" |
|||
1) |
|||
(one); => 1 |
|||
</syntaxhighlight> |
|||
'''Calling a function with a fixed number of arguments''' |
|||
<syntaxhighlight lang="clojure"> |
|||
(defn total-cost [item-price num-items] |
|||
"Returns the total price to buy the given number of items" |
|||
(* item-price num-items)) |
|||
(total-cost 1 5); => 5 |
|||
</syntaxhighlight> |
|||
'''Calling a function with optional arguments''' |
|||
The syntax is exactly the same for the calling code; here's an example of the exact same function as above, except now it takes an optional third argument (discount-percentage) |
|||
<syntaxhighlight lang="clojure"> |
|||
(defn total-cost-with-discount [item-price num-items & [discount-percentage]] |
|||
"Returns total price to buy the items after discount is applied (if given)" |
|||
(let [discount (or discount-percentage 0)] ;; Assign discount to either the discount-percentage (if given) or default 0 if not |
|||
(-> item-price |
|||
(* num-items) ;; Calculate total cost |
|||
(* (- 100 discount)) ;; Apply discount |
|||
(/ 100.0)))) |
|||
;; Now we can use the function without the optional arguments, and see the same behaviour as our total-cost function |
|||
(total-cost-with-discount 1 5); => 5 |
|||
;; Or we can add the third parameter to calculate the cost with 20% discount |
|||
(total-cost-with-discount 1 5 20); => 4 |
|||
</syntaxhighlight> |
|||
'''Calling a function with a variable number of arguments''' |
|||
You can use the optional argument syntax seen above to implement variable numbers, but here's another way to do it by writing multiple functions with different arguments all in one. |
|||
Once again, calling the function is the same, but you need to know what types of arguments are expected for each arity. |
|||
<syntaxhighlight lang="clojure"> |
|||
(defn make-address |
|||
([city place-name] (str place-name ", " city)) |
|||
([city street house-number] (str house-number " " street ", " city)) |
|||
([city street house-number apartment] (str house-number " " street ", Apt. " apartment ", " city))) |
|||
;; To call the function you just need to pass whatever arguments you are supplying as you would with a fixed number |
|||
;; First case- the queen doesn't need a street name |
|||
(make-address "London" "Buckingham Palace"); => "Buckingham Palace, London" |
|||
;; Second case |
|||
(make-address "London" "Downing Street" 10); => "10 Downing Street, London" |
|||
;; Third case |
|||
(make-address "London" "Baker Street" 221 "B"); => "221 Baker Street, Apt. B, London" |
|||
</syntaxhighlight> |
|||
'''Calling a function with named arguments''' |
|||
The way to do this in clojure is to pass the arguments as a map and destructure them by name in the function definition. The syntax is the same, but it requires you to pass a single map argument containing all of your arguments and their names. |
|||
<syntaxhighlight lang="clojure"> |
|||
(defn make-mailing-label [{:keys [name address country]}] |
|||
"Returns the correct text to mail a letter to the addressee" |
|||
(str name "\n" address "\n" (or country "UK"))) ;; If country is nil, assume it is the UK |
|||
;; We can call it with all three arguments in a map to get mickey's international address |
|||
(make-mailing-label {:name "Mickey Mouse" |
|||
:address "1 Disney Avenue, Los Angeles" |
|||
:country "USA"}); => "Mickey Mouse\n1 Disney Avenue, Los Angeles\nUSA" |
|||
;; Or we can call it with fewer arguments for domestic mail |
|||
(make-mailing-label {:name "Her Majesty" |
|||
:address "Buckingham Palace, London"}); => "Her Majesty\nBuckingham Palace, London\nUK" |
|||
</syntaxhighlight> |
|||
'''Using a function in statement context''' |
|||
I'm not really sure what this means - you can use a function to assign a variable, but there aren't really statements |
|||
<syntaxhighlight lang="clojure"> |
|||
(defn multiply-by-10 [number] |
|||
(* 10 number)) |
|||
(def fifty (multiply-by-10 5)) |
|||
fifty; => 50 |
|||
</syntaxhighlight> |
|||
'''Using a function in first-class context within an expression''' |
|||
Functions are always first-class, here are some examples of how they can be used in first class context: |
|||
You can use one function to create another |
|||
<syntaxhighlight lang="clojure"> |
|||
(defn make-discount-function [discount-percent] |
|||
"Returns a function that takes a price and applies the given discount" |
|||
(fn [price] (-> price |
|||
(* (- 100 discount-percent)) |
|||
(/ 100.0)))) |
|||
;; Now we can create a '20% off' function to calculate prices with your discount card |
|||
(def discount-20pc (make-discount-function 20)) |
|||
;; Use the function to calculate some discount prices |
|||
(discount-20pc 100); => 80 |
|||
(discount-20pc 5); => 4 |
|||
;; Your friend has a better discount card, we can use the same function to create their discount card function |
|||
(def discount-50pc (make-discount-function 50)) |
|||
(discount-50pc 100); => 50 |
|||
(discount-50pc 5); => 2.5 |
|||
</syntaxhighlight> |
|||
You can store functions in collections as if they were variables |
|||
<syntaxhighlight lang="clojure"> |
|||
;; Continuing on the same example, let's imagine Anna has a 20% discount card and Bill has 50%. Charlie pays full price |
|||
;; We can store their discount functions in a map |
|||
(def discount-cards {"Anna" discount-20pc |
|||
"Bill" discount-50pc |
|||
"Charlie" identity}) ;; Identity returns whatever value was passed to the function (in this case it will be price) |
|||
;; Now we can access them by cardholder name in another function |
|||
(defn calculate-discounted-price [price shopper-name] |
|||
"Applies the correct discount for the person" |
|||
(let [discount-fn (get discount-cards shopper-name)] ;; Get the right discount function |
|||
(discount-fn price))) ;; Apply discount function to the price |
|||
(calculate-discounted-price 100 "Anna"); => 80 |
|||
(calculate-discounted-price 100 "Bill"); => 50 |
|||
(calculate-discounted-price 100 "Charlie"); => 100 |
|||
</syntaxhighlight> |
|||
You can pass functions as arguments to other functions |
|||
<syntaxhighlight lang="clojure">;; Here we have two functions to format a price depending on the country |
|||
(defn format-price-uk [price] |
|||
(str "£" price)) |
|||
(defn format-price-us [price] |
|||
(str "$" price)) |
|||
;; And one function that takes a price formatting function as an argument |
|||
(defn format-receipt [item-name price price-formatting-function] |
|||
"Return the item name and price formatted according to the function" |
|||
(str item-name |
|||
" " |
|||
(price-formatting-function price))) ;; Call the format function to get the right representation of the price |
|||
(format-receipt "Loo Roll" 5 format-price-uk); => "Loo Roll £5" |
|||
(format-receipt "Toilet Paper" 5 format-price-us); => "Toilet Paper $5" |
|||
</syntaxhighlight> |
|||
'''Obtaining the return value of a function''' |
|||
<syntaxhighlight lang="clojure">;;You can assign it to a variable: |
|||
(def receipt-us (format-receipt "Toilet Paper" 5 format-price-us)) |
|||
;; Then the variable holds the value |
|||
receipt-us; => "Toilet Paper $5" |
|||
;; Or you can use it in a call to another function |
|||
(defn add-store-name [receipt] |
|||
"A function to add a footer to the receipt" |
|||
(str receipt "\n Thanks for shopping at Safeway" )) |
|||
;; Calls add-store-name with the result of the format function |
|||
(add-store-name (format-receipt "Toilet Paper" 5 format-price-us)); => "Toilet Paper $5\n Thanks for shopping at Safeway" |
|||
</syntaxhighlight> |
|||
'''Distinguishing built-in functions and user-defined functions''' |
|||
<syntaxhighlight lang="clojure">;; They are indistinguishable in Clojure, and you can even override a built in one |
|||
;; Using built-in addition |
|||
(+ 5 5); => 10 |
|||
;; Using custom defined addition |
|||
(defn ? [a b] |
|||
"Returns the sum of two numbers" |
|||
(+ a b)) |
|||
(? 5 5); => 10 |
|||
;; Overriding a built in function is possible but not recommended |
|||
(defn * [a b] ;; Redefining the multiplication operator |
|||
"Returns the sum of two numbers" |
|||
(+ a b)) |
|||
(* 5 5); => 10 |
|||
</syntaxhighlight> |
|||
'''Distinguishing subroutines and functions''' |
|||
<syntaxhighlight lang="clojure">;; They are the same thing - indeed, everything in clojure is a function |
|||
;; Functions without return values simply return nil |
|||
(defn no-return-value [a] |
|||
(print (str "Your argument was" a "; now returning nil"))) |
|||
(no-return-value "hi"); => nil |
|||
</syntaxhighlight> |
|||
'''Stating whether arguments are passed by value or by reference''' |
|||
All data structures are immutable, so they are passed by value only. |
|||
The value returned from the function does not change the original input |
|||
<syntaxhighlight lang="clojure">;; Set up a variable that we will pass to a function |
|||
(def the-queen {:name "Elizabeth" |
|||
:title "Your Majesty" |
|||
:address "Buckingham Palace" |
|||
:pets ["Corgi" "Horse"]}) |
|||
;; A function to modify the data |
|||
(defn adopt-pet [person pet] |
|||
"Adds pet to the person's list of pets" |
|||
(update person |
|||
:pets |
|||
#(conj % pet))) |
|||
;; Calling the function returns a new data structure with the modified pets |
|||
(adopt-pet the-queen "Ferret"); => {:name "Elizabeth":title "Your Majesty" :address "Buckingham Palace" :pets ["Corgi" "Horse" "Ferret]} |
|||
;; The original data structure is not changed |
|||
the-queen; => {:name "Elizabeth" :title "Your Majesty" :address "Buckingham Palace" :pets ["Corgi" "Horse"]}</syntaxhighlight> |
|||
'''Is partial application possible and how''' |
|||
Yes, it is similar to the discount card case we saw earlier. Instead of having a function return another function, we can use partial: |
|||
<syntaxhighlight lang="clojure">(defn apply-discount [discount-percentage price] |
|||
"Function to apply a discount to a price" |
|||
(-> price |
|||
(* (- 100 discount-percentage)) ;; Apply discount |
|||
(/ 100.0))) |
|||
;; Here we have assigned the variable to a partial function |
|||
;; It means 'call apply-discount with 10 as the first argument' |
|||
(def discount-10pc-option-1 (partial apply-discount 10)) |
|||
;; And is equivalent to this: |
|||
(defn discount-10pc-option-2 [price] |
|||
(apply-discount 10 price)) |
|||
(discount-10pc-option-1 100); => 90 |
|||
(discount-10pc-option-2 100); => 90 |
|||
</syntaxhighlight> |
|||
=={{header|COBOL}}== |
=={{header|COBOL}}== |
||
< |
<syntaxhighlight lang="cobol">CALL "No-Arguments" |
||
*> Fixed number of arguments. |
*> Fixed number of arguments. |
||
Line 237: | Line 1,428: | ||
ACCEPT Foo *> Get a PROGRAM-ID from the user. |
ACCEPT Foo *> Get a PROGRAM-ID from the user. |
||
CALL "Use-Func" USING Foo |
CALL "Use-Func" USING Foo |
||
CALL Foo USING Bar</ |
CALL Foo USING Bar</syntaxhighlight> |
||
=={{header|CoffeeScript}}== |
|||
<syntaxhighlight lang="coffeescript"> |
|||
# Calling a function that requires no arguments |
|||
foo() |
|||
# Calling a function with a fixed number of arguments |
|||
foo 1 |
|||
# Calling a function with optional arguments |
|||
# (Optional arguments are done using an object with named keys) |
|||
foo 1, optionalBar: 1, optionalBaz: 'bax' |
|||
# Calling a function with a variable number of arguments |
|||
# for a function `foo` defined as `foo = ( args... ) ->` |
|||
foo 1, 2, 3, 4 |
|||
# Calling a function with named arguments |
|||
# (Named arguments are done using an object with named keys) |
|||
foo bar: 1, bax: 'baz' |
|||
# Using a function in statement context |
|||
x = foo 1 |
|||
# Using a function in first-class context within an expression |
|||
# (For `foo` defined as `foo = ( x ) -> x + 1` |
|||
x = [ 1, 2, 3 ].map foo |
|||
# Obtaining the return value of a function |
|||
x = foo 1 |
|||
# Arguments are passed by value, even objects. Objects |
|||
# are passed as the _value_ of the reference to an object. |
|||
# Example: |
|||
bar = ( person ) -> |
|||
# Since `person` is a reference |
|||
# to the person passed in, we can assign |
|||
# a new value to its `name` key. |
|||
person.name = 'Bob' |
|||
# Since `person` is just the value of |
|||
# the original reference, assigning to it |
|||
# does not modify the original reference. |
|||
person = new Person 'Frank' |
|||
# Partial application is only possible manually through closures |
|||
curry = ( f, fixedArgs... ) -> |
|||
( args... ) -> f fixedArgs..., args... |
|||
# Example usage |
|||
add = ( x, y ) -> x + y |
|||
add2 = curry add, 2 |
|||
add2 1 #=> 3 |
|||
</syntaxhighlight> |
|||
=={{header|Common Lisp}}== |
|||
<syntaxhighlight lang="lisp"> |
|||
;Calling a function that requires no arguments |
|||
(defun a () "This is the 'A' function") |
|||
(a) |
|||
;Calling a function with a fixed number of arguments |
|||
(defun b (x y) (list x y)) |
|||
(b 1 2) |
|||
;Calling a function with optional arguments |
|||
(defun c (&optional x y) (list x y)) |
|||
(c 1) |
|||
;Calling a function with a variable number of arguments |
|||
(defun d (&rest args) args) |
|||
(d 1 2 3 4 5 6 7 8) |
|||
;Calling a function with named arguments |
|||
(defun e (&key (x 1) (y 2)) (list x y)) |
|||
(e :x 10 :y 20) |
|||
;Using a function in first-class context within an expression |
|||
(defun f (func) (funcall func)) |
|||
(f #'a) |
|||
;Obtaining the return value of a function |
|||
(defvar return-of-a (a)) |
|||
;Is partial application possible and how |
|||
(defun curry (function &rest args-1) |
|||
(lambda (&rest args-2) |
|||
(apply function (append args-1 args-2)))) |
|||
(funcall (curry #'+ 1) 2) |
|||
</syntaxhighlight> |
|||
=={{header|Cubescript}}== |
|||
<syntaxhighlight lang="cubescript"> |
|||
// No arguments |
|||
myfunction |
|||
// All functions can take a variable number of arguments. |
|||
// These can be accessed from within the function with the aliases: |
|||
// $arg1, $arg2, $arg3... $numargs tells the amount of args passed. |
|||
myfunction word "text string" 1 3.14 |
|||
// Getting a function's return value |
|||
retval = (myfunction) |
|||
// Trying to do a variable lookup on a builtin function will return an empty |
|||
// string. This can be used to distinguish builtin functions from user-defined |
|||
// ones. |
|||
if (strcmp $echo "") [echo builtin function] // true |
|||
if (strcmp $myfunction "") [echo builtin function] // false |
|||
</syntaxhighlight> |
|||
=={{header|D}}== |
|||
<syntaxhighlight lang="d">import std.traits; |
|||
enum isSubroutine(alias F) = is(ReturnType!F == void); |
|||
void main() { |
|||
void foo1() {} |
|||
// Calling a function that requires no arguments: |
|||
foo1(); |
|||
foo1; // Alternative syntax. |
|||
void foo2(int x, int y) {} |
|||
immutable lambda = function int(int x) => x ^^ 2; |
|||
// Calling a function with a fixed number of arguments: |
|||
foo2(1, 2); |
|||
foo2(1, 2); |
|||
cast(void)lambda(1); |
|||
void foo3(int x, int y=2) {} |
|||
// Calling a function with optional arguments: |
|||
foo3(1); |
|||
foo3(1, 3); |
|||
int sum(int[] arr...) { |
|||
int tot = 0; |
|||
foreach (immutable x; arr) |
|||
tot += x; |
|||
return tot; |
|||
} |
|||
real sum2(Args...)(Args arr) { |
|||
typeof(return) tot = 0; |
|||
foreach (immutable x; arr) |
|||
tot += x; |
|||
return tot; |
|||
} |
|||
// Calling a function with a variable number of arguments: |
|||
assert(sum(1, 2, 3) == 6); |
|||
assert(sum(1, 2, 3, 4) == 10); |
|||
assert(sum2(1, 2.5, 3.5) == 7); |
|||
// Calling a function with named arguments: |
|||
// Various struct or tuple-based tricks can be used for this, |
|||
// but currently D doesn't have named arguments. |
|||
// Using a function in statement context (?): |
|||
if (1) |
|||
foo1; |
|||
// Using a function in first-class context within an expression: |
|||
assert(sum(1) == 1); |
|||
auto foo4() { return 1; } |
|||
// Obtaining the return value of a function: |
|||
immutable x = foo4; |
|||
// Distinguishing built-in functions and user-defined functions: |
|||
// There are no built-in functions, beside the operators, and |
|||
// pseudo-functions like assert(). |
|||
int myFynction(int x) { return x; } |
|||
void mySubroutine(int x) {} |
|||
// Distinguishing subroutines and functions: |
|||
// (A subroutine is merely a function that has no explicit |
|||
// return statement and will return void). |
|||
pragma(msg, isSubroutine!mySubroutine); // Prints: true |
|||
pragma(msg, isSubroutine!myFynction); // Prints: false |
|||
void foo5(int a, in int b, ref int c, out int d, lazy int e, scope int f) {} |
|||
// Stating whether arguments are passed by value, by reference, etc: |
|||
alias STC = ParameterStorageClass; |
|||
alias psct = ParameterStorageClassTuple!foo5; |
|||
static assert(psct.length == 6); // Six parameters. |
|||
static assert(psct[0] == STC.none); |
|||
static assert(psct[1] == STC.none); |
|||
static assert(psct[2] == STC.ref_); |
|||
static assert(psct[3] == STC.out_); |
|||
static assert(psct[4] == STC.lazy_); |
|||
static assert(psct[5] == STC.scope_); |
|||
// There are also inout and auto ref. |
|||
int foo6(int a, int b) { return a + b; } |
|||
// Is partial application possible and how: |
|||
import std.functional; |
|||
alias foo6b = partial!(foo6, 5); |
|||
assert(foo6b(6) == 11); |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>true |
|||
false</pre> |
|||
=={{header|Dart}}== |
|||
<syntaxhighlight lang="dart">void main() { |
|||
// Function definition |
|||
// See the "Function definition" task for more info |
|||
void noArgs() {} |
|||
void fixedArgs(int arg1, int arg2) {} |
|||
void optionalArgs([int arg1 = 1]) {} |
|||
void namedArgs({required int arg1}) {} |
|||
int returnsValue() {return 1;} |
|||
// Calling a function that requires no arguments |
|||
noArgs(); |
|||
// Calling a function with a fixed number of arguments |
|||
fixedArgs(1, 2); |
|||
// Calling a function with optional arguments |
|||
optionalArgs(); |
|||
optionalArgs(2); |
|||
// Calling a function with named arguments |
|||
namedArgs(arg1: 1); |
|||
// Using a function in statement context |
|||
if (true) { |
|||
noArgs(); |
|||
} |
|||
// Obtaining the return value of a function |
|||
var value = returnsValue(); |
|||
}</syntaxhighlight> |
|||
=={{header|Delphi}}== |
|||
Delphi allows everything what [[#Pascal|Pascal]] allows. |
|||
In addition, the following is ''also'' possible: |
|||
Calling a function without arguments and obtaining its return value: |
|||
<syntaxhighlight lang="delphi">foo()</syntaxhighlight> |
|||
Calling a function with optional arguments: |
|||
<syntaxhighlight lang="delphi">foo(1)</syntaxhighlight> |
|||
Calling a function with a variable number of arguments: |
|||
<syntaxhighlight lang="delphi">foo(1, 2, 3, 4, 5)</syntaxhighlight> |
|||
Using a function in a statement context: |
|||
<syntaxhighlight lang="delphi">writeLn('Hello world.'); |
|||
foo; |
|||
writeLn('Goodbye world')</syntaxhighlight> |
|||
Like above, an empty parameter list, i. e. <tt>()</tt>, could be supplied too. |
|||
=={{header|Dragon}}== |
|||
* Calling a function that requires no arguments |
|||
<syntaxhighlight lang="dragon">myMethod()</syntaxhighlight> |
|||
* Calling a function with a fixed number of arguments |
|||
<syntaxhighlight lang="dragon">myMethod(97, 3.14)</syntaxhighlight> |
|||
=={{header|Dyalect}}== |
|||
Calling a function that requires no arguments: |
|||
<syntaxhighlight lang="dyalect">func foo() { } |
|||
foo()</syntaxhighlight> |
|||
Calling a function with a fixed number of arguments: |
|||
<syntaxhighlight lang="dyalect">func foo(x, y, z) { } |
|||
foo(1, 2, 3)</syntaxhighlight> |
|||
Calling a function with optional arguments: |
|||
<syntaxhighlight lang="dyalect">func foo(x, y = 0, z = 1) { } |
|||
foo(1)</syntaxhighlight> |
|||
Calling a function with a variable number of arguments: |
|||
<syntaxhighlight lang="dyalect">func foo(args...) { } |
|||
foo(1, 2, 3)</syntaxhighlight> |
|||
Calling a function with named arguments: |
|||
<syntaxhighlight lang="dyalect">func foo(x, y, z) { } |
|||
foo(z: 3, x: 1, y: 2)</syntaxhighlight> |
|||
Using a function in statement context: |
|||
<syntaxhighlight lang="dyalect">func foo() { } |
|||
if true { |
|||
foo() |
|||
}</syntaxhighlight> |
|||
Using a function in first-class context within an expression: |
|||
<syntaxhighlight lang="dyalect">func foo() { } |
|||
var x = if foo() { |
|||
1 |
|||
} else { |
|||
2 |
|||
}</syntaxhighlight> |
|||
Obtaining the return value of a function: |
|||
<syntaxhighlight lang="dyalect">func foo(x) { x * 2 } |
|||
var x = 2 |
|||
var y = foo(x)</syntaxhighlight> |
|||
Distinguishing built-in functions and user-defined functions: |
|||
<syntaxhighlight lang="dyalect">//Built-in functions are regular functions from an implicitly imported "lang" module |
|||
//There is no actual difference between these functions and user-defined functions |
|||
//You can however write a function that would check if a given function is declared in "lang" module: |
|||
func isBuiltin(fn) => |
|||
fn.Name is not nil && fn.Name in lang && lang[fn.Name] == fn |
|||
//Usage: |
|||
func foo() { } //A user-defined function |
|||
print(isBuiltin(foo)) //Prints: false |
|||
print(isBuiltin(assert)) //Prints: true</syntaxhighlight> |
|||
Distinguishing subroutines and functions: |
|||
<syntaxhighlight lang="dyalect">//There is no difference between subroutines and functions: |
|||
func foo() { } //doesn't explicitly return something (but in fact returns nil) |
|||
func bar(x) { return x * 2 } //explicitly returns value (keyword "return" can be omitted)</syntaxhighlight> |
|||
Stating whether arguments are passed by value or by reference: |
|||
<syntaxhighlight lang="dyalect">//All arguments are passed by reference</syntaxhighlight> |
|||
Is partial application possible and how: |
|||
<syntaxhighlight lang="dyalect">//Using a closure: |
|||
func apply(fun, fst) { snd => fun(fst, snd) } |
|||
//Usage: |
|||
func sum(x, y) { x + y } |
|||
var sum2 = apply(sum, 2) |
|||
var x = sum2(3) //x is 5 |
|||
//By second argument |
|||
func flip(fun) { (y, x) => fun(x, y) } |
|||
func sub(x, y) { x - y } |
|||
var sub3 = apply(flip(sub), 3) |
|||
x = sub3(9) //x is 6</syntaxhighlight> |
|||
=={{header|Déjà Vu}}== |
|||
<syntaxhighlight lang="dejavu"># all functions used are from the standard library |
|||
# calling a function with no arguments: |
|||
random-int |
|||
# calling a function with a fixed number of arguments: |
|||
+ 1 2 |
|||
# calling a function with optional arguments: |
|||
# optional arguments are not really possible as such |
|||
# generally differently named functions are used: |
|||
sort [ 3 2 1 ] |
|||
sort-by @len [ "Hello" "World" "Bob" ] |
|||
# calling a function with a variable number of arguments: |
|||
# generally with a special terminator value, which one depends |
|||
# on the function called |
|||
concat( 1 2 3 ) |
|||
[ 1 2 3 ] |
|||
set{ :foo :bar :spam } |
|||
# calling a function with named arguments: not possible |
|||
# using a function in first-class context within an expression |
|||
$ @-- @len # $ is "compose", so the function returned is "one less than the length" |
|||
# obtaining the return value of a function |
|||
# return values are always pushed on the stack, so you don't need anything special |
|||
random-int |
|||
# discarding the return value of a function |
|||
drop random-int |
|||
# method call: |
|||
local :do { :nuthin @pass } |
|||
do!nuthin |
|||
!import!fooModule # same as eva!import :fooModule |
|||
# arguments are passed by object-identity, like in Python and Lua |
|||
# partial application is not possible, due to the fact that |
|||
# a function's arity is a property of its behavior and not |
|||
# of its definition</syntaxhighlight> |
|||
=={{header|EasyLang}}== |
|||
<syntaxhighlight> |
|||
func sqr n . |
|||
return n * n |
|||
. |
|||
print sqr 3 |
|||
# |
|||
proc divmod a b . q r . |
|||
q = a div b |
|||
r = a mod b |
|||
. |
|||
divmod 11 3 q r |
|||
print q & " " & r |
|||
# |
|||
subr sqr2 |
|||
a = a * a |
|||
. |
|||
a = 5 |
|||
sqr2 |
|||
print a |
|||
</syntaxhighlight> |
|||
=={{header|Ecstasy}}== |
|||
<b><i>Calling a function that requires no arguments:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
foo(); // <-- this is "invoking a function in statement context" |
|||
Int x = bar(); // <-- this is "invoking a function in expression context" |
|||
</syntaxhighlight> |
|||
<b><i>Calling a function with a fixed number of arguments:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
foo(1, 2, 3); |
|||
Int x = bar(4, 5, 6); |
|||
</syntaxhighlight> |
|||
<b><i>Calling a function with optional arguments:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
module CallOptArgsFunc { |
|||
static Int foo(Int a=0, Int b=99, Int c=-1) { |
|||
return a + b + c; |
|||
} |
|||
void run() { |
|||
@Inject Console console; |
|||
console.print($"{foo()=}"); |
|||
console.print($"{foo(1)=}"); |
|||
console.print($"{foo(1, 2)=}"); |
|||
console.print($"{foo(1, 2, 3)=}"); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
foo()=98 |
|||
foo(1)=99 |
|||
foo(1, 2)=2 |
|||
foo(1, 2, 3)=6 |
|||
</pre> |
|||
<b><i>Calling a function with a variable number of arguments:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
module CallVarArgsFunc { |
|||
// Ecstasy does not have a var-args concept; instead, array notation is used |
|||
static Int foo(Int[] args = []) { |
|||
return args.size; |
|||
} |
|||
void run() { |
|||
@Inject Console console; |
|||
console.print($"{foo()=}"); |
|||
console.print($"{foo([])=}"); |
|||
console.print($"{foo([1])=}"); |
|||
console.print($"{foo([1, 2])=}"); |
|||
console.print($"{foo([1, 2, 3])=}"); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
foo()=0 |
|||
foo([])=0 |
|||
foo([1])=1 |
|||
foo([1, 2])=2 |
|||
foo([1, 2, 3])=3 |
|||
</pre> |
|||
<b><i>Calling a function with named arguments:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
module CallNamedArgsFunc { |
|||
static String foo(Int a=1, Int b=2, Int c=3) { |
|||
return $"a:{a}, b:{b}, c:{c}"; |
|||
} |
|||
void run() { |
|||
@Inject Console console; |
|||
console.print($"{foo(c=9, b=8, a=7)=}"); |
|||
console.print($"{foo(4, c=6, b=5)=}"); |
|||
console.print($"{foo(c=99)=}"); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
foo(c=9, b=8, a=7)=a:7, b:8, c:9 |
|||
foo(4, c=6, b=5)=a:4, b:5, c:6 |
|||
foo(c=99)=a:1, b:2, c:99 |
|||
</pre> |
|||
<b><i>Using a function in first-class context within an expression:</i></b> Functions are always first class in Ecstasy; everything (including classes, types, methods, properties, functions, variables, etc.) is an object. |
|||
<syntaxhighlight lang="java"> |
|||
module FirstClassFunctions { |
|||
@Inject Console console; |
|||
void run() { |
|||
function Int(String) stringLen = s -> s.size; |
|||
function Int(Int, Int) sum = (n1, n2) -> n1+n2; |
|||
String[] testData = ["abc", "easy", "as", "123"]; |
|||
console.print($|total string length of values in {testData} =\ |
|||
| {testData.map(stringLen).reduce(0, sum)} |
|||
); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
total string length of values in [abc, easy, as, 123] = 12 |
|||
</pre> |
|||
<b><i>Obtaining the return value of a function:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
module ObtainReturnValues { |
|||
(Int, String, Dec) foo() { |
|||
return 3, "hello!", 9.87; |
|||
} |
|||
void run() { |
|||
foo(); // ignore return values |
|||
Int i1 = foo(); // only use first returned value |
|||
(Int i2, String s2) = foo(); // only use first two returned values |
|||
(Int i3, String s3, Dec d3) = foo(); // use all returned values |
|||
Tuple<Int, String, Dec> t = foo(); // alternatively, get the tuple instead |
|||
@Inject Console console; |
|||
console.print($"{i3=}, {s3=}, {d3=}, {t=}"); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
i3=3, s3=hello!, d3=9.87, t=(3, hello!, 9.87) |
|||
</pre> |
|||
<b><i>Distinguishing built-in functions and user-defined functions:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
// Ecstasy does not have any built-in functions. However, there are two keywords |
|||
// ("is" and "as") that use a function-like syntax: |
|||
module IsAndAs { |
|||
Int|String foo() { |
|||
return "hello"; |
|||
} |
|||
void run() { |
|||
@Inject Console console; |
|||
Object o = foo(); |
|||
if (o.is(String)) { // <- looks like a function call |
|||
String s = o.as(String); // <- looks like a function call |
|||
console.print($"foo returned the string: {s.quoted()}"); |
|||
} |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
foo returned the string: "hello" |
|||
</pre> |
|||
<b><i>Distinguishing subroutines and functions:</i></b> There is no such thing as a subroutine in Ecstasy. There are only methods (virtual functions with a "this"), functions, and object constructors. |
|||
<b><i>Stating whether arguments are passed by value or by reference:</i></b> Ecstasy does not specify whether arguments are passed by value or by reference. However, since all Ecstasy types are <i>conceptually</i> reference types, the behavior is defined as if all arguments are references passed by value; this is the same model used by Java for all of its reference types. |
|||
<b><i>Is partial application possible and how:</i></b> |
|||
<syntaxhighlight lang="java"> |
|||
module PartialApplication { |
|||
void foo(String s, Int i, Dec d) { |
|||
@Inject Console console; |
|||
console.print($"inside call to foo({s=}, {i=}, {d=})"); |
|||
} |
|||
void run() { |
|||
// note that the "&" obtains the reference to the function, and suppresses the |
|||
// invocation thereof, so it is *allowed* in all three of these cases, but it |
|||
// is *required* in the third case: |
|||
function void(String, Int, Dec) unbound = foo; // or "foo(_, _, _)" |
|||
function void(String, Dec) partBound = unbound(_, 99, _); |
|||
function void() allBound = &partBound("world", 3.14); |
|||
unbound("nothing", 0, 0.0); |
|||
partBound("hello", 2.718); |
|||
allBound(); |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
inside call to foo(s=nothing, i=0, d=0) |
|||
inside call to foo(s=hello, i=99, d=2.718) |
|||
inside call to foo(s=world, i=99, d=3.14) |
|||
</pre> |
|||
=={{header|Elena}}== |
|||
ELENA 4.1: |
|||
Declaring closures |
|||
<syntaxhighlight lang="elena"> |
|||
var c0 := { console.writeLine("No argument provided") }; |
|||
var c2 := (int a, int b){ console.printLine("Arguments ",a," and ",b," provided") }; |
|||
</syntaxhighlight> |
|||
Calling a closure without arguments |
|||
<syntaxhighlight lang="elena"> |
|||
c0(); |
|||
</syntaxhighlight> |
|||
Calling a closure with arguments |
|||
<syntaxhighlight lang="elena"> |
|||
c2(2,4); |
|||
</syntaxhighlight> |
|||
Passing arguments by reference: |
|||
<syntaxhighlight lang="elena"> |
|||
var exch := (ref object x){ x := 2 }; |
|||
var a := 1; |
|||
exch(ref a); |
|||
</syntaxhighlight> |
|||
=={{header|Elixir}}== |
|||
<syntaxhighlight lang="elixir"> |
|||
# Anonymous function |
|||
foo = fn() -> |
|||
IO.puts("foo") |
|||
end |
|||
foo() #=> undefined function foo/0 |
|||
foo.() #=> "foo" |
|||
# Using `def` |
|||
defmodule Foo do |
|||
def foo do |
|||
IO.puts("foo") |
|||
end |
|||
end |
|||
Foo.foo #=> "foo" |
|||
Foo.foo() #=> "foo" |
|||
# Calling a function with a fixed number of arguments |
|||
defmodule Foo do |
|||
def foo(x) do |
|||
IO.puts(x) |
|||
end |
|||
end |
|||
Foo.foo("foo") #=> "foo" |
|||
# Calling a function with a default argument |
|||
defmodule Foo do |
|||
def foo(x \\ "foo") do |
|||
IO.puts(x) |
|||
end |
|||
end |
|||
Foo.foo() #=> "foo" |
|||
Foo.foo("bar") #=> "bar" |
|||
# There is no such thing as a function with a variable number of arguments. So in Elixir, you'd call the function with a list |
|||
defmodule Foo do |
|||
def foo(args) when is_list(args) do |
|||
Enum.each(args, &(IO.puts(&1))) |
|||
end |
|||
end |
|||
# Calling a function with named arguments |
|||
defmodule Foo do |
|||
def foo([x: x]) do |
|||
IO.inspect(x) |
|||
end |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|EMal}}== |
|||
<syntaxhighlight lang="emal"> |
|||
fun task = void by text about, fun code |
|||
writeLine(0U00b7 + " " + about) |
|||
code() |
|||
end |
|||
fun answer = void by var message do writeLine(" " + message) end |
|||
# few definitions |
|||
fun noArgumentsFunction = int by block do return 97 end |
|||
fun fixedArgumentsFunction = void by var a, var b do end |
|||
fun variadicFunction = void by text a, some var values do end |
|||
fun funArgumentFunction = var by fun f, var b do return f() + b end |
|||
task("Calling a function that requires no arguments", void by block |
|||
answer("Is supported.") |
|||
noArgumentsFunction() |
|||
end) |
|||
task("Calling a function with a fixed number of arguments", void by block |
|||
answer("Is supported.") |
|||
fixedArgumentsFunction(97, 3.14) |
|||
end) |
|||
task("Calling a function with optional arguments", void by block |
|||
answer("Not supported in EMal.") |
|||
end) |
|||
task("Calling a function with a variable number of arguments", void by block |
|||
answer("Variadic functions are supported.") |
|||
variadicFunction("mandatory", 97, 3.14) |
|||
variadicFunction("mandatory", 97) |
|||
end) |
|||
task("Calling a function with named arguments", void by block |
|||
answer("Not supported in EMal.") |
|||
end) |
|||
task("Using a function in statement context", void by block |
|||
answer("Is supported.") |
|||
if true do noArgumentsFunction() |
|||
else do fixedArgumentsFunction(97, 3.14) end |
|||
end) |
|||
task("Using a function in first-class context within an expression", void by block |
|||
answer("Functions are first class, can be passed as arguments and returned.") |
|||
answer(funArgumentFunction(noArgumentsFunction, 3.14)) |
|||
end) |
|||
task("Obtaining the return value of a function", void by block |
|||
answer("Is supported.") |
|||
int value = noArgumentsFunction() |
|||
answer(value) |
|||
end) |
|||
task("Distinguishing built-in functions and user-defined functions", void by block |
|||
answer("No distinction.") |
|||
end) |
|||
task("Distinguishing subroutines and functions", void by block |
|||
answer("No distinction, we support void return type.") |
|||
end) |
|||
task("Stating whether arguments are passed by value or by reference", void by block |
|||
answer("Pass by value, but text, blob, objects hold a reference.") |
|||
end) |
|||
task("Is partial application possible and how", void by block |
|||
answer("Is supported.") |
|||
^|I had some confusion about partial application and currying, thanks to these links: |
|||
| https://stackoverflow.com/questions/218025/what-is-the-difference-between-currying-and-partial-application |
|||
| https://web.archive.org/web/20161023205431/http://www.uncarved.com/articles/not_curryin |
|||
|^ |
|||
# Partial applying |
|||
fun add = int by int a, int b do return a + b end |
|||
fun partial = fun by fun f, int a |
|||
return int by int b |
|||
return add(a, b) |
|||
end |
|||
end |
|||
fun add7 = partial(add, 7) |
|||
answer(add(7, 5)) |
|||
answer(add7(5)) |
|||
# Currying |
|||
fun addN = fun by int n |
|||
return int by int x |
|||
return x + n |
|||
end |
|||
end |
|||
fun plus = int by int a, int b |
|||
fun addA = addN(a) |
|||
return addA(b) |
|||
end |
|||
answer(plus(7, 5)) |
|||
end) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
· Calling a function that requires no arguments |
|||
Is supported. |
|||
· Calling a function with a fixed number of arguments |
|||
Is supported. |
|||
· Calling a function with optional arguments |
|||
Not supported in EMal. |
|||
· Calling a function with a variable number of arguments |
|||
Variadic functions are supported. |
|||
· Calling a function with named arguments |
|||
Not supported in EMal. |
|||
· Using a function in statement context |
|||
Is supported. |
|||
· Using a function in first-class context within an expression |
|||
Functions are first class, can be passed as arguments and returned. |
|||
100.14 |
|||
· Obtaining the return value of a function |
|||
Is supported. |
|||
97 |
|||
· Distinguishing built-in functions and user-defined functions |
|||
No distinction. |
|||
· Distinguishing subroutines and functions |
|||
No distinction, we support void return type. |
|||
· Stating whether arguments are passed by value or by reference |
|||
Pass by value, but text, blob, objects hold a reference. |
|||
· Is partial application possible and how |
|||
Is supported. |
|||
12 |
|||
12 |
|||
12 |
|||
</pre> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
< |
<syntaxhighlight lang="erlang"> |
||
no_argument() |
no_argument() |
||
one_argument( Arg ) |
one_argument( Arg ) |
||
Line 253: | Line 2,243: | ||
% Arguments are passed by reference, but you can not change them. |
% Arguments are passed by reference, but you can not change them. |
||
% Partial application is possible (a function returns a function that has one argument bound) |
% Partial application is possible (a function returns a function that has one argument bound) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
|||
Icon and Unicon have generalized procedures and syntax that are used to implement functions, subroutines and generators. |
|||
* Procedures can return values or not and callers may use the returned values or not. |
|||
* Procedures in Icon and Unicon are first class values and can be assigned to variables which can then be used to call procedures. This also facilitates some additional calling syntax. |
|||
* Additionally, co-expressions are supported which allow for co-routine like transfers of control between two or more procedures. There are some differences in syntax for co-expression calls. |
|||
* There are no differences between calling built-in vs. user defined functions |
|||
* Named arguments is not natively supported; however, they can be supported using a user defined procedure as shown in [[Named_parameters#Icon_and_Unicon|Named parameters]] |
|||
* Method calling is similar with some extended syntax |
|||
* Arguments are basically passed by value or reference based on their type. Immutable values like strings, and numbers are passed by value. Mutable data types like structures are essentially references and although these are passed by value the effective behavior is like a call by reference. |
|||
For more information see [[Icon%2BUnicon/Intro|Icon and Unicon Introduction on Rosetta]] |
|||
<lang Icon>procedure main() # demonstrate and describe function calling syntax and semantics |
|||
# normal procedure/function calling |
|||
f() # no arguments, also command context |
|||
f(x) # fixed number of arguments |
|||
f(x,h,w) # variable number of arguments (varargs) |
|||
y := f(x) # Obtaining the returned value of a function |
|||
# procedures as first class values and string invocation |
|||
f!L # Alternate calling syntax using a list as args |
|||
(if \x then f else g)() # call (f or g)() |
|||
f := write # assign a procedure |
|||
f("Write is now called") # ... and call it |
|||
"f"() # string invocation, procedure |
|||
"-"(1) # string invocation, operator |
|||
# Co-expressions |
|||
f{e1,e2} # parallel evaluation co-expression call |
|||
# equivalent to f([create e1, create e2]) |
|||
expr @ coexp # transmission of a single value to a coexpression |
|||
[e1,e2]@coexp # ... of multiple values (list) to a coexpression |
|||
coexp(e1,e2) # ... same as above but only in Unicon |
|||
# Other |
|||
f("x:=",1,"y:=",2) # named parameters (user defined) |
|||
end</lang> |
|||
=={{header|F Sharp|F#}}== |
=={{header|F Sharp|F#}}== |
||
< |
<syntaxhighlight lang="fsharp">// No arguments |
||
noArgs() |
noArgs() |
||
Line 341: | Line 2,287: | ||
// Partial application example |
// Partial application example |
||
let add2 = (+) 2</ |
let add2 = (+) 2</syntaxhighlight> |
||
=={{header|Factor}}== |
|||
* Calling a word with no arguments: |
|||
<syntaxhighlight lang="factor">foo</syntaxhighlight> |
|||
* Calling a word with a fixed number of arguments. This will pull as many objects as it needs from the stack. If there are not enough, it will result in a stack underflow. |
|||
<syntaxhighlight lang="factor">foo</syntaxhighlight> |
|||
* No special support for optional arguments. |
|||
* Variable arguments are achieved by defining a word that takes an integer, and operates on that many items at the top of the stack: |
|||
<syntaxhighlight lang="factor">"a" "b" "c" 3 narray |
|||
! { "a" "b" "c" }</syntaxhighlight> |
|||
* The named arguments idiom is to define a tuple, set its slots, and pass it to a word: |
|||
<syntaxhighlight lang="factor"><email> |
|||
"jack@aol.com" >>from |
|||
{ "jill@aol.com" } >>to |
|||
"Hello there" >>subject |
|||
body >>body |
|||
send-email</syntaxhighlight> |
|||
* First-class context: this pushes a word to the stack. Use execute to evaluate. |
|||
<syntaxhighlight lang="factor">\ foo</syntaxhighlight> |
|||
Additionally, you can put words directly inside sequences and quotations for deferred execution: |
|||
<syntaxhighlight lang="factor">{ foo } [ foo ]</syntaxhighlight> |
|||
* Obtaining the return value, which will be placed on the stack: |
|||
<syntaxhighlight lang="factor">foo</syntaxhighlight> |
|||
* Returns true if the word is defined in the Factor VM as opposed to in a vocabulary. It should be noted that there are very few primitives. |
|||
<syntaxhighlight lang="factor">\ foo primitive?</syntaxhighlight> |
|||
* Factor makes no distinction between subroutines and functions. |
|||
* It's not perfectly accurate to think of words as passing arguments by reference (or at all), since all words simply operate on the data stack. However, it is still important for the programmer to understand that words which make duplicates of objects such as <tt>dup</tt> and <tt>over</tt> do so by copying references. If one wishes for a shallow copy of a non-immediate object, one may use <tt>clone</tt>. |
|||
* Partial application is possible by use of curry. Here, the object 2 is curried into the left side of the quotation (anonymous function) <tt>[ - ]</tt>: |
|||
<syntaxhighlight lang="factor">{ 1 2 3 } 2 [ - ] curry map . |
|||
! { -1 0 1 }</syntaxhighlight> |
|||
=={{header|Forth}}== |
|||
<syntaxhighlight lang="forth">a-function \ requiring no arguments |
|||
a-function \ with a fixed number of arguents |
|||
a-function \ having optional arguments |
|||
a-function \ having a variable number of arguments |
|||
a-function \ having such named arguments as we have in Forth |
|||
' a-function var ! \ using a function in a first-class context (here: storing it in a variable) |
|||
a-function \ in which we obtain a function's return value |
|||
\ forth lacks 'statement contenxt' |
|||
\ forth doesn't distinguish between built-in and user-defined functions |
|||
\ forth doesn't distinguish between functions and subroutines |
|||
\ forth doesn't care about by-value or by-reference |
|||
\ partial application is achieved by creating functions and manipulating stacks |
|||
: curried 0 a-function ; |
|||
: only-want-third-argument 1 2 rot a-function ; |
|||
\ Realistic example: |
|||
: move ( delta-x delta-y -- ) |
|||
y +! x +! ; |
|||
: down ( n -- ) 0 swap move ; |
|||
: up ( n -- ) negate down ; |
|||
: right ( n -- ) 0 move ; |
|||
: left ( n -- ) negate right ;</syntaxhighlight> |
|||
=={{header|Fortran}}== |
|||
===Examples=== |
|||
<syntaxhighlight lang="fortran">program main |
|||
implicit none |
|||
integer :: a |
|||
integer :: f, g |
|||
logical :: lresult |
|||
interface |
|||
integer function h(a,b,c) |
|||
integer :: a, b |
|||
integer, optional :: c |
|||
end function |
|||
end interface |
|||
write(*,*) 'no arguments: ', f() |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'fixed arguments: ', g(5,8,lresult) |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'optional arguments: ', h(5,8), h(5,8,4) |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'function with variable arguments: Does not apply!' |
|||
write(*,*) 'An option is to pass arrays of variable lengths.' |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'named arguments: ', h(c=4,b=8,a=5) |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'function in statement context: Does not apply!' |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'Fortran passes memory location of variables as arguments.' |
|||
write(*,*) 'So an argument can hold the return value.' |
|||
write(*,*) 'function result: ', g(5,8,lresult) , ' function successful? ', lresult |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'Distinguish between built-in and user-defined functions: Does not apply!' |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'Calling a subroutine: ' |
|||
a = 30 |
|||
call sub(a) |
|||
write(*,*) 'Function call: ', f() |
|||
write(*,*) '-----------------' |
|||
write(*,*) 'All variables are passed as pointers.' |
|||
write(*,*) 'Problems can arise if instead of sub(a), one uses sub(10).' |
|||
write(*,*) '-----------------' |
|||
end program |
|||
!no argument |
|||
integer function f() |
|||
f = 10 |
|||
end function |
|||
!fixed number of arguments |
|||
integer function g(a, b, lresult) |
|||
integer :: a, b |
|||
logical :: lresult |
|||
g = a+b |
|||
lresult = .TRUE. |
|||
end function |
|||
!optional arguments |
|||
integer function h(a, b, c) |
|||
integer :: a, b |
|||
integer, optional :: c |
|||
h = a+b |
|||
if(present(c)) then |
|||
h = h+10*c |
|||
end if |
|||
end function |
|||
!subroutine |
|||
subroutine sub(a) |
|||
integer :: a |
|||
a = a*100 |
|||
write(*,*) 'Output of subroutine: ', a |
|||
end subroutine |
|||
</syntaxhighlight> |
|||
<pre> |
|||
no arguments: 10 |
|||
----------------- |
|||
fixed arguments: 13 |
|||
----------------- |
|||
optional arguments: 13 53 |
|||
----------------- |
|||
function with variable arguments: Does not apply! |
|||
An option is to pass arrays of variable lengths. |
|||
----------------- |
|||
named arguments: 53 |
|||
----------------- |
|||
function in statement context: Does not apply! |
|||
----------------- |
|||
Fortran passes memory location of variables as arguments. |
|||
So an argument can hold the return value. |
|||
function result: 13 function successful? T |
|||
----------------- |
|||
Distinguish between built-in and user-defined functions: Does not apply! |
|||
----------------- |
|||
Calling a subroutine: |
|||
Output of subroutine: 3000 |
|||
Function call: 10 |
|||
----------------- |
|||
All variables are passed as pointers. |
|||
Problems can arise if instead of sub(a), one uses sub(10). |
|||
----------------- |
|||
</pre> |
|||
===In other words=== |
|||
As described in [[Naming_conventions#Fortran|Naming Conventions]], First Fortran (1958) allowed user-written functions but with restrictions on the names so that an ordinary variable called SIN would be disallowed because it was deemed to be in conflict with the library function SINF. These constraints were eased with Fortran II, and the rule became that a user could employ any correct-form name, such as SQRT, for a variable's name (simple or array) but then the library function SQRT would become inaccessible in such a routine. Similarly, there would be no point in the user writing a function called SQRT, because it could not be invoked - the compiler would take any invocation as being for the library routine SQRT. Thus, a user-written function could perhaps chance to have the name of an obscure (i.e. one forgotten about) library function, but if you were lucky it would have conflicting parameters and the compiler will complain. |
|||
A special case is provided by the "arithmetic statement function" that is defined after declarations but before executable statements in a routine and which has access to all the variables of the routine. Consider <syntaxhighlight lang="fortran"> REAL this,that |
|||
DIST(X,Y,Z) = SQRT(X**2 + Y**2 + Z**2) + this/that !One arithmetic statement, possibly lengthy. |
|||
... |
|||
D = 3 + DIST(X1 - X2,YDIFF,SQRT(ZD2)) !Invoke local function DIST.</syntaxhighlight> |
|||
In this case, even if "DIST" happened to be the name of some library function, invocations within the routine defining it would not be of the library function. |
|||
This flexibility in naming can be turned the other way around. For example, some compilers offer the intrinsic function SIND which calculates ''sine'' in degrees. Simply defining an array <code>REAL SIND(0:360)</code> (and properly initialising it) enables the slowish SIND function to be approximated by the faster indexing of an array. Put another way, an array is a function of a limited span of integer-valued arguments and is called in arithmetic expressions with the same syntax as is used for functions, be they intrinsic or user-written. Those writing in Pascal would be blocked by its insistence that arrays employ [] rather than (). Similarly, when testing, an array's declaration might be commented out and a function of that name defined, which function could check its arguments, write to a log file, note time stamps, or whatever else comes to mind. But alas, there is no "palindromic" or reverse-entry facility whereby a function could handle the assignment of a value ''to'' an array that would make this fully flexible. |
|||
Within a function there are some delicacies. The usual form is to assign the desired result to the name of the variable as in <code>H = A + B</code> where <code>H</code> is the name of the function. However, during evaluation the desired result might be developed over many stages and with reference to prior values. Suppose function H is to combine results from separate statements and it is not convenient to achieve this via one lengthy expression, perhaps because of conditional tests. Something like <syntaxhighlight lang="fortran"> H = A + B |
|||
IF (blah) H = 3*H - 7</syntaxhighlight> |
|||
As written, the appearance of <code>H</code> on the right-hand side of an expression does ''not'' constitute a call of function <code>H</code> at all. Some compilers fail to deal with this as hoped, and so one must use a scratch variable such as <code>FH</code> to develop the value, then remember to ensure that the assignment <code>H = FH</code> is executed before exiting the function, by whatever route. If the result is a large datum (a long character variable, say) this is annoying. |
|||
With the belated recognition of recursive possibilities (introduced by Algol in the 1960s) comes the possibility of a function invoking itself. In the above example, <code>H(3.7,5.5,6.6)</code> would clearly be a function invocation (because of the parentheses) whereas <code>H</code> would not be. Actually, Fortran routines have always been able to engage in recursion, it is just the returns that will fail - except on a stack-based system such as the Burroughs 6700 in the 1970s. |
|||
Fortran also offers the ability to pass a function as a parameter such that the recipient routine can call it, as in <syntaxhighlight lang="fortran"> REAL FUNCTION INTG8(F,A,B,DX) !Integrate function F. |
|||
EXTERNAL F !Some function of one parameter. |
|||
REAL A,B !Bounds. |
|||
REAL DX !Step. |
|||
INTEGER N !A counter. |
|||
INTG8 = F(A) + F(B) !Get the ends exactly. |
|||
N = (B - A)/DX !Truncates. Ignore A + N*DX = B chances. |
|||
DO I = 1,N !Step along the interior. |
|||
INTG8 = INTG8 + F(A + I*DX) !Evaluate the function. |
|||
END DO !On to the next. |
|||
INTG8 = INTG8/(N + 2)*(B - A) !Average value times interval width. |
|||
END FUNCTION INTG8 !This is not a good calculation! |
|||
FUNCTION TRIAL(X) !Some user-written function. |
|||
REAL X |
|||
TRIAL = 1 + X !This will do. |
|||
END FUNCTION TRIAL !Not the name of a library function. |
|||
PROGRAM POKE |
|||
INTRINSIC SIN !Thus, not an (undeclared) ordinary variable. |
|||
EXTERNAL TRIAL !Likewise, but also, not an intrinsic function. |
|||
REAL INTG8 !Don't look for the result in an integer place. |
|||
WRITE (6,*) "Result=",INTG8(SIN, 0.0,8*ATAN(1.0),0.01) |
|||
WRITE (6,*) "Linear=",INTG8(TRIAL,0.0,1.0, 0.01) |
|||
END</syntaxhighlight> |
|||
This involves a fair amount of juggling special declarations so that the compiler will make the desired assumptions that a function is being called upon, rather than the value of some variable. This is eased somewhat with F90 onwards if the MODULE protocol is used so that at least you do not have to remember to declare INTG8 as REAL. Certain library functions are not allowed as candidates for passing to INTG8 (for instance, the compiler may render them as in-line code, bypassing the protocol used for functions) and arithmetic statement functions are usually rejected, as would be an array masquerading as a function. Arithmetic expressions are not allowable as possible "functions" either - how might something like <code>sin(x) + 3*sqrt(x) + 7</code> be recognised as a function instead? As <code>INTG8(SIN + 3*SQRT + 7,''etc...''</code>? Unlike Algol, Fortran does not offer the call-by-name facility as used in [[Jensen's_Device|Jensen's Device]], which would be something like <code>INTG8(SIN(X) + 3*SQRT(X) + 7,''etc...''</code> and would also require passing variable X. Perhaps a keyword BYNAME might be introduced one day. Until then a properly-named function must be declared and its name only be given. And of course, candidate functions must have the correct number and type of parameters, or else... |
|||
This works because Fortran passes parameters by reference (i.e. by giving the machine address of the entity), so that for functions, the code's entry point for the function is passed. With normal variables this means that a function (or subroutine) might modify the value of a parameter, as well as returning the function's result - and also mess with any COMMON data or other available storage, so a function EATACARD(IN) might read a line of data into a shared work area (called say ACARD) from I/O unit number IN and return ''true'', otherwise ''false'' should it hit end-of-file. |
|||
But it is also possible that parameters are passed via copy-in copy-out instead of by reference, with subtle changes in behaviour. This may also be done even on systems that do employ passing by reference. For instance, with <syntaxhighlight lang="fortran"> TYPE MIXED |
|||
CHARACTER*12 NAME |
|||
INTEGER STUFF |
|||
END TYPE MIXED |
|||
TYPE(MIXED) LOTS(12000)</syntaxhighlight> |
|||
One might hope to try <code>IT = BCHOP(LOTS.NAME,"Fred")</code> where BCHOP is a well-tested function for performing a binary search that should run swiftly. Alas, no. The successive values of NAME are not contiguous while BCHOP expects to receive an array of values that are contiguous - that is, with a "stride" of one. So, the compiler inserts code to copy all the LOTS.NAME elements into such a work area and passes the location of that to BCHOP (which searches it swiftly), then on return, the work area is copied back to LOTS.NAME just in case there had been a change. This latter can be avoided if within BCHOP its array is given the attribute INTENT(IN) for read-only but the incoming copy still means an effort of order N, while for the search the effort is just Log(N). This can have a less-than-subtle effect if large arrays are involved. |
|||
=={{header|Fortress}}== |
|||
<syntaxhighlight lang="fortress"> |
|||
component call_a_function |
|||
export Executable |
|||
(* Declaring test functions that allow the various ways to call functions in Fortress to be demonstrated. *) |
|||
addition(i:ZZ32, j:ZZ32): ZZ32 = i+j |
|||
addition(i:ZZ32): ZZ32 = i+1 |
|||
(* Strings are concatenated by using a space as an infix operator. *) |
|||
addition(i:String, j:String): String = i j |
|||
printAString(s:String): () = println(s) |
|||
(* Functions can be passed to other functions as arguments. When passing a function as an argument, the argument's type should be |
|||
represented as follows: "typeOfArgument(s)->returnType," which, in this case, is "String->()." You could also technically use the |
|||
"Any" type, but that isn't type-safe. *) |
|||
printAString(s:String, f:String->()) = f(s) |
|||
(* Defined functions can then be called as follows. *) |
|||
var x:ZZ32 = addition(1, 2) |
|||
var str:String = addition("This is ", "another string.") |
|||
run() = do |
|||
(* You can call built-in functions the same way that you call functions that you define. *) |
|||
println("x at start: " x) |
|||
x := addition(x, 2) |
|||
println("x at middle: " x) |
|||
printAString("This " "is " "a " "string.") |
|||
printAString(str) |
|||
printAString("\nThis is a string that is being printed by a function of the same name \nthat takes a function as an argument.\n", |
|||
printAString) |
|||
x := addition(4) |
|||
println("x at end: " x) |
|||
end |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|Free Pascal}}== |
|||
See [[#Delphi|Delphi]]. |
|||
Note, calling a <tt>function</tt> as if it was a <tt>procedure</tt> [i. e. ''discarding'' the return value] is only permitted if you set the compiler setting <tt>{$extendedSyntax on}</tt>/<tt>{$X+}</tt>. |
|||
This is the default. |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="freebasic"> |
|||
Sub Saludo() |
|||
Print "Hola mundo!" |
|||
End Sub |
|||
Function Copialo(txt As String, siNo As Short, final As String = "") As String |
|||
Dim nuevaCadena As String |
|||
For cont As Short = 1 To siNo |
|||
nuevaCadena &= txt |
|||
Next |
|||
Return Trim(nuevaCadena) & final |
|||
End Function |
|||
Sub testNumeros(a As Integer, b As Integer, c As Integer = 0) |
|||
Print a, b, c |
|||
End Sub |
|||
Sub testCadenas(txt As String) |
|||
For cont As Byte = 0 To Len(txt) |
|||
Print Chr(txt[cont]); ""; |
|||
Next cont |
|||
End Sub |
|||
Saludo |
|||
Print Copialo("Saludos ", 6) |
|||
Print Copialo("Saludos ", 3, "!!") |
|||
? |
|||
testNumeros(1, 2, 3) |
|||
testNumeros(1, 2) |
|||
? |
|||
testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'") |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Hola mundo! |
|||
Saludos Saludos Saludos Saludos Saludos Saludos |
|||
Saludos Saludos Saludos!! |
|||
1 2 3 |
|||
1 2 0 |
|||
1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'</pre> |
|||
=={{header|FutureBasic}}== |
|||
No arguments |
|||
<syntaxhighlight lang="futurebasic"> |
|||
void local fn MyFunction |
|||
print @"MyFunction" |
|||
end fn |
|||
fn MyFunction |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
Fixed arguments - args passed by value |
|||
<syntaxhighlight lang="futurebasic"> |
|||
void local fn MyFunction( arg1 as long, arg2 as long, arg3 as long ) |
|||
print @"MyFunction" |
|||
end fn |
|||
fn MyFunction( 1, 2, 3 ) |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
Variable arguments - args passed by value |
|||
<syntaxhighlight lang="futurebasic"> |
|||
void local fn MyFunction( count as long, ... ) |
|||
va_list ap |
|||
long i, value |
|||
va_start( ap, count ) |
|||
for i = 1 to count |
|||
value = fn va_arglong( ap ) |
|||
print value |
|||
next |
|||
va_end( ap ) |
|||
end fn |
|||
fn MyFunction( 3, 12, 24, 36 ) |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
Return value - arg passed by value |
|||
<syntaxhighlight lang="futurebasic"> |
|||
local fn MultiplyByThree( value as long ) as long |
|||
end fn = value * 3 |
|||
print fn MultiplyByThree( 13 ) |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
Argument passed by reference |
|||
<syntaxhighlight lang="futurebasic"> |
|||
void local fn MultiplyByThree( value as ^long ) |
|||
*value *= 3 |
|||
end fn |
|||
long num |
|||
num = 9 |
|||
fn MultiplyByThree( @num ) |
|||
print num |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
=={{header|Gambas}}== |
|||
'''[https://gambas-playground.proko.eu/?gist=1bbbeb240f6fbca4b893271f1a19833b Click this link to run this code]'''<br> |
|||
Some of the uses of Procedures/Functions in Gambas |
|||
<syntaxhighlight lang="gambas">Public Sub Main() |
|||
Hello |
|||
Print CopyIt("Hello ", 6) |
|||
Print CopyIt("Hello ", 3, "!!") |
|||
End |
|||
'_____________________________________________________________________________________ |
|||
Public Sub CopyIt(sString As String, siNo As Short, Optional sEnd As String) As String |
|||
Dim siCount As Short |
|||
Dim sNewString As String |
|||
For siCount = 1 To siNo |
|||
sNewString &= sString |
|||
Next |
|||
Return Trim(sNewString) & sEnd |
|||
End |
|||
'_____________________________________________________________________________________ |
|||
Public Sub Hello() |
|||
Print "Hello world!" |
|||
End</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
Hello world! |
|||
Hello Hello Hello Hello Hello Hello |
|||
Hello Hello Hello!! |
|||
</pre> |
|||
=={{header|Go}}== |
|||
The following examples use functions from the standard packages |
|||
plus a few dummy local functions: |
|||
::<syntaxhighlight lang="go">import ( |
|||
"image" |
|||
"image/gif" |
|||
"io/ioutil" |
|||
"strings" |
|||
"unicode" |
|||
) |
|||
func f() (int, float64) { return 0, 0 } |
|||
func g(int, float64) int { return 0 } |
|||
func h(string, ...int) {}</syntaxhighlight> |
|||
* Calling with no arguments and calling with a fixed number of arguments: |
|||
::<syntaxhighlight lang="go"> f() |
|||
g(1, 2.0) |
|||
// If f() is defined to return exactly the number and type of |
|||
// arguments that g() accepts than they can be used in place: |
|||
g(f()) |
|||
// But only without other arguments, this won't compile: |
|||
//h("fail", f()) |
|||
// But this will: |
|||
g(g(1, 2.0), 3.0)</syntaxhighlight> |
|||
* Calling with a variable number of arguments: |
|||
::This is only possible with functions defined with a trailing optional/variable length argument of a single type (as <code>h</code> above). <syntaxhighlight lang="go"> h("ex1") |
|||
h("ex2", 1, 2) |
|||
h("ex3", 1, 2, 3, 4) |
|||
// such functions can also be called by expanding a slice: |
|||
list := []int{1,2,3,4} |
|||
h("ex4", list...) |
|||
// but again, not mixed with other arguments, this won't compile: |
|||
//h("fail", 2, list...)</syntaxhighlight> |
|||
* Optional arguments and named arguments are not supported. |
|||
::However, it is reasonably common to see a structure used for this. In this example <code>gif.Options</code> is a structure with multiple members which can initialized/assigned by name or omitted (or the whole third argument can just be <code>nil</code>). <syntaxhighlight lang="go"> gif.Encode(ioutil.Discard, image.Black, &gif.Options{NumColors: 16})</syntaxhighlight> |
|||
* Optional arguments are supported. |
|||
::<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
type Params struct { |
|||
a, b, c int |
|||
} |
|||
func doIt(p Params) int { |
|||
return p.a + p.b + p.c |
|||
} |
|||
func main() { |
|||
fmt.Println(doIt(Params{a: 1, c: 9})) // prt 10 |
|||
}</syntaxhighlight> |
|||
* Named arguments are supported. |
|||
::<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
func bar(a, b, c int) { |
|||
fmt.Printf("%d, %d, %d", a, b, c) |
|||
} |
|||
func main() { |
|||
args := make(map[string]int) |
|||
args["a"] = 3 |
|||
args["b"] = 2 |
|||
args["c"] = 1 |
|||
bar(args["a"], args["b"], args["c"]) // prt 3, 2, 1 |
|||
}</syntaxhighlight> |
|||
* Within a statement context. |
|||
::Assignment statements are shown later. Only functions returning a single value can be used in a single value context: <syntaxhighlight lang="go"> if 2*g(1, 3.0)+4 > 0 {}</syntaxhighlight> |
|||
* In a first-class context: |
|||
::<syntaxhighlight lang="go"> fn := func(r rune) rune { |
|||
if unicode.IsSpace(r) { |
|||
return -1 |
|||
} |
|||
return r |
|||
} |
|||
strings.Map(fn, "Spaces removed") |
|||
strings.Map(unicode.ToLower, "Test") |
|||
strings.Map(func(r rune) rune { return r + 1 }, "shift")</syntaxhighlight> |
|||
* Obtaining the value: |
|||
::<syntaxhighlight lang="text"> a, b := f() // multivalue return |
|||
_, c := f() // only some of a multivalue return |
|||
d := g(a, c) // single return value |
|||
e, i := g(d, b), g(d, 2) // multiple assignment</syntaxhighlight> |
|||
* Built-in functions and user defined functions can not be distinguished. |
|||
::Functions from the standard packages look like any other. The few truly built-in functions are only different in that they have no package specifier like local functions (and they sometimes have extra capabilities). <syntaxhighlight lang="go"> list = append(list, a, d, e, i) |
|||
i = len(list)</syntaxhighlight> |
|||
* Go has no subroutines, just functions and methods. |
|||
* Go arguments are passed by value. |
|||
::As with C, a pointer can be used to achieve the effect of reference passing. (Like pointers, slice arguments have their contents passed by reference, it's the slice header that is passed by value). |
|||
* Go arguments are passed by value or by reference |
|||
::<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
// int parameter, so arguments will be passed to it by value. |
|||
func zeroval(ival int) { |
|||
ival = 0 |
|||
} |
|||
// has an *int parameter, meaning that it takes an int pointer. |
|||
func zeroptr(iptr *int) { |
|||
*iptr = 0 |
|||
} |
|||
func main() { |
|||
i := 1 |
|||
fmt.Println("initial:", i) // prt initial: 1 |
|||
zeroval(i) |
|||
fmt.Println("zeroval:", i) // prt zeroval: 1 |
|||
zeroptr(&i) |
|||
fmt.Println("zeroptr:", i) // prt zeroptr: 0 |
|||
fmt.Println("pointer:", &i) // prt pointer: 0xc0000140b8 |
|||
}</syntaxhighlight> |
|||
* Partial and Currying is not directly supported. |
|||
::However something similar can be done, see [[Partial function application#Go]] |
|||
::<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
func mkAdd(a int) func(int) int { |
|||
return func(b int) int { |
|||
return a + b |
|||
} |
|||
} |
|||
func sum(x, y int) int { |
|||
return x + y |
|||
} |
|||
func partialSum(x int) func(int) int { |
|||
return func(y int) int { |
|||
return sum(x, y) |
|||
} |
|||
} |
|||
func main() { |
|||
// Is partial application possible and how |
|||
add2 := mkAdd(2) |
|||
add3 := mkAdd(3) |
|||
fmt.Println(add2(5), add3(6)) // prt 7 9 |
|||
// Currying functions in go |
|||
partial := partialSum(13) |
|||
fmt.Println(partial(5)) //prt 18 |
|||
}</syntaxhighlight> |
|||
=={{header|Groovy}}== |
|||
There are two types of first-class functions in Groovy. |
|||
# The first are functions defined in scripts, although they behave as if they are methods of the script "class". |
|||
# The second are closures, which are similar to lambdas in Java, except that they are defined as their own class type and must be explicitly converted to single-method "functional" interfaces. There are many methods within the Groovy API that accept closures as arguments. |
|||
* Calling a function that requires no arguments |
|||
<syntaxhighlight lang="groovy">noArgs()</syntaxhighlight> |
|||
* Calling a function with a fixed number of arguments |
|||
<syntaxhighlight lang="groovy">fixedArgs(1, "Zing", Color.BLUE, ZonedDateTime.now(), true)</syntaxhighlight> |
|||
* Calling a function with optional arguments |
|||
<syntaxhighlight lang="groovy">optArgs("It's", "a", "beautiful", "day") |
|||
optArgs("It's", "a", "beautiful") |
|||
optArgs("It's", "a") |
|||
optArgs("It's")</syntaxhighlight> |
|||
* Calling a function with a variable number of arguments |
|||
<syntaxhighlight lang="groovy">varArgs("It's", "a", "beautiful", "day") |
|||
varArgs("It's", "a", "beautiful") |
|||
varArgs("It's", "a") |
|||
varArgs("It's")</syntaxhighlight> |
|||
* Calling a function with named arguments |
|||
It's complicated |
|||
* Using a function in statement context |
|||
<syntaxhighlight lang="groovy">def mean = calcAverage(1.2, 4.5, 3, 8.9, 22, 3)</syntaxhighlight> |
|||
* Using a function in first-class context within an expression |
|||
** Create new functions from preexisting functions at run-time |
|||
<syntaxhighlight lang="groovy">def oldFunc = { arg1, arg2 -> arg1 + arg2 } |
|||
def newFunc = oldFunc.curry(30) |
|||
assert newFunc(12) == 42</syntaxhighlight> |
|||
** Store functions in collections |
|||
<syntaxhighlight lang="groovy">def funcList = [func1, func2, func3]</syntaxhighlight> |
|||
** Use functions as arguments to other functions |
|||
<syntaxhighlight lang="groovy">def eltChangeFunc = { it * 3 - 1 } |
|||
def changedList = list.collect(eltChangeFunc)</syntaxhighlight> |
|||
** Use functions as return values of other functions |
|||
<syntaxhighlight lang="groovy">def funcMaker = { String s, int reps, boolean caps -> |
|||
caps ? { String transString -> ((transString + s) * reps).toUpperCase() } |
|||
: { String transString -> (transString + s) * reps } |
|||
} |
|||
def func = funcMaker("a", 2, true) |
|||
assert func("pook") == "POOKAPOOKA"</syntaxhighlight> |
|||
* Obtaining the return value of a function |
|||
<syntaxhighlight lang="groovy">def retVal = func(x, y, z)</syntaxhighlight> |
|||
* Distinguishing built-in functions and user-defined functions |
|||
There are no "built-in" functions. All is illusion. |
|||
* Stating whether arguments are passed by value or by reference |
|||
As with Java everything is passed by value, but object values are actually references (pointers). So, |
|||
** if the argument is a primative it is passed by value and changes are not manifested in the caller's context. |
|||
** if the argument is an object reference, the reference is passed by value and changes to the reference (re-assignment, for example) are not manifested in the caller's context, but changes in the object are. |
|||
* Is partial application possible and how |
|||
Partial application in Groovy is performed via currying (demonstrated above) |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
<syntaxhighlight lang="haskell"> |
|||
-- Calling a function with a fixed number of arguments |
|||
multiply x y = x * y |
|||
multiply 10 20 -- returns 200 |
|||
-- Calling a function that requires no arguments |
|||
-- Normally, you use constant instead of function without arguments: |
|||
twopi = 6.28 |
|||
-- But you can also pass special value as the first argument indicating function call: |
|||
twopi () = 6.28 -- definition |
|||
twopi :: Num a => () -> a -- its type |
|||
twopi () -- returns 6.28 |
|||
-- Partial application and auto-currying is built-in. |
|||
multiply_by_10 = (10 * ) |
|||
map multiply_by_10 [1, 2, 3] -- [10, 20, 30] |
|||
multiply_all_by_10 = map multiply_by_10 |
|||
multiply_all_by_10 [1, 2, 3] -- [10, 20, 30] |
|||
-- TODO: |
|||
-- Calling a function with optional arguments |
|||
-- Calling a function with a variable number of arguments |
|||
-- Calling a function with named arguments |
|||
-- Using a function in statement context |
|||
-- Using a function in first-class context within an expression |
|||
-- Obtaining the return value of a function |
|||
-- Distinguishing built-in functions and user-defined functions |
|||
-- Distinguishing subroutines and functions |
|||
-- Stating whether arguments are passed by value or by reference |
|||
</syntaxhighlight> |
|||
=={{header|i}}== |
|||
<syntaxhighlight lang="i">//The type of the function argument determines whether or not the value is passed by reference or not. |
|||
//Eg. numbers are passed by value and lists/arrays are passed by reference. |
|||
software { |
|||
print() //Calling a function with no arguments. |
|||
print("Input a number!") //Calling a function with fixed arguments. |
|||
print(1,2,3,4,5,6,7,8,9,0) //Calling a function with variable arguments. |
|||
input = read() //Obtaining the return value of a function. |
|||
myprint = print |
|||
myprint("It was: ", input) //Calling first class functions, the same as calling ordinary functions. |
|||
//The only distinction that can be made between two functions is if they are 'real' or not. |
|||
if type(myprint) = concept |
|||
print("myprint is a not a real function") |
|||
else if type(myprint) = function |
|||
print("myprint is a real function") |
|||
end |
|||
//Partial functions can be created with static parts. |
|||
DebugPrint = print["[DEBUG] ", text] |
|||
DebugPrint("partial function!") //This would output '[DEBUG] partial function!' |
|||
if type(DebugPrint) = concept |
|||
print("DebugPrint is a not a real function") |
|||
else if type(DebugPrint) = function |
|||
print("DebugPrint is a real function") |
|||
end |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
|||
Icon and Unicon have generalized procedures and syntax that are used to implement functions, subroutines and generators. |
|||
* Procedures can return values or not and callers may use the returned values or not. |
|||
* Procedures in Icon and Unicon are first class values and can be assigned to variables which can then be used to call procedures. This also facilitates some additional calling syntax. |
|||
* Additionally, co-expressions are supported which allow for co-routine like transfers of control between two or more procedures. There are some differences in syntax for co-expression calls. |
|||
* There are no differences between calling built-in vs. user defined functions |
|||
* Named arguments is not natively supported; however, they can be supported using a user defined procedure as shown in [[Named_parameters#Icon_and_Unicon|Named parameters]] |
|||
* Method calling is similar with some extended syntax |
|||
* Arguments are basically passed by value or reference based on their type. Immutable values like strings, and numbers are passed by value. Mutable data types like structures are essentially references and although these are passed by value the effective behavior is like a call by reference. |
|||
For more information see [[Icon%2BUnicon/Intro|Icon and Unicon Introduction on Rosetta]] |
|||
<syntaxhighlight lang="icon">procedure main() # demonstrate and describe function calling syntax and semantics |
|||
# normal procedure/function calling |
|||
f() # no arguments, also command context |
|||
f(x) # fixed number of arguments |
|||
f(x,h,w) # variable number of arguments (varargs) |
|||
y := f(x) # Obtaining the returned value of a function |
|||
# procedures as first class values and string invocation |
|||
f!L # Alternate calling syntax using a list as args |
|||
(if \x then f else g)() # call (f or g)() |
|||
f := write # assign a procedure |
|||
f("Write is now called") # ... and call it |
|||
"f"() # string invocation, procedure |
|||
"-"(1) # string invocation, operator |
|||
# Co-expressions |
|||
f{e1,e2} # parallel evaluation co-expression call |
|||
# equivalent to f([create e1, create e2]) |
|||
expr @ coexp # transmission of a single value to a coexpression |
|||
[e1,e2]@coexp # ... of multiple values (list) to a coexpression |
|||
coexp(e1,e2) # ... same as above but only in Unicon |
|||
# Other |
|||
f("x:=",1,"y:=",2) # named parameters (user defined) |
|||
end</syntaxhighlight> |
|||
=={{header|J}}== |
=={{header|J}}== |
||
Line 351: | Line 3,018: | ||
A verb, in J, typically supports two syntactic variants: |
A verb, in J, typically supports two syntactic variants: |
||
< |
<syntaxhighlight lang="j"> verb noun |
||
noun verb noun</ |
noun verb noun</syntaxhighlight> |
||
And a noun, in J, is an array. |
And a noun, in J, is an array. |
||
Line 358: | Line 3,025: | ||
An argument list can be represented by an array. Thus, when dealing with multiple arguments, a typical form is: |
An argument list can be represented by an array. Thus, when dealing with multiple arguments, a typical form is: |
||
<lang |
<syntaxhighlight lang="j"> function argumentList</syntaxhighlight> |
||
Here, <code>function</code> is a verb and <code>argumentList</code> is a noun. |
Here, <code>function</code> is a verb and <code>argumentList</code> is a noun. |
||
Line 364: | Line 3,031: | ||
For example: |
For example: |
||
<lang |
<syntaxhighlight lang="j"> sum(1,2,3)</syntaxhighlight> |
||
Here <code>sum</code> is a verb and <code>(1,2,3)</code> is a noun. |
Here <code>sum</code> is a verb and <code>(1,2,3)</code> is a noun. |
||
Line 370: | Line 3,037: | ||
Thus: |
Thus: |
||
''A function that requires no arguments'' can be simulated by calling a function with empty argument list: <lang |
''A function that requires no arguments'' can be simulated by calling a function with empty argument list: <syntaxhighlight lang="j">f''</syntaxhighlight> Note that an empty list of characters is not the only constant in the language which is an empty list. That said, most operations in the language do not care what type of data is not present, in an array which contains nothing. |
||
''A function with a fixed number of arguments'' gets special treatment in J when the fixed number is 1 or 2. < |
''A function with a fixed number of arguments'' gets special treatment in J when the fixed number is 1 or 2. <syntaxhighlight lang="j">f 'one argument'</syntaxhighlight>and <syntaxhighlight lang="j">'this example has two arguments' f 'the other argument'</syntaxhighlight> Alternatively, the function can be written such that an argument list is an error when it's the wrong length. |
||
''A function with a variable number of arguments (varargs)'': See above. |
''A function with a variable number of arguments (varargs)'': See above. |
||
If argument types conflict they will need to be put in boxes and the function will have to take its arguments out of the boxes. Here's an unboxed example with five arguments: < |
If argument types conflict they will need to be put in boxes and the function will have to take its arguments out of the boxes. Here's an unboxed example with five arguments: <syntaxhighlight lang="j"> f 1,2,3,4,5</syntaxhighlight> and here's a boxed example with five arguments: <syntaxhighlight lang="j">f (<1),(<2),(<3),(<4),(<5) </syntaxhighlight> Note that the last set of parenthesis is unnecessary <syntaxhighlight lang="j">f (<1),(<2),(<3),(<4),<5</syntaxhighlight> Note also that J offers some syntactic sugar for this kind of list <syntaxhighlight lang="j">f 1; 2; 3; 4; <5</syntaxhighlight>. Note also that if the last argument in a semicolon list is not boxed there is no need to explicitly box it, since that is unambiguous (it must be boxed so that it conforms with the other members of the list). <syntaxhighlight lang="j">f 1; 2; 3; 4; 5</syntaxhighlight> |
||
''A function with named arguments'' can be accomplished by calling a function with the names of the arguments. < |
''A function with named arguments'' can be accomplished by calling a function with the names of the arguments. <syntaxhighlight lang="j">f 'george';'tom';'howard'</syntaxhighlight> Other interpretations of this concept are also possible. For example, the right argument for a verb might be a list of argument names and the left argument might be a corresponding list of argument values: <syntaxhighlight lang="j">1 2 3 f 'george';'tom';'howard'</syntaxhighlight> Or, for example a function which requires an object could be thought of as a function with named arguments since an object's members have names:<syntaxhighlight lang="j"> obj=: conew'blank' |
||
george__obj=: 1 |
george__obj=: 1 |
||
tom__obj=: 2 |
tom__obj=: 2 |
||
howard__obj=: 3 |
howard__obj=: 3 |
||
f obj |
f obj |
||
coerase obj</ |
coerase obj</syntaxhighlight> Name/value pairs can also be used for this purpose and can be implemented in various ways, including passing names followed by values <syntaxhighlight lang="j">f 'george';1;'tom';2;'howard';3</syntaxhighlight> and passing a structure of pairs <syntaxhighlight lang="j">f ('george';1),('tom';2),:(howard';3)</syntaxhighlight> Or, for example, the pairs could be individually boxed: <syntaxhighlight lang="j">f ('george';1);('tom';2);<howard';3</syntaxhighlight> |
||
''Using a function in command context'' is no different from using a function in any other context, in J. ''Using a function in first class context within an expression'' is no different from using a function in any other context, in J. |
''Using a function in command context'' is no different from using a function in any other context, in J. ''Using a function in first class context within an expression'' is no different from using a function in any other context, in J. |
||
''Obtaining the return value of a function'' is no different from using a function in j. For example, here we add 1 to the result of a function: <lang |
''Obtaining the return value of a function'' is no different from using a function in j. For example, here we add 1 to the result of a function: <syntaxhighlight lang="j">1 + f 2</syntaxhighlight> |
||
The only ''differences that apply to calling builtin functions rather than user defined functions'' is spelling of the function names. |
The only ''differences that apply to calling builtin functions rather than user defined functions'' is spelling of the function names. |
||
There are no ''differences between calling subroutines and functions'' because J defines neither <code>subroutines</code> nor <code>functions</code>. Instead, J defines <code>verbs</code>, <code>adverbs</code>, and <code>conjunctions</code> which for the purpose of this task are treated as functions. |
There are no ''differences between calling subroutines and functions'' because J defines neither <code>subroutines</code> nor <code>functions</code>. Instead, J defines <code>verbs</code>, <code>adverbs</code>, and <code>conjunctions</code> which for the purpose of this task are treated as functions. (All of the above examples used verbs. J's adverbs and conjunctions have stronger [[wp:Valence|valence]] than its verbs.) |
||
=={{header|Java}}== |
|||
<kbd><i>"Calling a function that requires no arguments."</i></kbd><br/> |
|||
The parentheses are required. |
|||
<syntaxhighlight lang="java"> |
|||
Object.methodName(); |
|||
</syntaxhighlight> |
|||
<p> |
|||
<kbd><i>"Calling a function with a fixed number of arguments."</i></kbd> |
|||
<syntaxhighlight lang="java"> |
|||
Object.methodName("rosetta", "code"); |
|||
</syntaxhighlight> |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Calling a function with optional arguments."</i></kbd><br/> |
|||
Java doesn't offer the ability to optionalize parameters, although there is something similar.<br/> |
|||
A <kbd>varargs</kbd>, or "Variable Arguments", parameter, could be of 0 length.<br/> |
|||
So if you're only parameter is a <kbd>vararg</kbd> parameter, it's possible to not supply any input. |
|||
This could be viewed, in some situations, as an optional parameter. |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Calling a function with a variable amount of arguments."</i></kbd><br/> |
|||
There is no special syntax, you simply offer the arguments as required. |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Calling a function with named arguments."</i></kbd><br/> |
|||
Java does not offer this feature. |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Using a function in a statement context."</i></kbd><br/> |
|||
Java is not a functional programming language, although Java 8 added basic closures and lambda expressions.<br/> |
|||
They are not in anyway as robust as functional languages like JavaScript.<br/> |
|||
A lambda works specifically with an <code>interface</code> that requires only 1 abstraction.<br/> |
|||
Consider the following <kbd>interface</kbd>. |
|||
<syntaxhighlight lang="java"> |
|||
interface Example { |
|||
int add(int valueA, int valueB); |
|||
} |
|||
</syntaxhighlight> |
|||
You could then implement this interface with a lambda, as opposed to creating an anonymous-class.<br/> |
|||
Consider the following method. |
|||
<syntaxhighlight lang="java"> |
|||
int sum(Example example) { |
|||
return example.add(1, 2); |
|||
} |
|||
</syntaxhighlight> |
|||
You would then provide the closure, or the functionality of the abstraction, during assignment. |
|||
<syntaxhighlight lang="java"> |
|||
Example example = (valueA, valueB) -> valueA + valueB; |
|||
sum(example); |
|||
</syntaxhighlight> |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Using a function in first-class context with an expression."</i></kbd><br /> |
|||
First-class context is out-of-scope for Java, which is statically-typed. |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Obtaining the return value of a function."</i></kbd><br /> |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
String string = Object.methodName("rosetta", "code"); |
|||
</syntaxhighlight> |
|||
<p> |
|||
<kbd><i>"Distinguishing built-in functions and user-defined functions."</i></kbd><br /> |
|||
There is no ambiguity between built-in functions and user-defined functions. |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Distinguishing subroutines and functions."</i></kbd><br /> |
|||
Java refers to all procedures as methods.<br/> |
|||
As with other languages, such as Visual Basic, which uses <kbd>Sub</kbd>, and <kbd>Function</kbd>, |
|||
there is no ambiguity from methods which return values and those that don't. |
|||
</p> |
|||
<p> |
|||
The defining factor is within the method definition.<br/> |
|||
A return-type is declared before the method name, and <code>void</code> is used when there is no returned value. |
|||
<syntaxhighlight lang="java"> |
|||
String methodA(); |
|||
void methodB(); |
|||
</syntaxhighlight> |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Stating whether arguments are passed by value or by reference."</i></kbd><br /> |
|||
The concept of pass-by-value and pass-by-reference is somewhat a redefined measure within Java.<br/> |
|||
For the most part, everything is pass-by-value; there are no pointers and dereferencing, as with C, C++, and Rust.<br/> |
|||
Although, if you're passing an object, it can be viewed as pass-by-reference, since the operation is occurring on the actual object, |
|||
and a new value is not created.<br/> |
|||
Java is essentially an language that was influenced by languages which use pass-by-reference, so it's abstraction is lacking. |
|||
</p> |
|||
<p> |
|||
<kbd><i>"Is partial application possible and how."</i></kbd><br /> |
|||
Not without a closure.<br/> |
|||
I found the following example on [https://en.wikipedia.org/wiki/Partial_application#Implementations Wikipedia - Partial application]. |
|||
</p> |
|||
<syntaxhighlight lang="java"> |
|||
<X, Y, Z> Function<Y, Z> exampleA(BiFunction<X, Y, Z> exampleB, X value) { |
|||
return y -> exampleB.apply(value, y); |
|||
} |
|||
</syntaxhighlight> |
|||
<br /> |
|||
Here is an alternate demonstration.<br /> |
|||
Java does not have functions, but Java classes have "methods" which are equivalent. |
|||
* Calling a function that requires no arguments |
|||
<syntaxhighlight lang="java">myMethod()</syntaxhighlight> |
|||
We didn't specify an object (or a class) as the location of the method, so <tt>this.myMethod()</tt> is assumed. This applies to all the following examples. |
|||
* Calling a function with a fixed number of arguments |
|||
<syntaxhighlight lang="java">myMethod(97, 3.14)</syntaxhighlight> |
|||
* Calling a function with optional arguments |
|||
This is possible if the method name is overloaded with different argument lists. For example: |
|||
<syntaxhighlight lang="java">int myMethod(int a, double b){ |
|||
// return result of doing sums with a and b |
|||
} |
|||
int myMethod(int a){ |
|||
return f(a, 1.414); |
|||
}</syntaxhighlight> |
|||
The compiler figures out which method to call based on the types of the arguments, so in this case the second argument appears to be optional. If you omit it, the value <tt>1.414</tt> is used. |
|||
<syntaxhighlight lang="java">System.out.println( myMethod( 97, 3.14 ) ); |
|||
System.out.println( myMethod( 97 ) );</syntaxhighlight> |
|||
* Calling a function with a variable number of arguments |
|||
This is possible if the method is defined with varargs syntax. For example: |
|||
<syntaxhighlight lang="java">void printAll(String... strings){ |
|||
for ( String s : strings ) |
|||
System.out.println( s ); |
|||
}</syntaxhighlight> |
|||
The type of <tt>strings</tt> is actually a string array, but the caller just passes strings: |
|||
<syntaxhighlight lang="java">printAll( "Freeman" ); |
|||
printAll( "Freeman", "Hardy", "Willis" );</syntaxhighlight> |
|||
To avoid ambiguity, only the last argument to a function can have varargs. |
|||
* Calling a function with named arguments |
|||
Not directly possible, but you could simulate this (somewhat verbosely): |
|||
<syntaxhighlight lang="java">int myMethod( Map<String,Object> params ){ |
|||
return |
|||
((Integer)params.get("x")).intValue() |
|||
+ ((Integer)params.get("y")).intValue(); |
|||
}</syntaxhighlight> |
|||
Called like this: |
|||
<syntaxhighlight lang="java">System.out.println( myMethod(new HashMap<String,Object>(){{put("x",27);put("y",52);}}) );</syntaxhighlight> |
|||
Yuk. |
|||
* Using a function in statement context |
|||
If this means "use a function where a statement is expected", see all the other examples |
|||
* Using a function in first-class context within an expression |
|||
Not possible - must be wrapped in a class |
|||
* Obtaining the return value of a function |
|||
<syntaxhighlight lang="java">int i = myMethod(x);</syntaxhighlight> |
|||
* Distinguishing built-in functions and user-defined functions |
|||
No distinction - all methods belong to classes, and there is no real distinction between built-in and user-defined classes. |
|||
* Distinguishing subroutines and functions |
|||
If the return type is void, you might consider a method as a subroutine rather than a function. |
|||
* Stating whether arguments are passed by value or by reference |
|||
All arguments are passed by value, but since object variables contain a reference to an object (not the object itself), objects appear to be passed by reference. For example: |
|||
<syntaxhighlight lang="java">myMethod(List<String> list){ |
|||
// If I change the contents of the list here, the caller will see the change |
|||
}</syntaxhighlight> |
|||
* Is partial application possible and how |
|||
Don't know |
|||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
Line 398: | Line 3,240: | ||
The arguments to a JavaScript function are stored in a special array-like object which does not enforce arity in any way; a function declared to take ''n'' arguments may be called with none‒and vice versa‒without raising an error. |
The arguments to a JavaScript function are stored in a special array-like object which does not enforce arity in any way; a function declared to take ''n'' arguments may be called with none‒and vice versa‒without raising an error. |
||
< |
<syntaxhighlight lang="javascript">var foo = function() { return arguments.length }; |
||
foo() // 0 |
foo() // 0 |
||
foo(1, 2, 3) // 3</ |
foo(1, 2, 3) // 3</syntaxhighlight> |
||
Neither optional (see above) nor named arguments are supported, though the latter (and the inverse of the former) may be simulated with the use of a helper object to be queried for the existence and/or values of relevant keys. <span style="color: transparent;">Seriously, what is "statement context"?</span> |
Neither optional (see above) nor named arguments are supported, though the latter (and the inverse of the former) may be simulated with the use of a helper object to be queried for the existence and/or values of relevant keys. <span style="color: transparent;">Seriously, what is "statement context"?</span> |
||
JavaScript functions are first-class citizens; they can be stored in variables (see above) and passed as arguments. |
JavaScript functions are first-class citizens; they can be stored in variables (see above) and passed as arguments. |
||
< |
<syntaxhighlight lang="javascript">var squares = [1, 2, 3].map(function (n) { return n * n }); // [1, 4, 9]</syntaxhighlight> |
||
Naturally, they can also be returned, thus partial application is supported. |
Naturally, they can also be returned, thus partial application is supported. |
||
<syntaxhighlight lang="javascript"> |
|||
<lang JavaScript> |
|||
var make_adder = function(m) { |
var make_adder = function(m) { |
||
return function(n) { return m + n } |
return function(n) { return m + n } |
||
}; |
}; |
||
var add42 = make_adder(42); |
var add42 = make_adder(42); |
||
add42(10) // 52</ |
add42(10) // 52</syntaxhighlight> |
||
Calling a user-defined function's <tt>toString()</tt> method returns its source verbatim; that the implementation is elided for built-ins provides a mechanism for distinguishing between the two. |
Calling a user-defined function's <tt>toString()</tt> method returns its source verbatim; that the implementation is elided for built-ins provides a mechanism for distinguishing between the two. |
||
< |
<syntaxhighlight lang="javascript">foo.toString() |
||
"function () { return arguments.length }" |
"function () { return arguments.length }" |
||
alert.toString() |
alert.toString() |
||
"function alert() { [native code] }"</ |
"function alert() { [native code] }"</syntaxhighlight> |
||
Arguments are passed by value, but the members of collections are essentially passed by reference and thus propagate modification. |
Arguments are passed by value, but the members of collections are essentially passed by reference and thus propagate modification. |
||
< |
<syntaxhighlight lang="javascript">var mutate = function(victim) { |
||
victim[0] = null; |
victim[0] = null; |
||
victim = 42; |
victim = 42; |
||
}; |
}; |
||
var foo = [1, 2, 3]; |
var foo = [1, 2, 3]; |
||
mutate(foo) // foo is now [null, 2, 3], not 42</ |
mutate(foo) // foo is now [null, 2, 3], not 42</syntaxhighlight> |
||
=={{header|jq}}== |
|||
jq functions are pure functions that are somewhat unusual in two respects: |
|||
* They are like commands in modern operating systems, in that they are <tt>parameterized filters</tt> that can accept input from the previous command and provide output to the next command if there is one in the pipeline of commands. |
|||
* Functions can not only process a stream of inputs, one at a time, but each argument can also accept a stream of inputs. The outputs are then a Cartesian product of the various inputs. |
|||
In this section, we use the notation fn/N to refer to a function named "fn" with N formal parameters. |
|||
'''Calling a function that requires no arguments''' |
|||
0-arity jq functions are invoked simply by specifying their name. |
|||
* Example: . |
|||
(Yes, "." is a 0-arity jq function.) |
|||
'''Calling a function with a fixed number of arguments''' |
|||
The conventional syntax is used except that ";" is the parameter separator. "," is used to construct a stream of values. |
|||
* Example: range(0;100;2) |
|||
'''Calling a function with optional arguments''' |
|||
Recent versions of jq allow one to define functions with the same name but different arities, and therefore if both fn/1 and fn/2 are defined, we may say that fn requires one parameter but accepts 2. In all cases, the syntax for function invocation is the same. |
|||
* Example: range(0; 10) and range(0; 10; 2) |
|||
Since jq functions can accept JSON arrays and objects, there are other ways to simulate optional arguments. |
|||
'''Calling a function with a variable number of arguments''' |
|||
See above. |
|||
'''Calling a function with named arguments''' |
|||
This is not directly supported but can be simulated by defining the function to accept JSON objects. For example, if fn were such a function, |
|||
we might invoke fn like so: <tt>fn( {"required": 1, "optional": 2} )</tt>. |
|||
'''Using a function in statement context''' |
|||
The assignment to a local variable (e.g. <tt>(2*2) as $two</tt>) is similar to a statement context in that the expression as a whole does nothing to the flow of values from its input to its output. |
|||
'''Using a function in first-class context within an expression''' |
|||
jq functions cannot be assigned to variables but are otherwise "first-class" in that the composition of functions can be passed as arguments to other functions. No special syntax is required. |
|||
* Example: <tt>2 | recurse(. * .)</tt> # generate the sequence 2, 4, 16, 256, ... |
|||
'''Obtaining the return value of a function''' |
|||
The value (or stream of values) returned by a function is (or are) automatically available to the next function in the pipeline (e.g. sin | cos); the returned value(s) can also be assigned to a local variable (e.g. sin as $v). |
|||
'''Distinguishing built-in functions and user-defined functions''' |
|||
Currently there is no such distinction, but user-defined functions always have the conventional form, whereas some built-in functions have special syntax. |
|||
'''Distinguishing subroutines and functions''' |
|||
A jq function can be written so as never to return anything (either because it returns without generating a value or because it generates an infinite stream of values), but there is no distinctive marker associated with such functions. |
|||
'''Stating whether arguments are passed by value or by reference''' |
|||
Arguments are in effect passed by value. |
|||
'''Is partial application possible and how''' |
|||
See [[Currying#jq]]. |
|||
=={{header|Julia}}== |
|||
<syntaxhighlight lang="julia"> |
|||
# Calling a function that requires no arguments: |
|||
f() = print("Hello world!") |
|||
f() |
|||
# Calling a function with a fixed number of arguments: |
|||
function f(x, y, z) |
|||
x*y - z^2 |
|||
end |
|||
f(3, 4, 2) |
|||
# Calling a function with optional arguments: |
|||
# Note Julia uses multiple dispatch based on argument number and type, so |
|||
# f() is always different from f(x) unless default arguments are used, as in: |
|||
pimultiple(mult=1.0) = pi * mult # so pimultiple() defaults to pi * (1.0) or pi |
|||
# Calling a function with a variable number of arguments: |
|||
f(a,b,x...) = reduce(+, 0, x) - a - b |
|||
# here a and b are single arguments, but x is a tuple of x plus whatever follows x, so: |
|||
a = b = c = d = e = 3 |
|||
f(a,b,c) # x within the function is (c) so == 0 + c - a - b |
|||
f(a,b,c,d,e) # x is a tuple == (c,d,e) so == (0 + c + d + e) - a - b |
|||
f(a,b) # x is () so == 0 - a - b |
|||
# Calling a function with named arguments: |
|||
# Functions with keyword arguments are defined using a semicolon in the function signature, |
|||
# as in |
|||
# function plot(x, y; style="solid", width=1, color="black") |
|||
# |
|||
# When the function is called, the semicolon is optional, so plot here can be |
|||
# either called with plot(x, y, width=2) or less commonly as plot(x, y; width=2). |
|||
# Using a function in statement context: |
|||
# Any function can be used as a variable by its name. |
|||
circlearea(x) = x^2 * pi |
|||
map(circlearea, [r1, r2, r3, r4]) |
|||
# Using a function in first-class context within an expression: |
|||
cylindervolume = circlearea(r) * h |
|||
# Obtaining the return value of a function: |
|||
radius = 2.5 |
|||
area = circlearea(2.5) |
|||
# Distinguishing built-in functions and user-defined functions: |
|||
# Julia does not attempt to distinguish these in any special way, |
|||
# but at the REPL command line there is ? help available for builtin |
|||
# functions that would not generally be available for the user-defined ones. |
|||
# Distinguishing subroutines and functions: |
|||
# All subroutines are called functions in Julia, regardless of whether they return values. |
|||
# Stating whether arguments are passed by value or by reference: |
|||
# As in Python, all arguments are passed by pointer reference, but assignment to a passed argument |
|||
# only changes the variable within the function. Assignment to the values referenced by the argument |
|||
## DOES however change those values. For instance: |
|||
a = 3 |
|||
b = [3] |
|||
c = [3] |
|||
function f(x, y) |
|||
a = 0 |
|||
b[1] = 0 |
|||
c = [0] |
|||
end # a and c are now unchanged but b = [0] |
|||
# Is partial application possible and how: |
|||
# In Julia, there are many different ways to compose functions. In particular, |
|||
# Julia has an "arrow" operator -> that may be used to curry other functions. |
|||
f(a, b) = a^2 + a + b |
|||
v = [4, 6, 8] |
|||
map(x -> f(x, 10), v) # v = [30, 52, 82] |
|||
</syntaxhighlight> |
|||
=={{header|Kotlin}}== |
|||
In Kotlin parameters are always passed by value though, apart from the (unboxed) primitive types, the value passed is actually a reference to an object. |
|||
<syntaxhighlight lang="kotlin">fun fun1() = println("No arguments") |
|||
fun fun2(i: Int) = println("One argument = $i") |
|||
fun fun3(i: Int, j: Int = 0) = println("One required argument = $i, one optional argument = $j") |
|||
fun fun4(vararg v: Int) = println("Variable number of arguments = ${v.asList()}") |
|||
fun fun5(i: Int) = i * i |
|||
fun fun6(i: Int, f: (Int) -> Int) = f(i) |
|||
fun fun7(i: Int): Double = i / 2.0 |
|||
fun fun8(x: String) = { y: String -> x + " " + y } |
|||
fun main() { |
|||
fun1() // no arguments |
|||
fun2(2) // fixed number of arguments, one here |
|||
fun3(3) // optional argument, default value used here |
|||
fun4(4, 5, 6) // variable number of arguments |
|||
fun3(j = 8, i = 7) // using named arguments, order unimportant |
|||
val b = false |
|||
if (b) fun1() else fun2(9) // statement context |
|||
println(1 + fun6(4, ::fun5) + 3) // first class context within an expression |
|||
println(fun5(5)) // obtaining return value |
|||
println(kotlin.math.round(2.5)) // no distinction between built-in and user-defined functions, though former usually have a receiver |
|||
fun1() // calling sub-routine which has a Unit return type by default |
|||
println(fun7(11)) // calling function with a return type of Double (here explicit but can be implicit) |
|||
println(fun8("Hello")("world")) // partial application isn't supported though you can do this |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
No arguments |
|||
One argument = 2 |
|||
One required argument = 3, one optional argument = 0 |
|||
Variable number of arguments = [4, 5, 6] |
|||
One required argument = 7, one optional argument = 8 |
|||
One argument = 9 |
|||
20 |
|||
25 |
|||
2.0 |
|||
No arguments |
|||
5.5 |
|||
Hello world |
|||
</pre> |
|||
=={{header|Lambdatalk}}== |
|||
In lambdatalk functions are abstractions {lambda {args} body} whose behaviour is best explained as a part of such a complete expression {{lambda {args} body} values}. |
|||
<syntaxhighlight lang="scheme"> |
|||
The command |
|||
replace :a0 :a1 ... an-1 |
|||
in expression containing some occurences of :ai |
|||
by v0 v1 ... vp-1 |
|||
is rewritten in a prefixed parenthesized form |
|||
{{lambda {:a0 :a1 ... an-1} |
|||
expression containing some occurences of :ai} |
|||
v0 v1 ... vp-1} |
|||
so called IIFE (Immediately Invoked Function Expression), and defines an anonymous function containing a sequence of n arguments :ai, immediately invoked on a sequence of p values vi, and returning the expression in its body as so modified: |
|||
1) if p < n (partial application) |
|||
• the occurrences of the p first arguments are replaced in the function's body by the corresponding p given values, |
|||
• a function waiting for missing n-p values is created, |
|||
• and its reference is returned. |
|||
• example: |
|||
{{lambda {:x :y} ... :y ... :x ...} hello} |
|||
-> {lambda {:y} ... :y ... hello ...} // replaces :x by hello |
|||
-> LAMB_123 // the new functions's reference |
|||
• called with the value world this function will return ... world ... hello ... |
|||
2) if p = n (normal application) |
|||
• the occurences of the n arguments are replaced in the function's body by the corresponding p given values, |
|||
• the body is evaluated and the result is returned. |
|||
• example |
|||
{{lambda {:x :y} ... :y ... :x ...} hello world} |
|||
-> {{lambda {:y} ... :y ... hello ...} world} // replaces :x by hello |
|||
-> {{lambda {} ... world ... hello ...} } // replaces :y by world |
|||
-> ... world ... hello ... // the value |
|||
3) if p > n (variadicity) |
|||
• the occurrences of the n-1 first arguments are replaced in the function's body by the corresponding n-1 given values, |
|||
• the occurrences of the last argument are replaced in the body by the sequence of p-n supernumerary values, |
|||
• the body is evaluated and the result is returned. |
|||
• example: |
|||
{{lambda {:x :y} ... :y ... :x ...} hello world good morning} |
|||
-> {{lambda {:y} ... :y ... hello ...} world good morning} |
|||
-> {{lambda {} ... world good morning ... hello ...}} |
|||
-> ... world good morning ... hello ... // the value |
|||
More can be seen in http://lambdaway.free.fr/lambdawalks/?view=lambda |
|||
</syntaxhighlight> |
|||
=={{header|Lang}}== |
|||
<syntaxhighlight lang="lang"> |
|||
fp.noArgs = () -> \! |
|||
fp.noArgs() |
|||
# For user defined-functions, the argument count is not checked: If too many arguments were provided, they are ignored. If not enough arguments were provided, the last argument will be duplicated (If none was provided, VOID values will be filled in). [This process is is referred to as implict argument duplication] |
|||
fp.noArgs(42) # No Error nor Warning |
|||
fp.fixArgs = ($x, $y) -> \! |
|||
fp.fixArgs(1, 2) |
|||
fp.fixArgs(2) # Fix args will be called with $x=2 and $y=2 |
|||
fp.fixArgs() # Fix args will be called with $x=VOID and $y=VOID |
|||
# fn.argCntX (X must be replaced with 0, 1, 2, 3, 4, or 5) can be used to force the caller to provided the exact argument count |
|||
# fn.argCntX must be called with the function to apply the constraint to and will return a new function |
|||
fp.realFixArgs = fn.argCnt2(fp.fixArgs) |
|||
fp.realFixArgs(1, 2) |
|||
fp.realFixArgs() # Error |
|||
fp.realFixArgs(1) # Error |
|||
fp.realFixArgs(1, 2, 3) # Error |
|||
# Arrays can be unpacked in function calls |
|||
&values $= [1, 2] |
|||
fp.fixArgs(&values...) # Fix args will be called with $x=1 and $y=2 |
|||
# In Lang there are text and array varags parameters |
|||
fp.varArgsText = ($text...) -> \! |
|||
fp.varArgsText(1) # Var args text will be called with "1" |
|||
fp.varArgsText(1, 2) # Var args text will be called with "1, 2" |
|||
fp.varArgsText(1,2) # Var args text will be called with "1,2" |
|||
fp.varArgsText(1,text ,3) # Var args text will be called with "1,text ,3" |
|||
fp.varArgsArray = (&args...) -> \! |
|||
fp.varArgsArray(1) # Var args array will be called with [1] |
|||
fp.varArgsArray(1, 2) # Var args array will be called with [1, 2] |
|||
fp.varArgsArray(1,2) # Var args array will be called with [1, 2] |
|||
fp.varArgsArray(1,text ,3) # Var args array will be called with [1, text, 3] |
|||
# Functions with named arguments can not be created |
|||
# Using a function in a statement context |
|||
$x = fp.fixArgs(1, 2) |
|||
# Functions (Even predefined and linker functions) can be used as values |
|||
fp.retAFunc = () -> { |
|||
return ($x) -> \! |
|||
} |
|||
fp.func = fp.retAFunc() |
|||
fp.func(2) |
|||
# Multiple call-expressions can be used directly |
|||
fp.retAFunc()(2) |
|||
fp.retAFunc = () -> return fn.println |
|||
fp.retAFunc()(test, values) |
|||
fp.retAFunc = () -> return ln.loadModule |
|||
fp.retAFunc()(x.lm) # Error, because file not found |
|||
# The return value or the thrown error can be obtained with the assignment operator |
|||
fp.inc2 = ($x) -> return parser.op($x + 2) |
|||
$ret = fp.inc2(40) # $ret is 42 |
|||
# Built-in (They are called predefined functions in Lang) start with the "func." or "fn." prefix wheras user-defined functions start with "fp." |
|||
# Linker functions start with "linker." or "ln." |
|||
# Predefined and linker functions can be stored in a user-defined function |
|||
fp.userDefinedFunc = fn.println |
|||
fp.userDefinedFunc(Called println) |
|||
# In Lang there are no subroutines |
|||
# In Lang functions can have call-by-pointer values |
|||
# $ptr is a pointer to the called value |
|||
fp.callByPtr = ($[ptr]) -> \! |
|||
fp.callByPtr(42) # This will create a pointer to an anonymous value, therefor it can not be changed |
|||
fp.inc2 = ($[ptr]) -> $*ptr += 2 |
|||
fp.inc2(40) # Error |
|||
$val = 40 |
|||
fp.inc2($val) # $val is now 42 |
|||
# Functions can also be called with pointers directly |
|||
fp.inc2 = ($ptr) -> $*ptr += 2 |
|||
fp.inc2(40) # Multiple Errors (Value will be dereferenced as NULL -> + is not defined for NULL and INT AND anonymous values can not be changed) |
|||
$val = 40 |
|||
fp.inc2($[val]) # $val is now 42 |
|||
# Partial apllication of functions is possible by using combinator functions |
|||
# The simplest combinator function-family is the A combinator family (Other families change the order of arguments, can call multiple function, ...) |
|||
fp.partialAdd = fn.combA2(fn.add) # When all arguments for fn.combA2(a, b, c) are provided, the execution of a(b, c) will begin |
|||
fp.add42 = fp.partialAdd(42) # Creates a function which still needs 1 argument |
|||
fp.add42(2) # Will return 44 |
|||
# Without the use of fn.argCntX 0 args can also be provied |
|||
fp.add42()()()(2) # Will also return 44 |
|||
</syntaxhighlight> |
|||
===Special function-related features=== |
|||
<syntaxhighlight lang="lang"> |
|||
# The function argument auto un-pack operator (▲ or +|) can be used to create a function which must be called with an array value that is automatically unpacked |
|||
fp.fixArgs = ($x, $y) -> \! |
|||
fp.unpackingFixArgs $= +|fp.fixArgs |
|||
fp.unpackingFixArgs(&values) # Fix args will be called with $x=1 and $y=2 |
|||
# The function argument auto pack operator (▼ or -|) can be used to cerate a function wich must be called with varargs and will call the original function with a single array argument |
|||
fp.arrayArg = (&arr) -> \! |
|||
fp.packingArrayArg $= -|fp.arrayArg |
|||
fp.packingArrayArg(1, 2) # Array arg will be called with [1, 2] |
|||
# Functions can also be called with the pipe operators (|, >>, and >>>) |
|||
# The "|" and ">>" pipe operators are identical apart from the operator precedence |
|||
# The ">>>" pipe operator automatically unpacks array values |
|||
fp.func = ($x) -> \! |
|||
parser.op(42 | fp.func) # fp.func is called with 42 |
|||
parser.op(42 >> fp.func) # fp.func is called with 42 |
|||
parser.op([42] >>> fp.func) # fp.func is called with 42 |
|||
# Function calls can be concatinated with the concat operator (|||) |
|||
fp.incAndPrint $= fn.inc ||| fn.println # Calling fp.incAndPrint($x) has the same effect as calling fn.println(fn.inc($x)) |
|||
fp.incAndPrint(2) # Prints 3 |
|||
# The pow operator can be used to call a function multiple times in succession |
|||
# This works only with exponents >= 0 (If the exponent is 0 a function will be returned, that always returns VOID) |
|||
fp.voidFunc $= fn.inc ** 0 |
|||
fp.voidFunc(2) # Returns VOID |
|||
fn.pow(fn.inc, 1)(2) # Returns 3 |
|||
fn.pow(fn.inc, 2)(2) # Returns 4 |
|||
fn.pow(fn.inc, 3)(2) # Returns 5 |
|||
fn.pow(fn.inc, 10)(2) # Returns 12 |
|||
</syntaxhighlight> |
|||
=={{header|langur}}== |
|||
User-defined and built-in functions can be called using parentheses. |
|||
Built-in functions can also be called using an "unbounded list," which ends at a line return, EOF, closing parenthesis, curly brace, or square bracket, or before a comma preceding a line return. |
|||
=== parentheses === |
|||
<syntaxhighlight lang="langur">.x() |
|||
# call user-defined function</syntaxhighlight> |
|||
<syntaxhighlight lang="langur">write(.key, ": ", .value) |
|||
# call built-in with parentheses</syntaxhighlight> |
|||
=== unbounded lists === |
|||
<syntaxhighlight lang="langur">write .key, ": ", .value |
|||
# call built-in with unbounded list</syntaxhighlight> |
|||
<syntaxhighlight lang="langur">writeln "numbers: ", join ", ", [.a1, .a2, .a3, .a4] |
|||
# unbounded lists on writeln and join |
|||
# later function join takes remaining arguments</syntaxhighlight> |
|||
<syntaxhighlight lang="langur">writeln "numbers: ", join(", ", [.a1, .a2, .a3, .a4]), " === " |
|||
# unbounded list on writeln |
|||
# join using parentheses so it doesn't take remaining arguments</syntaxhighlight> |
|||
<syntaxhighlight lang="langur">val .sum = foldfrom( |
|||
fn(.sum, .i, .c) { .sum + number(.c, 36) * .weight[.i] }, |
|||
0, |
|||
pseries len .code, |
|||
split .code, |
|||
) |
|||
# split, pseries, and len using unbounded lists, ending before comma preceding line return</syntaxhighlight> |
|||
<syntaxhighlight lang="langur">for .key in sort(keys .tests) { |
|||
... |
|||
} |
|||
# unbounded list on keys bounded by closing parenthesis of sort</syntaxhighlight> |
|||
=={{header|Latitude}}== |
|||
Like Ruby, Latitude doesn't have functions in the traditional sense, only methods. Methods can be called with parentheses, as in many languages. If a method takes no arguments, the parentheses may be omitted. If a method takes a single argument and that argument is a literal (such as a literal number or string), then the parentheses may also be omitted. Additionally, Latitude provides an alternative syntax for method calls which replaces the parentheses with a colon. |
|||
<syntaxhighlight lang="text">foo (1, 2, 3). ; (1) Ordinary call |
|||
foo (). ; (2) No arguments |
|||
foo. ; (3) Equivalent to (2) |
|||
foo (1). ; (4) Single-argument function |
|||
foo 1. ; (5) Equivalent to (4) |
|||
foo (bar). ; (6) Parentheses necessary here since bar is not a literal |
|||
foo: 1, 2, 3. ; (7) Alternative syntax, equivalent to (1)</syntaxhighlight> |
|||
Although methods themselves can be passed around as first-class values, the method evaluation semantics often make such an approach suboptimal. If one needs a first-class function in the traditional sense, the usual approach is to wrap it in a <code>Proc</code> object and then call it explicitly as needed. |
|||
<syntaxhighlight lang="text">myProc := proc { foo. }. |
|||
myProc call (1, 2, 3).</syntaxhighlight> |
|||
If you want to write a function which can accept either a <code>Proc</code> or a method object (as many standard library functions do, for convenience), you may use the <code>shield</code> method to ensure that the object is a <code>Proc</code>. <code>shield</code> wraps methods in a <code>Proc</code> while leaving objects which are already procedures alone. |
|||
<syntaxhighlight lang="text">myProc1 := #'foo shield. |
|||
myProc2 := proc { foo. }. |
|||
myProc3 := proc { foo. } shield.</syntaxhighlight> |
|||
All three of the above procedures will act the same. |
|||
=={{header|LFE}}== |
=={{header|LFE}}== |
||
Line 435: | Line 3,733: | ||
In some module, define the following: |
In some module, define the following: |
||
< |
<syntaxhighlight lang="lisp"> |
||
(defun my-func() |
(defun my-func() |
||
(: io format '"I get called with NOTHING!~n")) |
(: io format '"I get called with NOTHING!~n")) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Then you use it like so (depending upon how you import it): |
Then you use it like so (depending upon how you import it): |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (my-func) |
> (my-func) |
||
I get called with NOTHING! |
I get called with NOTHING! |
||
ok |
ok |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Calling a function with a fixed number of arguments:''' |
'''Calling a function with a fixed number of arguments:''' |
||
In some module, define the following: |
In some module, define the following: |
||
< |
<syntaxhighlight lang="lisp"> |
||
(defun my-func(a b) |
(defun my-func(a b) |
||
(: io format '"I got called with ~p and ~p~n" (list a b))) |
(: io format '"I got called with ~p and ~p~n" (list a b))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Then you use it like so: |
Then you use it like so: |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (my-func '"bread" '"cheese") |
> (my-func '"bread" '"cheese") |
||
I got called with "bread" and "cheese" |
I got called with "bread" and "cheese" |
||
ok |
ok |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Calling a function with optional arguments or calling a function with a variable number of arguments:''' |
'''Calling a function with optional arguments or calling a function with a variable number of arguments:''' |
||
Line 467: | Line 3,765: | ||
* One can define multiple functions so that it ''appears'' that one is calling a function with optional or a variable number of arguments: |
* One can define multiple functions so that it ''appears'' that one is calling a function with optional or a variable number of arguments: |
||
< |
<syntaxhighlight lang="lisp"> |
||
(defmodule args |
(defmodule args |
||
(export all)) |
(export all)) |
||
Line 482: | Line 3,780: | ||
(defun my-func (a b c) |
(defun my-func (a b c) |
||
(: io format '"~p ~p ~p~n" (list a b c))) |
(: io format '"~p ~p ~p~n" (list a b c))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Here is some example usage: |
Here is some example usage: |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (slurp '"args.lfe") |
> (slurp '"args.lfe") |
||
#(ok args) |
#(ok args) |
||
Line 502: | Line 3,800: | ||
> (my-func '"apple" '"banana" '"cranberry" '"bad arg") |
> (my-func '"apple" '"banana" '"cranberry" '"bad arg") |
||
exception error: #(unbound_func #(my-func 4)) |
exception error: #(unbound_func #(my-func 4)) |
||
</ |
</syntaxhighlight> |
||
'''Calling a function with named arguments:''' |
'''Calling a function with named arguments:''' |
||
Line 512: | Line 3,810: | ||
'''Using a function in statement context:''' |
'''Using a function in statement context:''' |
||
< |
<syntaxhighlight lang="lisp"> |
||
... |
... |
||
(cond ((== count limit) (hit-limit-func arg-1 arg-2)) |
(cond ((== count limit) (hit-limit-func arg-1 arg-2)) |
||
((/= count limit) (keep-going-func count))) |
((/= count limit) (keep-going-func count))) |
||
... |
... |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Using a function in first-class context within an expression:''' |
'''Using a function in first-class context within an expression:''' |
||
From the LFE REPL: |
From the LFE REPL: |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (>= 0.5 (: math sin 0.5)) |
> (>= 0.5 (: math sin 0.5)) |
||
true |
true |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Obtaining the return value of a function:''' |
'''Obtaining the return value of a function:''' |
||
There are many, many ways to assign function outputs to variables in LFE. One fairly standard way is with the <code>(let ...)</code> form: |
There are many, many ways to assign function outputs to variables in LFE. One fairly standard way is with the <code>(let ...)</code> form: |
||
< |
<syntaxhighlight lang="lisp"> |
||
(let ((x (: math sin 0.5))) |
(let ((x (: math sin 0.5))) |
||
...) |
...) |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Distinguishing built-in functions and user-defined functions:''' |
'''Distinguishing built-in functions and user-defined functions:''' |
||
* There is no distinction made in LFE/Erlang between functions that are built-in and those that are not. |
* There is no distinction made in LFE/Erlang between functions that are built-in and those that are not. |
||
* "Built-in" for LFE/Erlang usually can be figured out: if a function has the module name <code>erlang</code>, e.g., <code>(: erlang list_to_integer ... )</ |
* "Built-in" for LFE/Erlang usually can be figured out: if a function has the module name <code>erlang</code>, e.g., <code>(: erlang list_to_integer ... )</code>, then it's built-in. |
||
* Most of the functions that come with LFE/Erlang are not even in the <code>erlang</code> module, but exist in other modules (e.g., <code>io</code>, <code>math</code>, etc.) and in OTP. |
* Most of the functions that come with LFE/Erlang are not even in the <code>erlang</code> module, but exist in other modules (e.g., <code>io</code>, <code>math</code>, etc.) and in OTP. |
||
* One uses user/third-party modules in exactly the same way as one uses built-ins and modules that come with the Erlang distribution. |
* One uses user/third-party modules in exactly the same way as one uses built-ins and modules that come with the Erlang distribution. |
||
Line 559: | Line 3,857: | ||
* However, one can use <code>lambda</code>s to achieve the same effect. |
* However, one can use <code>lambda</code>s to achieve the same effect. |
||
=={{header|Liberty BASIC}}== |
|||
<syntaxhighlight lang="lb"> |
|||
'Call a function - Liberty BASIC |
|||
'First, function result could not be discarded |
|||
' that is, you cannot do "f(x)" as a separate statement |
|||
'Calling a function that requires no arguments |
|||
res = f() 'brackets required |
|||
'Calling a function with a fixed number of arguments |
|||
res = g(x) |
|||
res = h(x,y) |
|||
'Calling a function with optional arguments |
|||
'impossible for user-defined functions |
|||
'Some build-in functions ex. INSTR and MID$ could be called with last argument omitted |
|||
'Calling a function with a variable number of arguments |
|||
'impossible |
|||
'Calling a function with named arguments |
|||
'impossible |
|||
'Using a function in statement context |
|||
'impossible (see starting notice) |
|||
'Using a function in first-class context within an expression |
|||
'impossible |
|||
'Obtaining the return value of a function |
|||
res = g(x) |
|||
'Distinguishing built-in functions and user-defined functions |
|||
'I would say impossible. Though built-in functions could be EVAL'ed, |
|||
'while user-defined would not be called (tries address array instead). |
|||
'Still cannot distinguish user-defined function from array. |
|||
'Distinguishing subroutines and functions |
|||
'then defined, subroutines and functions defined with words |
|||
'SUB and FUNCTION (case incensitive) |
|||
'Then used, function used as expression (with return value), |
|||
res = g(x) |
|||
'while subroutines called with special keyword CALL and without brackets |
|||
call test x, y |
|||
'Stating whether arguments are passed by value or by reference |
|||
'Variables passed as arguments into functions and subs are passed "by value" by default |
|||
'parameters could be passed "by reference" if formal parameter in sub/function definition uses the "byref" specifier |
|||
'Then calling a function, you can prevent pass by reference by changing variable to expression |
|||
' like x+0, x$+"" or just (x), (x$) |
|||
'Is partial application possible and how |
|||
'impossible |
|||
</syntaxhighlight> |
|||
=={{header|Lingo}}== |
|||
*Calling a function that requires no arguments |
|||
<syntaxhighlight lang="lingo">foo() |
|||
-- or alternatively: |
|||
call(#foo, _movie)</syntaxhighlight> |
|||
*Calling a function with a fixed number of arguments |
|||
<syntaxhighlight lang="lingo">foo(1,2,3) |
|||
-- or alternatively: |
|||
call(#foo, _movie, 1, 2, 3)</syntaxhighlight> |
|||
*Calling a function with optional arguments |
|||
<syntaxhighlight lang="lingo">on foo (a, b) |
|||
if voidP(b) then b = 1 |
|||
return a * b |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lingo">put foo(23, 2) |
|||
-- 46 |
|||
put foo(23) |
|||
-- 23</syntaxhighlight> |
|||
*Calling a function with a variable number of arguments |
|||
<syntaxhighlight lang="lingo">on sum () |
|||
res = 0 |
|||
repeat with i = 1 to the paramCount |
|||
res = res + param(i) |
|||
end repeat |
|||
return res |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lingo">put sum (1,2,3) |
|||
-- 6</syntaxhighlight> |
|||
*Calling a function with named arguments |
|||
Not directly supported, but you can of course re-write any function to only accept a single property list (hash) as argument, which can make sense e.g. for functions that have a lot of optional aruments. |
|||
*Using a function in statement context |
|||
*Using a function in first-class context within an expression |
|||
Lingo has no first-class functions, but the call(...) syntax (see above) allows to identify and use functions specified as "symbols" (e.g. #foo). This allows some "first-class alike" features: |
|||
<syntaxhighlight lang="lingo">---------------------------------------- |
|||
-- One of the five native iterative methods defined in ECMAScript 5 |
|||
-- @param {list} tList |
|||
-- @param {symbol} cbFunc |
|||
-- @param {object} [cbObj=_movie] |
|||
-- @return {list} |
|||
---------------------------------------- |
|||
on map (tList, cbFunc, cbObj) |
|||
if voidP(cbObj) then cbObj = _movie |
|||
res = [] |
|||
cnt = tList.count |
|||
repeat with i = 1 to cnt |
|||
res[i] = call(cbFunc, cbObj, tList[i], i, tList) |
|||
end repeat |
|||
return res |
|||
end |
|||
on doubleInt (n) |
|||
return n*2 |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lingo">l = [1,2,3] |
|||
put map(l, #doubleInt) |
|||
-- [2, 4, 6]</syntaxhighlight> |
|||
*Obtaining the return value of a function |
|||
<syntaxhighlight lang="lingo">x = foo(1,2)</syntaxhighlight> |
|||
*Distinguishing built-in functions and user-defined functions |
|||
In Lingo all user-defined (global) functions are 'methods' of the _movie object, and there is AFAIK no direct way to distinguish those from _movie's built-in functions. But by iterating over of all movie scripts in all castlibs you can get a complete list of all user-defined (global) functions, and then any function not in this list is a built-in function: |
|||
<syntaxhighlight lang="lingo">on getAllUserFunctions () |
|||
res = [] |
|||
repeat with i = 1 to _movie.castlib.count |
|||
c = _movie.castlib(i) |
|||
repeat with j = 1 to c.member.count |
|||
m = c.member[j] |
|||
if m.type<>#script then next repeat |
|||
if m.scripttype=#movie then |
|||
functions = m.script.handlers() |
|||
repeat with f in functions |
|||
res.append(f) |
|||
end repeat |
|||
end if |
|||
end repeat |
|||
end repeat |
|||
return res |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lingo">put getAllUserFunctions() |
|||
-- [#sum, #double, #getAllUserFunctions]</syntaxhighlight> |
|||
*Distinguishing subroutines and functions |
|||
In Lingo functions (also called "handlers") don't have to return anything, so there is no distinction. The return value of a function without a "return ..." line is VOID, and not distinguishable from a function with the explicit line "return VOID". |
|||
*Stating whether arguments are passed by value or by reference |
|||
In lingo 'objects' are always passed by reference, all other types (e.g. strings, integers, floats) by value. 'Objects' are e.g. lists (arrays), property lists (hashes), images and script instances. The built-in function objectP() returns TRUE (1) for objects and FALSE (0) for non-objects. To prevent the effects of call-by-reference, some object types (lists, property lists and images) support the method duplicate() to clone the object before passing it to a function: |
|||
<syntaxhighlight lang="lingo">on double (someList) |
|||
cnt = someList.count |
|||
repeat with i = 1 to cnt |
|||
someList[i] = someList[i] * 2 |
|||
end repeat |
|||
end</syntaxhighlight> |
|||
<syntaxhighlight lang="lingo">l = [1,2,3] |
|||
double(l) |
|||
put l |
|||
-- [2, 4, 6] |
|||
l = [1,2,3] |
|||
double(l.duplicate()) |
|||
put l |
|||
-- [1, 2, 3]</syntaxhighlight> |
|||
=={{header|Little}}== |
|||
The following examples use buldin functions, standard Tcl commands and some |
|||
local fuctions. |
|||
<syntaxhighlight lang="c">// Calling a function that requires no arguments |
|||
void foo() {puts("Calling a function with no arguments");} |
|||
foo(); |
|||
// Calling a function with a fixed number of arguments |
|||
abs(-36); |
|||
// Calling a function with optional arguments |
|||
puts(nonewline: "nonewline is an optional argument"); |
|||
puts("\n"); |
|||
// Calling a function with a variable number of arguments |
|||
void var_arg_func(...args) { |
|||
puts(length(args)); |
|||
} |
|||
var_arg_func(1, 2); |
|||
var_arg_func(1, 2, 3); |
|||
// Obtaining the return value of a function |
|||
int s = clock("seconds"); //current time in seconds |
|||
// Calling a function with named arguments |
|||
// format is a named argument in Clock_format |
|||
int str = Clock_format(s, format: "%B"); |
|||
puts(str); |
|||
// Stating whether arguments are passed by value or by reference |
|||
void f(int a, int &b) { a++; b++; } |
|||
{ |
|||
int a = 0; |
|||
int b = 0; |
|||
f(a, &b); |
|||
puts (a); |
|||
puts (b); |
|||
}</syntaxhighlight> |
|||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
< |
<syntaxhighlight lang="lua">-- Lua functions accept any number of arguments; missing arguments are nil-padded, extras are dropped. |
||
function fixed (a, b, c) print(a, b, c) end |
function fixed (a, b, c) print(a, b, c) end |
||
fixed() --> nil nil nil |
fixed() --> nil nil nil |
||
Line 593: | Line 4,083: | ||
-- There is no separate notion of subroutines |
-- There is no separate notion of subroutines |
||
-- Built-in functions are not easily distinguishable from user-defined functions |
-- Built-in functions are not easily distinguishable from user-defined functions |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Luck}}== |
|||
<syntaxhighlight lang="luck">/* Calling a function that requires no arguments */ |
|||
f();; |
|||
/* Calling a function with a fixed number of arguments */ |
|||
=={{header|Mathematica}}== |
|||
f(1,2);; |
|||
/* Calling a function with optional arguments |
|||
Note: defining the function is cumbersome but will get easier in future versions. */ |
|||
f(1,2,new {default with x=3, y=4});; |
|||
/* Calling a function with a variable number of arguments */ |
|||
printf("%d %d %d %d":char*,2,3,4,5);; |
|||
/* Calling a function with named arguments |
|||
Note: may get syntax sugar in future versions */ |
|||
f(1,2,new {default with x=3, y=4});; |
|||
/* Using a function in statement context (what?) */ |
|||
f();f();f();; |
|||
/* Using a function in first-class context within an expression */ |
|||
[1,2,3].map(string);; |
|||
/* Obtaining the return value of a function */ |
|||
let x:int = f();; |
|||
/* Distinguishing built-in functions and user-defined functions */ |
|||
/* Builtin function i.e. custom calling convention: */ |
|||
(@ binop "==" l r);; |
|||
/* User defined function i.e. normal function */ |
|||
f(l)(r);; |
|||
/* Distinguishing subroutines and functions: both are supported, but compiler is not aware of difference */ |
|||
sub();; |
|||
fun();; |
|||
/* Stating whether arguments are passed by value or by reference */ |
|||
f(value);; /* by value */ |
|||
f(&value);; /* by pointer reference */ |
|||
f(ref(value));; /* by managed reference */ |
|||
/* Is partial application possible and how */ |
|||
tasty_curry(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);;</syntaxhighlight> |
|||
=={{header|M2000 Interpreter}}== |
|||
<pre> |
|||
// Calling a function that requires no arguments |
|||
ModuleA ' introduce a namespace can have modules/functions/subs, anything inside, and threads. |
|||
Call FunctionA() ' introduce a namespace can have modules/functions/subs, anything inside. |
|||
Call LambdaA() ' introduce a namespace can have modules/functions/subs, anything inside. |
|||
SubAlfa() ' subroutine this has the same scope as the caller, we can use Local statement to shadow variables/arrays |
|||
Print @Simple() ' simple function this has the same scope as the caller, we can use Local statement to shadow variables/arrays |
|||
Gosub labelA ' Statement Return used to return from a gosub, no arguments and no local statement used, the code is like any other code in the module/function/lambda scope. No jump out of scope allowed. |
|||
Gosub 10020 ' Statement Return used to return from a gosub,, no arguments and no local statement used, the code is like any other code in the module/function/lambda scope. No jump out of scope allowed. |
|||
// Calling a function with a fixed number of arguments |
|||
ModuleA 100 |
|||
SubAlfa(100) ' subroutine |
|||
Print @Simple(100) ' simple function |
|||
Call FunctionA(100) |
|||
Call LambdaA(100) |
|||
// Calling a function with optional arguments |
|||
ModuleA ?,4 |
|||
SubAlfa(?) ' subroutine |
|||
Print @Simple(?) ' simple function |
|||
Call FunctionA(,4) |
|||
Call LambdaA(,4) |
|||
// Calling a function with a variable number of arguments |
|||
Call FunctionA(1,2,3,4,5) |
|||
Call LambdaA(1,2,3,4,5) |
|||
// Calling a function with named arguments |
|||
ModuleA %X=10, %Z=20 |
|||
// Using a function in statement context |
|||
Module A |
|||
SubAlfa() |
|||
Call Void FunctionA() |
|||
Call Void LambdaA() |
|||
// Using a function in first-class context within an expression |
|||
Print (lambda (x,y)->{=x**y}(2,3))*8=64 |
|||
// Obtaining the return value of a function |
|||
A%=FunctionA%() ' integer part from any numeric type. Also A% if get decimals convert to integer using school rounding (0.5, so 3.5 is 4, 2.5 is 3) |
|||
A=FunctionA() ' numeric or object |
|||
A$=FunctionA$() ' string or object which return string |
|||
A=LambdaA() |
|||
A$=LambdaA$() |
|||
A=@SimpleA() |
|||
A$=@SimpleA$() |
|||
// Distinguishing built-in functions and user-defined functions |
|||
Def Cos(x)=100*X ' change the build in |
|||
Print Cos(3), @Cos(3) ' @Cos() is the build in anyway |
|||
' we can't use simple function with same name as a bultin function. |
|||
// Distinguishing subroutines and functions |
|||
Name without parenthesis like a command or statement is a Module |
|||
Name with parentesis without operator is a Sub |
|||
Name with parenthesis in an expression is a function or array (array come first), using a(*10) we say that it is function even an array a() exist. |
|||
Name with @ as first symbol and parenthesis like @alfa() is a simple function unless has a builtin name, so is that function. |
|||
// Stating whether arguments are passed by value or by reference |
|||
Default:By Value |
|||
By Reference: Using & at both sides (caller and calee) |
|||
Function Alfa(&x) { |
|||
=X : X++ |
|||
} |
|||
Print Alfa(&counter) |
|||
Subs and Simple Functions not need a by reference pass because they are in the same scope from the caller, so actuall we pass by value to be local to those entities. But we can use by reference, except for static variables, and array items. Those can only passed by reference on modules and nornal functions and lambdas (which are normal functions plus more). |
|||
// Is partial application possible and how |
|||
A=Lambda (X) -> { |
|||
=Lambda X (Y) -> { |
|||
=Y**X |
|||
} |
|||
} |
|||
Cube=A(3) : Square=A(2) |
|||
Print Cube(2)=8, Square(2)=4 |
|||
OOP: Functions/Modules can be members of objects. |
|||
Objects may have a name (they live until code get out of scope) |
|||
Objects may don't have a name but one or more pointers, (they live until counting references are zero) |
|||
ObjectA.moduleA is a call to an object method (a module) |
|||
pointerA=>moduleA is a call to an object by a pointer |
|||
An object may return values, and may accept parameters too. Also objects if they didn't return values other than a copy of them can be use operators defined as object functions. |
|||
Objects may have events and fire them using Call Event "simpleevent", param1, param2... |
|||
Functions and lambda (not simple functions), and object functions can be passed by reference as parameters. |
|||
</pre> |
|||
=={{header|Maple}}== |
|||
Calling a function with no arguments:<syntaxhighlight lang="maple"> f()</syntaxhighlight> |
|||
Calling a function with a fixed number of arguments:<syntaxhighlight lang="maple">f(1,sin(x), g -> int(g(t),t=0..1)</syntaxhighlight> |
|||
Calling a function with optional arguments: <syntaxhighlight lang="maple">f(1, sin(x), g -> int(g(t),t=0..1)</syntaxhighlight> |
|||
Calling a function with a variable number of arguments: <syntaxhighlight lang="maple">f(1, sin(x), g -> int(g(t),t=0..1)</syntaxhighlight> |
|||
Calling a function with named arguments:<syntaxhighlight lang="maple">f(a,b,method = foo)</syntaxhighlight> |
|||
Calling a function in a statements context:<syntaxhighlight lang="maple">f(a); f(b);</syntaxhighlight> |
|||
Using a function in first-class context within an expression:<syntaxhighlight lang="maple">f(a) + g(b)</syntaxhighlight> |
|||
Obtaining the return value of a function:<syntaxhighlight lang="maple"> x := f(1)</syntaxhighlight> |
|||
Distinguishing built-in functions and user-defined functions: |
|||
<syntaxhighlight lang="maple">> type( op, 'builtin' ); |
|||
true |
|||
</syntaxhighlight> |
|||
Distinguishing subroutines and functions: There is no distinction. |
|||
Stating whether arguments are passed by value or by reference: All values are passed by value. |
|||
However, if an argument is a name, then it can be assigned to and, if a value is mutable (such as an array), then it can be modified by the function. This is implemented by function definition; there is no distinction when calling the function. |
|||
Partial application is supported by the <code>curry</code> and <code>rcurry</code> commands. |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
Calling a function that requires no arguments: |
Calling a function that requires no arguments: |
||
<lang |
<syntaxhighlight lang="mathematica">f[]</syntaxhighlight> |
||
Calling a function with a fixed number of arguments: |
Calling a function with a fixed number of arguments: |
||
<lang |
<syntaxhighlight lang="mathematica">f[1,2]</syntaxhighlight> |
||
Calling a function with optional arguments: |
Calling a function with optional arguments: |
||
<lang |
<syntaxhighlight lang="mathematica">f[1,Option1->True]</syntaxhighlight> |
||
Calling a function with a variable number of arguments: |
Calling a function with a variable number of arguments: |
||
< |
<syntaxhighlight lang="mathematica">f[1,Option1->True] |
||
f[1,Option1->True,Option2->False]</ |
f[1,Option1->True,Option2->False]</syntaxhighlight> |
||
Calling a function with named arguments: |
Calling a function with named arguments: |
||
< |
<syntaxhighlight lang="mathematica">f[Option1->True,Option2->False]</syntaxhighlight> |
||
Using a function in statement context: |
Using a function in statement context: |
||
< |
<syntaxhighlight lang="mathematica">f[1,2];f[2,3]</syntaxhighlight> |
||
Using a function in first-class context within an expression: |
Using a function in first-class context within an expression: |
||
<lang |
<syntaxhighlight lang="mathematica">(#^2)&[3];</syntaxhighlight> |
||
The return value of a function can be formally extracted using Return[] |
The return value of a function can be formally extracted using Return[] |
||
Line 622: | Line 4,259: | ||
No formal distinction between subroutines and functions. |
No formal distinction between subroutines and functions. |
||
Arguments can be passed by value or by reference. |
Arguments can be passed by value or by reference. |
||
=={{header|MATLAB}} / {{header|Octave}}== |
=={{header|MATLAB}} / {{header|Octave}}== |
||
<syntaxhighlight lang="matlab"> |
|||
<lang Matlab> |
|||
% Calling a function that requires no arguments |
% Calling a function that requires no arguments |
||
function a=foo(); |
function a=foo(); |
||
Line 674: | Line 4,310: | ||
% Stating whether arguments are passed by value or by reference |
% Stating whether arguments are passed by value or by reference |
||
% arguments are passed by value, however Matlab has delayed evaluation, such that a copy of large data structures are done only when an element is written to. |
% arguments are passed by value, however Matlab has delayed evaluation, such that a copy of large data structures are done only when an element is written to. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Nanoquery}}== |
|||
<syntaxhighlight lang="nanoquery">// function with no arguments |
|||
no_args() |
|||
// function with fixed amount of arguments |
|||
three_args(a, b, c) |
|||
// nanoquery does not support optional, variable, or named arguments |
|||
// obtaining a return value |
|||
value = returns_value() |
|||
// checking if a function called "func" is user-defined |
|||
try |
|||
type(func) |
|||
println "func is user-defined" |
|||
catch |
|||
println "func is a built-in or doesn't exist" |
|||
end</syntaxhighlight> |
|||
=={{header|Nemerle}}== |
=={{header|Nemerle}}== |
||
< |
<syntaxhighlight lang="nemerle">// no arguments |
||
f() |
f() |
||
Line 733: | Line 4,387: | ||
def h = f(_, 2) |
def h = f(_, 2) |
||
def a = g(3) // equivalent to: def a = f(2, 3) |
def a = g(3) // equivalent to: def a = f(2, 3) |
||
def b = h(3) // equivalent to: def b = f(3, 2)</ |
def b = h(3) // equivalent to: def b = f(3, 2)</syntaxhighlight> |
||
=={{header|Nim}}== |
|||
Translated from Python, when possible: |
|||
<syntaxhighlight lang="nim">proc no_args() = |
|||
discard |
|||
# call |
|||
no_args() |
|||
proc fixed_args(x, y) = |
|||
echo x |
|||
echo y |
|||
# calls |
|||
fixed_args(1, 2) # x=1, y=2 |
|||
fixed_args 1, 2 # same call |
|||
1.fixed_args(2) # same call |
|||
proc opt_args(x=1.0) = |
|||
echo x |
|||
# calls |
|||
opt_args() # 1 |
|||
opt_args(3.141) # 3.141 |
|||
proc var_args(v: varargs[string, `$`]) = |
|||
for x in v: echo x |
|||
# calls |
|||
var_args(1, 2, 3) # (1, 2, 3) |
|||
var_args(1, (2,3)) # (1, (2, 3)) |
|||
var_args() # () |
|||
## Named arguments |
|||
fixed_args(y=2, x=1) # x=1, y=2 |
|||
## As a statement |
|||
if true: |
|||
no_args() |
|||
proc return_something(x): int = |
|||
x + 1 |
|||
var a = return_something(2) |
|||
## First-class within an expression |
|||
let x = return_something(19) + 10 |
|||
let y = 19.return_something() + 10 |
|||
let z = 19.return_something + 10</syntaxhighlight> |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
* Calling a function that requires no arguments: |
* Calling a function that requires no arguments: |
||
<lang |
<syntaxhighlight lang="ocaml">f ()</syntaxhighlight> |
||
(In fact it is impossible to call a function without arguments, when there are no particular arguments we provide the type <code>unit</code> which is a type that has only one possible value. This type is mainly made for this use.) |
(In fact it is impossible to call a function without arguments, when there are no particular arguments we provide the type <code>unit</code> which is a type that has only one possible value. This type is mainly made for this use.) |
||
Line 745: | Line 4,443: | ||
* Calling a function with a fixed number of arguments: |
* Calling a function with a fixed number of arguments: |
||
<lang |
<syntaxhighlight lang="ocaml">f 1 2 3</syntaxhighlight> |
||
* Calling a function with optional arguments: |
* Calling a function with optional arguments: |
||
Line 751: | Line 4,449: | ||
For a function that has this signature: |
For a function that has this signature: |
||
< |
<syntaxhighlight lang="ocaml">val f : ?a:int -> int -> unit</syntaxhighlight> |
||
here is how to call it with or without the first argument omited: |
here is how to call it with or without the first argument omited: |
||
< |
<syntaxhighlight lang="ocaml">f 10 |
||
f ~a:6 10</ |
f ~a:6 10</syntaxhighlight> |
||
Due to partial application, an optional argument always has to be followed by a non-optional argument. If the function needs no additional arguments then we use the type <code>unit</code>: |
Due to partial application, an optional argument always has to be followed by a non-optional argument. If the function needs no additional arguments then we use the type <code>unit</code>: |
||
< |
<syntaxhighlight lang="ocaml">g () |
||
g ~b:1.0 ()</ |
g ~b:1.0 ()</syntaxhighlight> |
||
* Calling a function with a variable number of arguments: |
* Calling a function with a variable number of arguments: |
||
Line 773: | Line 4,471: | ||
Named arguments are called '''labels'''. |
Named arguments are called '''labels'''. |
||
<lang |
<syntaxhighlight lang="ocaml">f ~arg:3</syntaxhighlight> |
||
If a variable has the same name than the label we can use this simpler syntax: |
If a variable has the same name than the label we can use this simpler syntax: |
||
< |
<syntaxhighlight lang="ocaml">let arg = 3 in |
||
f ~arg</ |
f ~arg</syntaxhighlight> |
||
* Using a function in statement context: |
* Using a function in statement context: |
||
<lang |
<syntaxhighlight lang="ocaml">(* TODO *)</syntaxhighlight> |
||
* Using a function in first-class context within an expression: |
* Using a function in first-class context within an expression: |
||
Line 790: | Line 4,488: | ||
* Obtaining the return value of a function: |
* Obtaining the return value of a function: |
||
< |
<syntaxhighlight lang="ocaml">let ret = f () |
||
let a, b, c = f () (* if there are several returned values given as a tuple *) |
let a, b, c = f () (* if there are several returned values given as a tuple *) |
||
let _ = f () (* if we want to ignore the returned value *) |
let _ = f () (* if we want to ignore the returned value *) |
||
let v, _ = f () (* if we want to ignore one of the returned value *)</ |
let v, _ = f () (* if we want to ignore one of the returned value *)</syntaxhighlight> |
||
* Distinguishing built-in functions and user-defined functions: |
* Distinguishing built-in functions and user-defined functions: |
||
Line 812: | Line 4,510: | ||
With partial application, the arguments are applied in the same order than they are defined in the signature of the function, except if there are labeled arguments, then it is possible to use these labels to partially apply the arguments in any order. |
With partial application, the arguments are applied in the same order than they are defined in the signature of the function, except if there are labeled arguments, then it is possible to use these labels to partially apply the arguments in any order. |
||
=={{header|Oforth}}== |
|||
Oforth provides functions (global prodecure, without receiver) and methods (need a receiver). |
|||
Oforth uses RPN notation. Arguments must be on the stack before calling a function or method. So, the same syntax is use for calling a function with or without prameters. |
|||
If f is a function and c b a ares objects : |
|||
<syntaxhighlight lang="oforth">a b c f</syntaxhighlight> |
|||
will push c then b then a on the stack then call f. Calling f does not describe if f will use 1, 2 or 3 arguments (or none). |
|||
Oforth adds a notation to describe parameters used by a function. It is only a way to add information about which parameters will be used by f : |
|||
<syntaxhighlight lang="oforth">f(a, b, c)</syntaxhighlight> |
|||
Intepreter will replace this second syntax by the first one. It is only "sugar"... |
|||
<syntaxhighlight lang="oforth">a b c f |
|||
a b f(c) |
|||
a f(b, c) |
|||
f(a, b, c)</syntaxhighlight> |
|||
are the same call to function f and the interpreter will translate all of them into the first one. Which parameters are really used by f will depend on f implementation. |
|||
Methods need a receiver (the object on which the method will apply and the object that will pushed on th stack when self is used into the method body). |
|||
The receiver must be on the top of the stack before calling the method. If a, b, c and r are objects and m a method : |
|||
<syntaxhighlight lang="oforth">a b c r m</syntaxhighlight> |
|||
will call m with r as its receiver. |
|||
It is also possible to use the same "sugar" notation used by functions : |
|||
<syntaxhighlight lang="oforth">r m(a, b, c)</syntaxhighlight> |
|||
=={{header|Ol}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
; note: sign "==>" indicates expected output |
|||
;;; Calling a function that requires no arguments |
|||
(define (no-args-function) |
|||
(print "ok.")) |
|||
(no-args-function) |
|||
; ==> ok. |
|||
;;; Calling a function with a fixed number of arguments |
|||
(define (two-args-function a b) |
|||
(print "a: " a) |
|||
(print "b: " b)) |
|||
(two-args-function 8 13) |
|||
; ==> a: 8 |
|||
; ==> b: 13 |
|||
;;; Calling a function with optional arguments |
|||
(define (optional-args-function a . args) |
|||
(print "a: " a) |
|||
(if (null? args) |
|||
(print "no optional arguments")) |
|||
(if (less? 0 (length args)) |
|||
(print "b: " (car args))) |
|||
(if (less? 1 (length args)) |
|||
(print "c: " (cadr args))) |
|||
; etc... |
|||
) |
|||
(optional-args-function 3) |
|||
; ==> a: 3 |
|||
; ==> no optional arguments |
|||
(optional-args-function 3 8) |
|||
; ==> a: 3 |
|||
; ==> b: 8 |
|||
(optional-args-function 3 8 13) |
|||
; ==> a: 3 |
|||
; ==> b: 8 |
|||
; ==> c: 13 |
|||
(optional-args-function 3 8 13 77) |
|||
; ==> a: 3 |
|||
; ==> b: 8 |
|||
; ==> c: 13 |
|||
;;; Calling a function with a variable number of arguments |
|||
; /same as optional arguments |
|||
;;; Calling a function with named arguments |
|||
; /no named arguments "from the box" is provided, but it can be easily simulated using builtin associative arrays (named "ff") |
|||
(define (named-args-function args) |
|||
(print "a: " (get args 'a 8)) ; 8 is default value if no variable value given |
|||
(print "b: " (get args 'b 13)); same as above |
|||
) |
|||
(named-args-function #empty) |
|||
; ==> a: 8 |
|||
; ==> b: 13 |
|||
(named-args-function (list->ff '((a . 3)))) |
|||
; ==> a: 3 |
|||
; ==> b: 13 |
|||
; or nicer (and shorter) form available from ol version 2.1 |
|||
(named-args-function '{a 3}) |
|||
; ==> a: 3 |
|||
; ==> b: 13 |
|||
(named-args-function '{b 7}) |
|||
; ==> a: 8 |
|||
; ==> b: 7 |
|||
(named-args-function '{a 3 b 7}) |
|||
; ==> a: 3 |
|||
; ==> b: 7 |
|||
;;; Using a function in first-class context within an expression |
|||
(define (first-class-arg-function arg a b) |
|||
(print (arg a b)) |
|||
) |
|||
(first-class-arg-function + 2 3) |
|||
; ==> 5 |
|||
(first-class-arg-function - 2 3) |
|||
; ==> -1 |
|||
;;; Using a function in statement context |
|||
(let ((function (lambda (x) (* x x)))) |
|||
(print (function 4)) |
|||
; ==> 16 |
|||
;(print (function 4)) |
|||
; ==> What is 'function'? |
|||
;;; Obtaining the return value of a function |
|||
(define (return-value-function) |
|||
(print "ok.") |
|||
123) |
|||
(let ((result (return-value-function))) |
|||
(print result)) |
|||
; ==> ok. |
|||
; ==> 123 |
|||
;;; Obtaining the return value of a function while breaking the function execution (for example infinite loop) |
|||
(print |
|||
(call/cc (lambda (return) |
|||
(let loop ((n 0)) |
|||
(if (eq? n 100) |
|||
(return (* n n))) |
|||
(loop (+ n 1))))))) ; this is infinite loop |
|||
; ==> 10000 |
|||
;;; Is partial application possible and how |
|||
(define (make-partial-function n) |
|||
(lambda (x y) |
|||
(print (n x y))) |
|||
) |
|||
(define plus (make-partial-function +)) |
|||
(define minus (make-partial-function -)) |
|||
(plus 2 3) |
|||
; ==> 5 |
|||
(minus 2 3) |
|||
; ==> -1 |
|||
;;; Distinguishing built-in functions and user-defined functions |
|||
; ol has no builtin functions but only eight builtin forms: quote, values, lambda, setq, letq, ifeq, either, values-apply. |
|||
; all other functions is "user-defined", and some of them defined in base library, for example (scheme core) defines if, or, and, zero?, length, append... |
|||
;;; Distinguishing subroutines and functions |
|||
; Both subroutines and functions is a functions in Ol. |
|||
; Btw, the "subroutine" has a different meaning in Ol - the special function that executes simultaneously in own context. The intersubroutine messaging mechanism is provided, sure. |
|||
;;; Stating whether arguments are passed by value or by reference |
|||
; The values in Ol always passed as values and objects always passed as references. If you want to pass an object copy - make a copy by yourself. |
|||
</syntaxhighlight> |
|||
=={{header|ooRexx}}== |
|||
This is to show how a built-in function is invoked when an internal function on the dame name in present. |
|||
<syntaxhighlight lang="oorexx">say 'DATE'() |
|||
Say date() |
|||
Exit |
|||
daTe: Return 'my date' </syntaxhighlight> |
|||
{{out}} |
|||
<pre>H:\>rexx fdate |
|||
31 Mar 2022 |
|||
my date</pre> |
|||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Calling a function is done in GP by writing the name of the function and the arguments, if any, in parentheses. As of version 2.5.0, function calls must use parentheses; some earlier versions allowed functions with an arity of 0 to be called without parentheses. However built-in constants (which are implicit functions of the current precision) can still be called without parentheses. |
Calling a function is done in GP by writing the name of the function and the arguments, if any, in parentheses. As of version 2.5.0, function calls must use parentheses; some earlier versions allowed functions with an arity of 0 to be called without parentheses. However built-in constants (which are implicit functions of the current precision) can still be called without parentheses. |
||
Line 819: | Line 4,695: | ||
Functions can be used when statements would be expected without change. |
Functions can be used when statements would be expected without change. |
||
< |
<syntaxhighlight lang="parigp">f(); \\ zero arguments |
||
sin(Pi/2); \\ fixed number of arguments |
sin(Pi/2); \\ fixed number of arguments |
||
vecsort([5,6]) != vecsort([5,6],,4) \\ optional arguments |
|||
Str("gg", 1, "hh") \\ variable number of arguments |
|||
call(Str, ["gg", 1, "hh"]) \\ variable number of arguments in a vector |
|||
(x->x^2)(3); \\ first-class |
(x->x^2)(3); \\ first-class |
||
x = sin(0); \\ get function value</ |
x = sin(0); \\ get function value</syntaxhighlight> |
||
Built-in functions are like user-defined functions in current versions. In older versions built-in functions cannot be passed as closures. |
Built-in functions are like user-defined functions in current versions. In older versions built-in functions cannot be passed as closures. |
||
Most arguments are passed by reference. Some built-in functions accept arguments (e.g., flags) that are not <code>GEN</code>s; these are passed by value or reference depending on their [[C]] type. See the User's Guide to the PARI Library section 5.7.3, "Parser Codes". |
Most arguments are passed by reference. Some built-in functions accept arguments (e.g., flags) that are not <code>GEN</code>s; these are passed by value or reference depending on their [[C]] type. See the User's Guide to the PARI Library section 5.7.3, "Parser Codes". |
||
=={{header|Pascal}}== |
|||
''see also: [[#Delphi|Delphi]] and [[#Free Pascal|Free Pascal]]'' |
|||
Calling a nullary function and obtaining its return value: |
|||
=={{header|Perl 6}}== |
|||
<syntaxhighlight lang="pascal">foo</syntaxhighlight> |
|||
Fundamentally, nearly everything you do in Perl 6 is a function call if you look hard enough. |
|||
Calling an n-ary function (n ≥ 1) and obtaining its return value: |
|||
<syntaxhighlight lang="pascal">foo(1, 'abc', true)</syntaxhighlight> |
|||
Following are not possible in Pascal as defined by the ISO standards (ISO 7185 and ISO 10206). |
|||
* optional arguments<!-- except for certain _built-in_ _procedures_ [no functions!] --> |
|||
* variable number of arguments<!-- except for certain built-in _procedures_ [no functions!] --> |
|||
* named arguments |
|||
* using a function call as a statement |
|||
* distinguishing built-in functions and user-defined functions |
|||
* distinguishing subroutines and functions |
|||
* stating ''at the call site'' whether arguments are passed by value or by reference |
|||
* partial application |
|||
=={{header|Perl}}== |
|||
The most common syntax; simply calls the function foo on the argument(s) provided. |
|||
<syntaxhighlight lang="perl">foo(); # Call foo on the null list |
|||
&foo(); # Ditto |
|||
foo($arg1, $arg2); # Call foo on $arg1 and $arg2 |
|||
&foo($arg1, $arg2); # Ditto; ignores prototypes</syntaxhighlight> |
|||
Call foo() as a bareword. Only works after the function has been declared, which |
|||
can be done normally or with the use subs pragma. |
|||
<syntaxhighlight lang="perl">foo;</syntaxhighlight> |
|||
Call foo() with the current values of @_<syntaxhighlight lang="perl">&foo;</syntaxhighlight> |
|||
Call foo() with the current values of @_, discarding the previous stack frame. Not your grandfather's (harmful) goto, although the keyword can do both.<syntaxhighlight lang="perl">goto &foo;</syntaxhighlight> |
|||
For subroutines stored in references (anonymous subroutines).<syntaxhighlight lang="perl">&$fooref('foo', 'bar'); |
|||
&{$fooref}('foo', 'bar'); |
|||
$fooref->('foo', 'bar');</syntaxhighlight> |
|||
=={{header|Phix}}== |
|||
{{libheader|Phix/basics}} |
|||
Phix has three kinds of routines: procedure, function, and type. A procedure does not return a value, whereas a function does. |
|||
A type is a specialised kind of function that permits declarations of instances which are automatically validated whenever they are changed, further a type routine always returns either true or false. |
|||
* Phix does not allow implicit discard of function results. The explicit discard statement takes the form |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #0000FF;">{<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">myfunction<span style="color: #0000FF;">(<span style="color: #0000FF;">) |
|||
<!--</syntaxhighlight>--> |
|||
* This is in fact a simple contraction of standard multiple assigment (which can be nested as deeply as you like): |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #0000FF;">{<span style="color: #000000;">cities<span style="color: #0000FF;">,<span style="color: #000000;">populations<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize<span style="color: #0000FF;">(<span style="color: #000000;">muncipalities<span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">{<span style="color: #0000FF;">{<span style="color: #0000FF;">}<span style="color: #0000FF;">,<span style="color: #000000;">populations<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize<span style="color: #0000FF;">(<span style="color: #000000;">muncipalities<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- discard result[1]</span> |
|||
<span style="color: #0000FF;">{<span style="color: #000000;">cities<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #0000FF;">}<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize<span style="color: #0000FF;">(<span style="color: #000000;">muncipalities<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- discard result[2]</span> |
|||
<span style="color: #0000FF;">{<span style="color: #000000;">cities<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize<span style="color: #0000FF;">(<span style="color: #000000;">muncipalities<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- "" |
|||
<!--</syntaxhighlight>--> |
|||
* Calling a function with no parameters still requires the "()" empty argument list. |
|||
* Optional arguments are denoted simply by the presence of a default, and must be grouped on the right: |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">myfunction<span style="color: #0000FF;">(<span style="color: #004080;">integer</span> <span style="color: #000000;">a<span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">b<span style="color: #0000FF;">=<span style="color: #008000;">"default"<span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{<span style="color: #000000;">a<span style="color: #0000FF;">,<span style="color: #000000;">b<span style="color: #0000FF;">}</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #000080;font-style:italic;">--? myfunction() -- illegal, compile-time error</span> |
|||
<span style="color: #0000FF;">?<span style="color: #000000;">myfunction<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- displays {1,"default"}</span> |
|||
<span style="color: #0000FF;">?<span style="color: #000000;">myfunction<span style="color: #0000FF;">(<span style="color: #000000;">2<span style="color: #0000FF;">,<span style="color: #008000;">"that"<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- displays {2,"that"} |
|||
<!--</syntaxhighlight>--> |
|||
* Sequence parameters can be of any length, which is another way to implement optional/variable number of arguments. |
|||
* Named arguments can be specified in any order, with an error if any non-optional parameters are missing: |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #0000FF;">?<span style="color: #000000;">myfunction<span style="color: #0000FF;">(<span style="color: #000000;">b<span style="color: #0000FF;">:=<span style="color: #008000;">"then"<span style="color: #0000FF;">,<span style="color: #000000;">a<span style="color: #0000FF;">:=<span style="color: #000000;">3<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- displays {3,"then"} |
|||
--?myfunction(b:="though") -- compile-time error |
|||
<!--</syntaxhighlight>--> |
|||
* The programmer is free to use either positional parameters or named parameters, or a mixture of both (with positional parameters first). |
|||
* Phix support first-class functions directly, as integers, along with an older routine_id mechanism: |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #008080;">constant</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">r_myfunction</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">routine_id<span style="color: #0000FF;">(<span style="color: #008000;">"myfunction"<span style="color: #0000FF;">)<span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">first_class</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">myfunction</span> |
|||
<span style="color: #0000FF;">?<span style="color: #7060A8;">call_func<span style="color: #0000FF;">(<span style="color: #000000;">r_myfunction<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #000000;">1<span style="color: #0000FF;">}<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- displays {1,"default"}</span> |
|||
<span style="color: #0000FF;">?<span style="color: #7060A8;">call_func<span style="color: #0000FF;">(<span style="color: #000000;">myfunction<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #000000;">1<span style="color: #0000FF;">}<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ""</span> |
|||
<span style="color: #0000FF;">?<span style="color: #7060A8;">call_func<span style="color: #0000FF;">(<span style="color: #000000;">first_class<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #000000;">1<span style="color: #0000FF;">}<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- ""</span> |
|||
<span style="color: #0000FF;">?<span style="color: #000000;">first_class<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- "" |
|||
<!--</syntaxhighlight>--> |
|||
The value of r_my_func can be passed as an argument to any routine, or stored in a table, and invoked in a similar fashion.<br> |
|||
Note however that for performance reasons some builtins do not have a proper routine_id; if you need one you must write a trivial one-line wrapper.<br> |
|||
(For a full list, see psym.e/syminit() calls to AutoAsm(), whereas calls to initialAutoEntry() therein indicate builtins that can have routine_ids.)<br> |
|||
(Routines that do not have a proper routine_id do not support named parameters either.)<br> |
|||
(One day the compiler may be enhanced to automatically create one-line wrappers as needed, but that is quite near the end of a fairly long to-do list.) |
|||
* Partial application is usually achieved through a single variable-length "user_data" parameter within a call_func() expression. |
|||
* All arguments are passed by reference with copy-on-write semantics: to modify the value of a parameter you must both return and assign it, as in: |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append<span style="color: #0000FF;">(<span style="color: #000000;">s<span style="color: #0000FF;">,<span style="color: #000000;">item<span style="color: #0000FF;">) |
|||
<!--</syntaxhighlight>--> |
|||
* Implicit forward calls are supported, as are optional explicit forward declarations, which can occasionally cure compilation error messages. |
|||
=={{header|Phixmonti}}== |
|||
<syntaxhighlight lang="phixmonti">/# Phixmonti does not distinguish between subroutines and functions. |
|||
Each word (as they are called), takes its arguments (if any) from the data stack. #/ |
|||
def saludo |
|||
"Hola mundo" print nl |
|||
enddef |
|||
saludo /# 'saludo' is a user-defined word. #/ |
|||
2 3 + print /# The '+' sign and 'print' are intrinsic words. The return value is deposited on the data stack #/ </syntaxhighlight> |
|||
=={{header|PicoLisp}}== |
|||
When calling a funcion in PicoLisp directly (does this mean "in a statement context"?), it is always surrounded by parentheses, with or without arguments, and for any kind of arguments (evaluated or not): |
|||
<syntaxhighlight lang="picolisp">(foo) |
|||
(bar 1 'arg 2 'mumble)</syntaxhighlight> |
|||
When a function is used in a "first class context" (e.g. passed to another function), then it is not yet '''called'''. It is simply '''used'''. Technically, a function can be either a '''number''' (a built-in function) or a '''list''' (a Lisp-level function) in PicoLisp): |
|||
<syntaxhighlight lang="picolisp">(mapc println Lst) # The value of 'printlin' is a number |
|||
(apply '((A B C) (foo (+ A (* B C)))) (3 5 7)) # A list is passed</syntaxhighlight> |
|||
Any argument to a function may be evaluated or not, depending on the function. For example, 'setq' evaluates every second argument |
|||
<syntaxhighlight lang="picolisp">(setq A (+ 3 4) B (* 3 4))</syntaxhighlight> |
|||
i.e. the first argument 'A' is not evaluated, the second evaluates to 7, 'B' is not evaluated, then the fourth evaluates to 12. |
|||
=={{header|PureBasic}}== |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="purebasic">Procedure Saludo() |
|||
PrintN("Hola mundo!") |
|||
EndProcedure |
|||
Procedure.s Copialo(txt.s, siNo.b, final.s = "") |
|||
Define nuevaCadena.s, resul.s |
|||
For cont.b = 1 To siNo |
|||
nuevaCadena + txt |
|||
Next |
|||
Resul = Trim(nuevaCadena) + final |
|||
ProcedureReturn resul |
|||
EndProcedure |
|||
Procedure testNumeros(a.i, b.i, c.i = 0) |
|||
PrintN(Str(a) + #TAB$ + Str(b) + #TAB$ + Str(c)) |
|||
EndProcedure |
|||
Procedure testCadenas(txt.s) |
|||
For cont.b = 1 To Len(txt) |
|||
Print(Mid(txt,cont,1)) |
|||
Next cont |
|||
EndProcedure |
|||
OpenConsole() |
|||
Saludo() |
|||
PrintN(Copialo("Saludos ", 6)) |
|||
PrintN(Copialo("Saludos ", 3, "!!")) |
|||
PrintN("") |
|||
testNumeros(1, 2, 3) |
|||
testNumeros(1, 2) |
|||
PrintN("") |
|||
testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'") |
|||
Input() |
|||
CloseConsole()</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Same as FreeBASIC entry.</pre> |
|||
=={{header|Python}}== |
|||
Under the hood all Python function/method parameters are named. All arguments can be passed as ''name=value'' pairs or as a dictionary containing such pairs using the ''myfunc('''**key_args''')'' (apply over dictionary) syntax). One can also "apply" a function over a sequence of arguments using the syntax: ''myfunc('''*args''')'' as noted in comments below. Parameters can be mixed so long parameters with default values (optional arguments) follow any "positional" (required) parameters, and catchall parameter ('''''*args''''') follow those, and any "keyword arguments' parameter" is last. (Any function can only have up to one "catchall" or '''''*args'''' parameter and up to one "keyword args" '''''**kwargs''''' parameter). |
|||
<syntaxhighlight lang="python">def no_args(): |
|||
pass |
|||
# call |
|||
no_args() |
|||
def fixed_args(x, y): |
|||
print('x=%r, y=%r' % (x, y)) |
|||
# call |
|||
fixed_args(1, 2) # x=1, y=2 |
|||
## Can also called them using the parameter names, in either order: |
|||
fixed_args(y=2, x=1) |
|||
## Can also "apply" fixed_args() to a sequence: |
|||
myargs=(1,2) # tuple |
|||
fixed_args(*myargs) |
|||
def opt_args(x=1): |
|||
print(x) |
|||
# calls |
|||
opt_args() # 1 |
|||
opt_args(3.141) # 3.141 |
|||
def var_args(*v): |
|||
print(v) |
|||
# calls |
|||
var_args(1, 2, 3) # (1, 2, 3) |
|||
var_args(1, (2,3)) # (1, (2, 3)) |
|||
var_args() # () |
|||
## Named arguments |
|||
fixed_args(y=2, x=1) # x=1, y=2 |
|||
## As a statement |
|||
if 1: |
|||
no_args() |
|||
## First-class within an expression |
|||
assert no_args() is None |
|||
def return_something(): |
|||
return 1 |
|||
x = return_something() |
|||
def is_builtin(x): |
|||
print(x.__name__ in dir(__builtins__)) |
|||
# calls |
|||
is_builtin(pow) # True |
|||
is_builtin(is_builtin) # False |
|||
# Very liberal function definition |
|||
def takes_anything(*args, **kwargs): |
|||
for each in args: |
|||
print(each) |
|||
for key, value in sorted(kwargs.items()): |
|||
print("%s:%s" % (key, value)) |
|||
# Passing those to another, wrapped, function: |
|||
wrapped_fn(*args, **kwargs) |
|||
# (Function being wrapped can have any parameter list |
|||
# ... that doesn't have to match this prototype) |
|||
## A subroutine is merely a function that has no explicit |
|||
## return statement and will return None. |
|||
## Python uses "Call by Object Reference". |
|||
## See, for example, http://www.python-course.eu/passing_arguments.php |
|||
## For partial function application see: |
|||
## http://rosettacode.org/wiki/Partial_function_application#Python</syntaxhighlight> |
|||
=={{header|QBasic}}== |
|||
{{works with|QBasic|1.1}} |
|||
{{works with|QuickBasic|4.5}} |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="qbasic">FUNCTION Copialo$ (txt$, siNo, final$) |
|||
DIM nuevaCadena$ |
|||
FOR cont = 1 TO siNo |
|||
nuevaCadena$ = nuevaCadena$ + txt$ |
|||
NEXT cont |
|||
Copialo$ = LTRIM$(RTRIM$(nuevaCadena$)) + final$ |
|||
END FUNCTION |
|||
SUB Saludo |
|||
PRINT "Hola mundo!" |
|||
END SUB |
|||
SUB testCadenas (txt$) |
|||
FOR cont = 1 TO LEN(txt$) |
|||
PRINT MID$(txt$, cont, 1); ""; |
|||
NEXT cont |
|||
END SUB |
|||
SUB testNumeros (a, b, c) |
|||
PRINT a, b, c |
|||
END SUB |
|||
CALL Saludo |
|||
PRINT Copialo$("Saludos ", 6, "") |
|||
PRINT Copialo$("Saludos ", 3, "!!") |
|||
PRINT |
|||
CALL testNumeros(1, 2, 3) |
|||
CALL testNumeros(1, 2, 0) |
|||
PRINT |
|||
CALL testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Igual que la entrada de FreeBASIC. |
|||
</pre> |
|||
=={{header|Quackery}}== |
|||
Words in Quackery take zero or more arguments from the (programmer accessible) data stack, and return zero or more results to the data stack. |
|||
In this dialogue in the Quackery shell, <code>/mod</code> takes two arguments and returns two results, <code>pack</code> takes three arguments (the topmost argument on the stack (<code>2</code>) specifies how many more arguments it is to take from the stack), <code>echo</code> takes one argument and returns no results, and <code>cr</code> takes no arguments and returns no results. |
|||
<pre>/O> 123 7 /mod |
|||
... |
|||
Stack: 17 4 |
|||
/O> 2 pack |
|||
... |
|||
Stack: [ 17 4 ] |
|||
/O> echo cr |
|||
... |
|||
[ 17 4 ] |
|||
Stack empty.</pre> |
|||
Words can also take one or more items (nests, words or numbers) and arbitrary strings of text following the word as arguments. For example, <code>times</code> performs the item following it a specified number of times, and <code>say</code> echoes the string following it to the terminal. |
|||
<pre>/O> 4 times [ 3 times [ say "badger" sp ] cr ] |
|||
... 2 times [ say "mushroom" sp ] cr |
|||
... |
|||
badger badger badger |
|||
badger badger badger |
|||
badger badger badger |
|||
badger badger badger |
|||
mushroom mushroom |
|||
Stack empty. |
|||
</pre> |
|||
=={{header|R}}== |
|||
Translated from Python, when possible. |
|||
<syntaxhighlight lang="rsplus">### Calling a function that requires no arguments |
|||
no_args <- function() NULL |
|||
no_args() |
|||
### Calling a function with a fixed number of arguments |
|||
fixed_args <- function(x, y) print(paste("x=", x, ", y=", y, sep="")) |
|||
fixed_args(1, 2) # x=1, y=2 |
|||
fixed_args(y=2, x=1) # y=1, x=2 |
|||
### Calling a function with optional arguments |
|||
opt_args <- function(x=1) x |
|||
opt_args() # x=1 |
|||
opt_args(3.141) # x=3.141 |
|||
### Calling a function with a variable number of arguments |
|||
var_args <- function(...) print(list(...)) |
|||
var_args(1, 2, 3) |
|||
var_args(1, c(2,3)) |
|||
var_args() |
|||
### Calling a function with named arguments |
|||
fixed_args(y=2, x=1) # x=1, y=2 |
|||
### Using a function in statement context |
|||
if (TRUE) no_args() |
|||
### Using a function in first-class context within an expression |
|||
print(no_args) |
|||
### Obtaining the return value of a function |
|||
return_something <- function() 1 |
|||
x <- return_something() |
|||
x |
|||
### Distinguishing built-in functions and user-defined functions |
|||
# Not easily possible. See |
|||
# http://cran.r-project.org/doc/manuals/R-ints.html#g_t_002eInternal-vs-_002ePrimitive |
|||
# for details. |
|||
### Distinguishing subroutines and functions |
|||
# No such distinction. |
|||
### Stating whether arguments are passed by value or by reference |
|||
# Pass by value. |
|||
### Is partial application possible and how |
|||
# Yes, see http://rosettacode.org/wiki/Partial_function_application#R</syntaxhighlight> |
|||
=={{header|Racket}}== |
|||
<syntaxhighlight lang="racket"> |
|||
#lang racket |
|||
;; Calling a function that requires no arguments |
|||
(foo) |
|||
;; Calling a function with a fixed number of arguments |
|||
(foo 1 2 3) |
|||
;; Calling a function with optional arguments |
|||
;; Calling a function with a variable number of arguments |
|||
(foo 1 2 3) ; same in both cases |
|||
;; Calling a function with named arguments |
|||
(foo 1 2 #:x 3) ; using #:keywords for the names |
|||
;; Using a function in statement context |
|||
;; Using a function in first-class context within an expression |
|||
;; Obtaining the return value of a function |
|||
;; -> Makes no sense for Racket, as well as most other functional PLs |
|||
;; Distinguishing built-in functions and user-defined functions |
|||
(primitive? foo) |
|||
;; but this is mostly useless, since most of Racket is implemented in |
|||
;; itself |
|||
;; Distinguishing subroutines and functions |
|||
;; -> No difference, though `!' is an idiomatic suffix for names of |
|||
;; side-effect functions, and they usually return (void) |
|||
;; Stating whether arguments are passed by value or by reference |
|||
;; -> Always by value, but it's possible to implement languages with |
|||
;; other argument passing styles, including passing arguments by |
|||
;; reference (eg, there is "#lang algol60") |
|||
;; Is partial application possible and how |
|||
(curry foo 1 2) ; later apply this on 3 |
|||
(λ(x) (foo 1 2 x)) ; a direct way of doing the same |
|||
</syntaxhighlight> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
===Theory=== |
|||
Fundamentally, nearly everything you do in Raku is a function call if you look hard enough. |
|||
At the lowest level, a function call merely requires a reference to any |
At the lowest level, a function call merely requires a reference to any |
||
kind of invokable object, and a call to its <tt>postcircumfix:<( )></tt> method. |
kind of invokable object, and a call to its <tt>postcircumfix:<( )></tt> method. |
||
Line 839: | Line 5,125: | ||
Calling a function that requires no arguments: |
Calling a function that requires no arguments: |
||
<lang |
<syntaxhighlight lang="raku" line>foo # as list operator |
||
foo() # as function |
foo() # as function |
||
foo.() # as function, explicit postfix form |
foo.() # as function, explicit postfix form |
||
Line 846: | Line 5,132: | ||
&foo() # as object invocation |
&foo() # as object invocation |
||
&foo.() # as object invocation, explicit postfix |
&foo.() # as object invocation, explicit postfix |
||
::($name)() # as symbolic ref</ |
::($name)() # as symbolic ref</syntaxhighlight> |
||
Calling a function with exactly one argument: |
Calling a function with exactly one argument: |
||
<lang |
<syntaxhighlight lang="raku" line>foo 1 # as list operator |
||
foo(1) # as named function |
foo(1) # as named function |
||
foo.(1) # as named function, explicit postfix |
foo.(1) # as named function, explicit postfix |
||
Line 862: | Line 5,148: | ||
1.foo() # as method via dispatcher |
1.foo() # as method via dispatcher |
||
1."$name"() # as method via dispatcher, symbolic |
1."$name"() # as method via dispatcher, symbolic |
||
+1 # as operator to prefix:<+> function</ |
+1 # as operator to prefix:<+> function</syntaxhighlight> |
||
Method calls are included here because they do eventually dispatch to a true |
Method calls are included here because they do eventually dispatch to a true |
||
Line 868: | Line 5,154: | ||
to dispatch to the same set of functions that a function call of that name |
to dispatch to the same set of functions that a function call of that name |
||
would invoke. That's why there's a dispatcher, after all. Methods are declared |
would invoke. That's why there's a dispatcher, after all. Methods are declared |
||
with a different keyword, <tt>method</tt>, in |
with a different keyword, <tt>method</tt>, in Raku, but all that does is |
||
install the actual function into a metaclass. Once it's there, it's merely |
install the actual function into a metaclass. Once it's there, it's merely |
||
a function that expects its first argument to be the invocant object. Hence we |
a function that expects its first argument to be the invocant object. Hence we |
||
Line 876: | Line 5,162: | ||
multiply dispatched to all lexically scoped candidates for the function. Hence |
multiply dispatched to all lexically scoped candidates for the function. Hence |
||
the candidate list is bound early, and the function itself can be bound early |
the candidate list is bound early, and the function itself can be bound early |
||
if the type is known. |
if the type is known. Raku maintains a clear distinction between early-bound |
||
linguistic constructs that force Perlish semantics, and late-bound OO dispatch |
linguistic constructs that force Perlish semantics, and late-bound OO dispatch |
||
that puts the objects and/or classes in charge of semantics. (In any case, <tt>&foo</tt>, |
that puts the objects and/or classes in charge of semantics. (In any case, <tt>&foo</tt>, |
||
Line 884: | Line 5,170: | ||
Calling a function with exactly two arguments: |
Calling a function with exactly two arguments: |
||
<lang |
<syntaxhighlight lang="raku" line>foo 1,2 # as list operator |
||
foo(1,2) # as named function |
foo(1,2) # as named function |
||
foo.(1,2) # as named function, explicit postfix |
foo.(1,2) # as named function, explicit postfix |
||
Line 896: | Line 5,182: | ||
1.foo(2) # as method via dispatcher |
1.foo(2) # as method via dispatcher |
||
1."$name"(2) # as method via dispatcher, symbolic |
1."$name"(2) # as method via dispatcher, symbolic |
||
1 + 2 # as operator to infix:<+> function</ |
1 + 2 # as operator to infix:<+> function</syntaxhighlight> |
||
Optional arguments don't look any different from normal arguments. |
Optional arguments don't look any different from normal arguments. |
||
Line 903: | Line 5,189: | ||
Calling a function with a variable number of arguments (varargs): |
Calling a function with a variable number of arguments (varargs): |
||
<lang |
<syntaxhighlight lang="raku" line>foo @args # as list operator |
||
foo(@args) # as named function |
foo(@args) # as named function |
||
foo.(@args) # as named function, explicit postfix |
foo.(@args) # as named function, explicit postfix |
||
Line 915: | Line 5,201: | ||
1.foo(@args) # as method via dispatcher |
1.foo(@args) # as method via dispatcher |
||
1."$name"(@args) # as method via dispatcher, symbolic |
1."$name"(@args) # as method via dispatcher, symbolic |
||
@args X @blargs # as list infix operator to infix:<X></ |
@args X @blargs # as list infix operator to infix:<X></syntaxhighlight> |
||
Note: whether a function may actually be called with a variable number of arguments depends entirely |
Note: whether a function may actually be called with a variable number of arguments depends entirely |
||
on whether a signature accepts a list at that position in the argument list, but |
on whether a signature accepts a list at that position in the argument list, but |
||
describing that is not the purpose of this task. Suffice to say that we assume here that the |
describing that is not the purpose of this task. Suffice to say that we assume here that the |
||
foo function is declared with a signature of the form (*@params). The calls above might be interpreted as having a single array argument if the signature indicates a normal parameter instead of a variadic one. What you cannot do in |
foo function is declared with a signature of the form (*@params). The calls above might be interpreted as having a single array argument if the signature indicates a normal parameter instead of a variadic one. What you cannot do in Raku (unlike Perl 5) is pass an array as several fixed arguments. By default it must either represent a single argument, or be part of a variadic list. You can force the extra level of argument list interpolation using a prefix <tt>|</tt> however: |
||
<lang |
<syntaxhighlight lang="raku" line>my @args = 1,2,3; |
||
foo(|@args); # equivalent to foo(1,2,3)</ |
foo(|@args); # equivalent to foo(1,2,3)</syntaxhighlight> |
||
Calling a function with named arguments: |
Calling a function with named arguments: |
||
<lang |
<syntaxhighlight lang="raku" line>foo :a, :b(4), :!c, d => "stuff" |
||
foo(:a, :b(4), :!c, d => "stuff")</ |
foo(:a, :b(4), :!c, d => "stuff")</syntaxhighlight> |
||
...and so on. Operators may also be called with named arguments, but only |
...and so on. Operators may also be called with named arguments, but only |
||
colon adverbials are allowed: |
colon adverbials are allowed: |
||
<lang |
<syntaxhighlight lang="raku" line>1 + 1 :a :b(4) :!c :d("stuff") # calls infix:<+>(1,1,:a, :b(4), :!c, d => "stuff")</syntaxhighlight> |
||
Using a function in statement context: |
Using a function in statement context: |
||
<lang |
<syntaxhighlight lang="raku" line>foo(); bar(); baz(); # evaluate for side effects</syntaxhighlight> |
||
Using a function in first class context within an expression: |
Using a function in first class context within an expression: |
||
<lang |
<syntaxhighlight lang="raku" line>1 / find-a-func(1,2,3)(4,5,6) ** 2;</syntaxhighlight> |
||
Obtaining the return value of a function: |
Obtaining the return value of a function: |
||
<lang |
<syntaxhighlight lang="raku" line>my $result = somefunc(1,2,3) + 2;</syntaxhighlight> |
||
There is no difference between calling builtins and user-defined functions and operators (or |
There is no difference between calling builtins and user-defined functions and operators (or |
||
even control stuctures). This was a major design goal of |
even control stuctures). This was a major design goal of Raku, and apart from a very few |
||
low-level primitives, all of |
low-level primitives, all of Raku can be written in Raku. |
||
There is no difference between calling subroutines and functions in |
There is no difference between calling subroutines and functions in Raku, other than that |
||
calling a function in void context that has no side effects is likely to get you a "Useless use of..." warning. |
calling a function in void context that has no side effects is likely to get you a "Useless use of..." warning. |
||
And, of course, the fact that pure functions can participate in more optimizations such as constant folding. |
And, of course, the fact that pure functions can participate in more optimizations such as constant folding. |
||
By default, arguments are passed readonly, which allows the implementation to decide whether pass-by-reference or pass-by-value is more efficient on a case-by-case basis. Explicit lvalue, reference, or copy semantics may be requested on a parameter-by-parameter basis, and the entire argument list may be processed raw if that level of control is needed. |
By default, arguments are passed readonly, which allows the implementation to decide whether pass-by-reference or pass-by-value is more efficient on a case-by-case basis. Explicit lvalue, reference, or copy semantics may be requested on a parameter-by-parameter basis, and the entire argument list may be processed raw if that level of control is needed. |
||
===Practice=== |
|||
Demonstrating each of the above-mentioned function calls with actual running code, along with the various extra definitions required to make them work (in certain cases). Arguments are checked, and function name / run-sequence number are displayed upon success. |
|||
<syntaxhighlight lang="raku" line>{ |
|||
state $n; |
|||
multi f () { print ' f' ~ ++$n } |
|||
=={{header|PicoLisp}}== |
|||
multi f ($a) { die if 1 != $a; print ' f' ~ ++$n } |
|||
When calling a funcion in PicoLisp directly (does this mean "in a statement context"?), it is always surrounded by parentheses, with or without arguments, and for any kind of arguments (evaluated or not): |
|||
multi f ($a,$b) { die if 3 != $a+$b; print ' f' ~ ++$n } |
|||
<lang PicoLisp>(foo) |
|||
multi f (@a) { die if @a != [2,3,4]; print ' f' ~ ++$n } |
|||
(bar 1 'arg 2 'mumble)</lang> |
|||
multi f ($a,$b,$c) { die if 2 != $a || 4 != $c; print ' f' ~ ++$n } |
|||
When a function is used in a "first class context" (e.g. passed to another function), then it is not yet '''called'''. It is simply '''used'''. Technically, a function can be either a '''number''' (a built-in function) or a '''list''' (a Lisp-level function) in PicoLisp): |
|||
sub g ($a,*@b) { die if @b != [2,3,4] || 1 != $a; print ' g' ~ ++$n } |
|||
<lang PicoLisp>(mapc println Lst) # The value of 'printlin' is a number |
|||
(apply '((A B C) (foo (+ A (* B C)))) (3 5 7)) # A list is passed</lang> |
|||
Any argument to a function may be evaluated or not, depending on the function. For example, 'setq' evaluates every second argument |
|||
<lang PicoLisp>(setq A (+ 3 4) B (* 3 4))</lang> |
|||
i.e. the first argument 'A' is not evaluated, the second evaluates to 7, 'B' is not evaluated, then the fourth evaluates to 12. |
|||
my \i = -> { print ' i' ~ ++$n } |
|||
=={{header|Python}}== |
|||
my \l = -> $a { die if 1 != $a; print ' l' ~ ++$n } |
|||
<lang python>def no_args(): |
|||
my \m = -> $a,$b { die if 1 != $a || 2 != $b; print ' m' ~ ++$n } |
|||
pass |
|||
my \n = -> @a { die if @a != [2,3,4]; print ' n' ~ ++$n } |
|||
# call |
|||
no_args() |
|||
Int.^add_method( 'j', method () |
|||
def fixed_args(x, y): |
|||
{ die if 1 != self; print ' j' ~ ++$n } ); |
|||
print('x=%r, y=%r' % (x, y)) |
|||
Int.^add_method( 'k', method ($a) |
|||
# call |
|||
{ die if 1 != self || 2 != $a; print ' k' ~ ++$n } ); |
|||
fixed_args(1, 2) # x=1, y=2 |
|||
Int.^add_method( 'h', method (@a) |
|||
{ die if @a != [2,3,4] || 1 != self; print ' h' ~ ++$n } ); |
|||
my $ref = &f; # soft ref |
|||
def opt_args(x=1): |
|||
my $f := &f; # hard ref |
|||
print(x) |
|||
my $g := &g; # hard ref |
|||
# calls |
|||
my $f-sym = '&f'; # symbolic ref |
|||
opt_args() # 1 |
|||
my $g-sym = '&g'; # symbolic ref |
|||
opt_args(3.141) # 3.141 |
|||
my $j-sym = 'j'; # symbolic ref |
|||
my $k-sym = 'k'; # symbolic ref |
|||
my $h-sym = 'h'; # symbolic ref |
|||
# Calling a function with no arguments: |
|||
def var_args(*v): |
|||
print(v) |
|||
# calls |
|||
var_args(1, 2, 3) # (1, 2, 3) |
|||
var_args(1, (2,3)) # (1, (2, 3)) |
|||
var_args() # () |
|||
f; # 1 as list operator |
|||
## Named arguments |
|||
f(); # 2 as function |
|||
fixed_args(y=2, x=1) # x=1, y=2 |
|||
i.(); # 3 as function, explicit postfix form # defined via pointy-block |
|||
$ref(); # 4 as object invocation |
|||
$ref.(); # 5 as object invocation, explicit postfix |
|||
&f(); # 6 as object invocation |
|||
&f.(); # 7 as object invocation, explicit postfix |
|||
::($f-sym)(); # 8 as symbolic ref |
|||
# Calling a function with exactly one argument: |
|||
## As a statement |
|||
if 1: |
|||
no_args() |
|||
f 1; # 9 as list operator |
|||
## First-class within an expression |
|||
f(1); # 10 as named function |
|||
assert no_args() is None |
|||
l.(1); # 11 as named function, explicit postfix # defined via pointy-block |
|||
$f(1); # 12 as object invocation (must be hard ref) |
|||
$ref.(1); # 13 as object invocation, explicit postfix |
|||
1.$f; # 14 as pseudo-method meaning $f(1) (hard ref only) |
|||
1.$f(); # 15 as pseudo-method meaning $f(1) (hard ref only) |
|||
1.&f; # 16 as pseudo-method meaning &f(1) (is hard f) |
|||
1.&f(); # 17 as pseudo-method meaning &f(1) (is hard f) |
|||
1.j; # 18 as method via dispatcher # requires custom method, via 'Int.^add_method' |
|||
1.j(); # 19 as method via dispatcher |
|||
1."$j-sym"(); # 20 as method via dispatcher, symbolic |
|||
# Calling a function with exactly two arguments: |
|||
def return_something(): |
|||
return 1 |
|||
x = return_something() |
|||
f 1,2; # 21 as list operator |
|||
def is_builtin(x): |
|||
f(1,2); # 22 as named function |
|||
print(x.__name__ in dir(__builtins__)) |
|||
m.(1,2); # 23 as named function, explicit postfix # defined via pointy-block |
|||
# calls |
|||
$ref(1,2); # 24 as object invocation (must be hard ref) |
|||
is_builtin(pow) # True |
|||
$ref.(1,2); # 25 as object invocation, explicit postfix |
|||
is_builtin(is_builtin) # False |
|||
1.$f: 2; # 26 as pseudo-method meaning $f(1,2) (hard ref only) |
|||
1.$f(2); # 27 as pseudo-method meaning $f(1,2) (hard ref only) |
|||
1.&f: 2; # 28 as pseudo-method meaning &f(1,2) (is hard f) |
|||
1.&f(2); # 29 as pseudo-method meaning &f(1,2) (is hard f) |
|||
1.k: 2; # 30 as method via dispatcher # requires custom method, via 'Int.^add_method' |
|||
1.k(2); # 31 as method via dispatcher |
|||
1."$k-sym"(2); # 32 as method via dispatcher, symbolic |
|||
# Calling a function with a variable number of arguments (varargs): |
|||
## A subroutine is merely a function that has no explicit |
|||
## return statement and will return None. |
|||
my @args = 2,3,4; |
|||
## Python uses "Call by Object Reference". |
|||
## See, for example, http://www.python-course.eu/passing_arguments.php |
|||
f @args; # 33 as list operator |
|||
## For partial function application see: |
|||
f(@args); # 34 as named function |
|||
## http://rosettacode.org/wiki/Partial_function_application#Python</lang> |
|||
n.(@args); # 35 as named function, explicit postfix # defined via pointy-block |
|||
$ref(@args); # 36 as object invocation (must be hard ref) |
|||
$ref.(@args); # 37 as object invocation, explicit postfix |
|||
1.$g: @args; # 38 as pseudo-method meaning $f(1,@args) (hard ref) |
|||
1.$g(@args); # 39 as pseudo-method meaning $f(1,@args) (hard ref) |
|||
1.&g: @args; # 40 as pseudo-method meaning &f(1,@args) |
|||
1.&g(@args); # 41 as pseudo-method meaning &f(1,@args) |
|||
1.h: @args; # 42 as method via dispatcher # requires custom method, via 'Int.^add_method' |
|||
1.h(@args); # 43 as method via dispatcher |
|||
1."$h-sym"(@args); # 44 as method via dispatcher, symbolic |
|||
f(|@args); # 45 equivalent to f(1,2,3) |
|||
}</syntaxhighlight> |
|||
=={{header|Racket}}== |
|||
{{out}} |
|||
<pre>f1 f2 i3 f4 f5 f6 f7 f8 f9 f10 l11 f12 f13 f14 f15 f16 f17 j18 j19 j20 f21 f22 m23 f24 f25 f26 f27 f28 f29 k30 k31 k32 f33 f34 n35 f36 f37 g38 g39 g40 g41 h42 h43 h44 f45</pre> |
|||
=={{header|REXX}}== |
|||
===version 1=== |
|||
<syntaxhighlight lang="rexx">/*REXX pgms demonstrates various methods/approaches of invoking/calling a REXX function.*/ |
|||
/*╔════════════════════════════════════════════════════════════════════╗ |
|||
<lang Racket> |
|||
║ Calling a function that REQUIRES no arguments. ║ |
|||
#lang racket |
|||
║ ║ |
|||
║ In the REXX language, there is no way to require the caller to not ║ |
|||
║ pass arguments, but the programmer can check if any arguments were ║ |
|||
║ (or weren't) passed. ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
yr= yearFunc() /*the function name is caseless if it isn't */ |
|||
;; Calling a function that requires no arguments |
|||
/*enclosed in quotes (') or apostrophes (").*/ |
|||
(foo) |
|||
say 'year=' yr |
|||
exit /*stick a fork in it, we're all done. */ |
|||
yearFunc: procedure /*function ARG returns the # of args.*/ |
|||
;; Calling a function with a fixed number of arguments |
|||
errmsg= '***error***' /*an error message eyecatcher string. */ |
|||
(foo 1 2 3) |
|||
if arg() \== 0 then say errmsg "the YEARFUNC function won't accept arguments." |
|||
return left( date('Sorted'), 3)</syntaxhighlight> |
|||
;; Calling a function with optional arguments |
|||
;; Calling a function with a variable number of arguments |
|||
(foo 1 2 3) ; same in both cases |
|||
<syntaxhighlight lang="rexx"> /*╔════════════════════════════════════════════════════════════════════╗ |
|||
;; Calling a function with named arguments |
|||
║ Calling a function with a fixed number of arguments. ║ |
|||
(foo 1 2 #:x 3) ; using #:keywords for the names |
|||
║ ║ |
|||
║ I take this to mean that the function requires a fixed number of ║ |
|||
║ arguments. As above, REXX doesn't enforce calling (or invoking) ║ |
|||
║ a (any) function with a certain number of arguments, but the ║ |
|||
║ programmer can check if the correct number of arguments have been ║ |
|||
║ specified (or not). ║ |
|||
║ In some languages, these are known as "generic" functions. ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
ggg= FourFunc(12, abc, 6+q, zz%2, 'da 5th disagreement') |
|||
;; Using a function in statement context |
|||
say 'ggg squared=' ggg**2 |
|||
;; Using a function in first-class context within an expression |
|||
exit /*stick a fork in it, we're all done. */ |
|||
;; Obtaining the return value of a function |
|||
;; -> Makes no sense for Racket, as well as most other functional PLs |
|||
FourFunc: procedure; parse arg a1,a2,a3 /*obtain the first three arguments. */ |
|||
;; Distinguishing built-in functions and user-defined functions |
|||
a4= arg(4) /*another way to obtain the 4th arg. */ |
|||
(primitive? foo) |
|||
errmsg= '***error***' /*an error message eyecatcher string. */ |
|||
;; but this is mostly useless, since most of Racket is implemented in |
|||
if arg() \== 4 then do |
|||
;; itself |
|||
say err "FourFunc function requires 4 arguments," |
|||
say err "but instead it found" arg() 'arguments.' |
|||
exit 13 /*exit function with a RC of 13*/ |
|||
end |
|||
return a1 + a2 + a3 + a4</syntaxhighlight> |
|||
;; Distinguishing subroutines and functions |
|||
;; -> No difference, though `!' is an idiomatic suffix for names of |
|||
;; side-effect functions, and they usually return (void) |
|||
;; Stating whether arguments are passed by value or by reference |
|||
<syntaxhighlight lang="rexx"> /*╔════════════════════════════════════════════════════════════════════╗ |
|||
;; -> Always by value, but it's possible to implement languages with |
|||
║ Calling a function with optional arguments. ║ |
|||
;; other argument passing styles, including passing arguments by |
|||
║ ║ |
|||
;; reference (eg, there is "#lang algol60") |
|||
║ Note that not passing an argument isn't the same as passing a null ║ |
|||
║ argument (a REXX variable whose value is length zero). ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
x= 12; w= x/2; y= x**2; z= x//7 /* z is x modulo seven. */ |
|||
;; Is partial application possible and how |
|||
say 'sum of w, x, y, & z=' SumIt(w,x,y,,z) /*pass five args, the 4th arg is "null"*/ |
|||
(curry foo 1 2) ; later apply this on 3 |
|||
exit /*stick a fork in it, we're all done. */ |
|||
(λ(x) (foo 1 2 x)) ; a direct way of doing the same |
|||
</lang> |
|||
SumIt: procedure |
|||
=={{header|REXX}}== |
|||
$= 0 /*initialize the sum to zero. */ |
|||
===version 1=== |
|||
do j=1 for arg() /*obtain the sum of a number of args. */ |
|||
<lang rexx>/*REXX program to demonstrate various methods of calling a REXX function*/ |
|||
if arg(j,'E') then $= $ + arg(j) /*the Jth arg may have been omitted. */ |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
end /*j*/ |
|||
│ │ |
|||
│ In the REXX language, there is no way to require the caller to not │ |
|||
│ pass arguments, but the programmer can check if any arguments were │ |
|||
│ (or weren't) passed. │ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
yr=yearFunc() |
|||
say 'year=' yr |
|||
exit |
|||
return $</syntaxhighlight> |
|||
yearFunc: procedure |
|||
if arg()\==0 then call sayErr "SomeFunc function won't accept arguments." |
|||
return left(date('Sorted'),3) |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ Calling a function with a fixed number of arguments. │ |
|||
│ │ |
|||
│ I take this to mean that the function requires a fixed number of │ |
|||
│ arguments. As above, REXX doesn't enforce calling (or invoking) │ |
|||
│ a (any) function with a certain number of arguments, but the │ |
|||
│ programmer can check if the correct number of arguments have been │ |
|||
│ specified (or not). │ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
ggg=FourFunc(12,abc,6+q,zz%2,'da 5th disagreement') |
|||
say 'ggg squared=' ggg**2 |
|||
exit |
|||
FourFunc: procedure; parse arg a1,a2,a3; a4=arg(4) /*another way get a4*/ |
|||
<syntaxhighlight lang="rexx"> /*╔════════════════════════════════════════════════════════════════════╗ |
|||
if arg()\==4 then do |
|||
║ Calling a function with a variable number of arguments. ║ |
|||
║ ║ |
|||
║ This situation isn't any different then the previous example. ║ |
|||
║ It's up to the programmer to code how to utilize the arguments. ║ |
|||
end |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
return a1+a2+a3+a4 |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ Calling a function with optional arguments. │ |
|||
│ │ |
|||
│ Note that not passing an argument isn't the same as passing a null │ |
|||
│ argument (a REXX variable whose value is length zero). │ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
x=12; w=x/2; y=x**2; z=x//7 /* z is x modulo seven.*/ |
|||
say 'sum of w, x, y, & z=' SumIt(w,x,y,,z) /*pass 5 args, 4th is null*/ |
|||
exit |
|||
/*╔════════════════════════════════════════════════════════════════════╗ |
|||
SumIt: procedure; sum=0 |
|||
║ Calling a function with named arguments. ║ |
|||
║ ║ |
|||
║ REXX allows almost anything to be passed, so the following is one ║ |
|||
║ way this can be accomplished. ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
what= parserFunc('name=Luna', "gravity=.1654", 'moon=yes') |
|||
do j=1 for arg() |
|||
say 'name=' common.name |
|||
if arg(j,'E') then sum=sum+arg(j) /*the Jth arg may have been omitted*/ |
|||
gr= common.gr |
|||
end |
|||
return sum |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ Calling a function with a variable number of arguments. │ |
|||
│ │ |
|||
│ This situation isn't any different then the previous example. │ |
|||
│ It's up to the programmer to code how to utilize the arguments. │ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ Calling a function with named arguments. │ |
|||
│ │ |
|||
│ REXX allows almost anything to be passed, so the following is one │ |
|||
│ way this can be accomplished. │ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
what=parserFunc('name=Luna',"gravity=.1654",'moon=yes') |
|||
say 'name=' common.name |
|||
gr=common.gr |
|||
say 'gravity=' gr |
say 'gravity=' gr |
||
exit /*stick a fork in it, we're all done. */ |
|||
exit |
|||
parseFunc: procedure expose common. |
parseFunc: procedure expose common. |
||
do j=1 for arg() |
do j=1 for arg() |
||
parse var arg(j) name '=' val |
parse var arg(j) name '=' val |
||
upper name /*uppercase it.*/ |
|||
upper name |
|||
call value 'COMMON.'name,val |
call value 'COMMON.'name,val |
||
end |
end |
||
return arg() |
return arg()</syntaxhighlight> |
||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ Calling a function in statement context. │ |
|||
<syntaxhighlight lang="rexx"> /*╔════════════════════════════════════════════════════════════════════╗ |
|||
│ │ |
|||
║ Calling a function in statement context. ║ |
|||
│ REXX allows functions to be called (invoked) two ways, the first │ |
|||
║ ║ |
|||
│ example (above) is calling a function in statement context. │ |
|||
║ REXX allows functions to be called (invoked) two ways, the first ║ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
║ example (above) is calling a function in statement context. ║ |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
│ Calling a function in within an expression. │ |
|||
│ │ |
|||
/*╔════════════════════════════════════════════════════════════════════╗ |
|||
│ This is a variant of the first example. │ |
|||
║ Calling a function in within an expression. ║ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
║ ║ |
|||
yr=yearFunc()+20 |
|||
║ This is a variant of the first example. ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
yr= yearFunc() + 20 |
|||
say 'two decades from now, the year will be:' yr |
say 'two decades from now, the year will be:' yr |
||
exit /*stick a fork in it, we're all done. */</syntaxhighlight> |
|||
exit |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ Obtaining the return value of a function. │ |
|||
<syntaxhighlight lang="rexx"> /*╔════════════════════════════════════════════════════════════════════╗ |
|||
│ │ |
|||
║ Obtaining the return value of a function. ║ |
|||
║ ║ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
║ There are 2 ways to get the (return) value (RESULT) of a function. ║ |
|||
currYear=yearFunc() |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
say 'the current year is' currYear |
|||
currYear= yearFunc() |
|||
say 'the current year is' currYear |
|||
call yearFunc |
call yearFunc |
||
say 'the current year is' result |
say 'the current year is' result /*result can be RESULT, it is caseless.*/</syntaxhighlight> |
||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ Distinguishing built-in functions and user-defined functions. │ |
|||
<syntaxhighlight lang="rexx"> /*╔════════════════════════════════════════════════════════════════════╗ |
|||
│ │ |
|||
║ Distinguishing built-in functions and user-defined functions. ║ |
|||
│ One objective of the REXX language is to allow the user to use any │ |
|||
║ ║ |
|||
│ function (or subroutine) name whether or not there is a built-in │ |
|||
║ One objective of the REXX language is to allow the user to use any ║ |
|||
│ function with the same name (there isn't a penality for this). │ |
|||
║ function (or subroutine) name whether or not there is a built-in ║ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
║ function with the same name (there isn't a penality for this). ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
say "Bob's been out" qqq 'times.' |
|||
www='DATE'('USA') /*returns date in format mm/dd/yyy */ |
|||
/*date: as in going out with someone. */ |
|||
qqq= date() /*number of real dates that Bob was on.*/ |
|||
/*hopefully, it accurately counts dates*/ |
|||
say "Bob's been out" qqq 'times.' |
|||
www= 'DATE'("USA") /*returns date in format mm/dd/yyyy */ |
|||
/*any function in quotes is external. */ |
|||
exit /*stick a fork in it, we're all done. */ |
|||
date: return 4 /*Bob only "went out" 4 times, no need */ |
|||
/* to actually count, he quit after 4. */</syntaxhighlight> |
|||
<syntaxhighlight lang="rexx"> /*╔════════════════════════════════════════════════════════════════════╗ |
|||
║ Distinguishing subroutines and functions. ║ |
|||
║ ║ |
|||
║ There is no programmatic difference between subroutines and ║ |
|||
║ functions if the subroutine returns a value (which effectively ║ |
|||
║ makes it a function). REXX allows you to call a function as if ║ |
|||
║ it were a subroutine. ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
/*╔════════════════════════════════════════════════════════════════════╗ |
|||
║ In REXX, all arguments are passed by value, never by name, but it ║ |
|||
║ is possible to accomplish this if the variable's name is passed ║ |
|||
║ and the subroutine/function could use the built-in-function VALUE ║ |
|||
║ to retrieve the variable's value. ║ |
|||
╚════════════════════════════════════════════════════════════════════╝*/ |
|||
/*╔════════════════════════════════════════════════════════════════════╗ |
|||
date: return 4 |
|||
║ In the REXX language, partial application is possible, depending ║ |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
║ how partial application is defined; I prefer the 1st definition ║ |
|||
║ (as per the "discussion" for "Partial Function Application" task: ║ |
|||
║ 1. The "syntactic sugar" that allows one to write some examples ║ |
|||
│ There is no programatic difference between subroutines and │ |
|||
║ are: map (f 1 9) [1..9] ║ |
|||
│ functions if the subroutine returns a value (which effectively │ |
|||
║ or: map (f(1,_,9)) [1, ..., 9] ║ |
|||
│ makes it a function). REXX allows you to call a function as if │ |
|||
╚════════════════════════════════════════════════════════════════════╝*/</syntaxhighlight> |
|||
│ it were a subroutine. │ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ In REXX, all arguments are passed by value, never by name, but it │ |
|||
│ is possible to accomplish this if the variable's name is passed │ |
|||
│ and the subroutine/function could use the built-in-function VALUE │ |
|||
│ to retrieve the variable's value. │ |
|||
└────────────────────────────────────────────────────────────────────┘*/ |
|||
/*┌────────────────────────────────────────────────────────────────────┐ |
|||
│ In the REXX language, partial application is possible, depending │ |
|||
│ how partial application is defined; I prefer the 1st definition (as│ |
|||
│ (as per the "discussion" for "Partial Function Application" task: │ |
|||
│ 1. The "syntactic sugar" that allows one to write (some examples│ |
|||
│ are: map (f 7 9) [1..9] │ |
|||
│ or: map(f(7,_,9),{1,...,9}) │ |
|||
└────────────────────────────────────────────────────────────────────┘*/</lang> |
|||
===version 2=== |
===version 2=== |
||
< |
<syntaxhighlight lang="rexx">/* REXX *************************************************************** |
||
* 29.07.2013 Walter Pachl trying to address the task concisely |
* 29.07.2013 Walter Pachl trying to address the task concisely |
||
*********************************************************************** |
*********************************************************************** |
||
Line 1,280: | Line 5,588: | ||
If sigl=39 Then |
If sigl=39 Then |
||
Say 'fb cannot be invoked as function (it does not return a value' |
Say 'fb cannot be invoked as function (it does not return a value' |
||
Exit</ |
Exit</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
f1 doesn't need an argument |
f1 doesn't need an argument |
||
Line 1,317: | Line 5,625: | ||
x=fb(1,2) |
x=fb(1,2) |
||
rc=44 (Function or message did not return data) |
rc=44 (Function or message did not return data) |
||
fb cannot be invoked as function (it does not return a value |
fb cannot be invoked as function (it does not return a value)</pre> |
||
=={{header|Ring}}== |
|||
</pre> |
|||
<syntaxhighlight lang="ring"> |
|||
hello() |
|||
func hello |
|||
see "Hello from function" + nl |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ring"> |
|||
first() second() |
|||
func first see "message from the first function" + nl |
|||
func second see "message from the second function" + nl |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ring"> |
|||
sum(3,5) sum(1000,2000) |
|||
func sum x,y see x+y+nl |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="ring"> |
|||
# this program will print the hello world message first then execute the main function |
|||
See "Hello World!" + nl |
|||
func main |
|||
see "Message from the main function" + nl |
|||
</syntaxhighlight> |
|||
=={{header|Ruby}}== |
|||
Ruby does not have functions, but Ruby classes have "methods" which are equivalent. |
|||
The parentheses around the arguments are optional (definition and call). |
|||
A method returns the last expression that was evaluated in the body of the method. |
|||
The return keyword can be used to make it explicit that a method returns a value. |
|||
*Calling a function that requires no arguments |
|||
:<syntaxhighlight lang="ruby">def foo() p "foo" end |
|||
foo #=> "foo" |
|||
foo() #=> "foo"</syntaxhighlight> |
|||
*Calling a function with a fixed number of arguments |
|||
:<syntaxhighlight lang="ruby">def foo arg; p arg end # one argument |
|||
foo(1) #=> 1 |
|||
foo "1" #=> "1" |
|||
foo [0,1,2] #=> [0, 1, 2] (one Array)</syntaxhighlight> |
|||
*Calling a function with optional arguments |
|||
:<syntaxhighlight lang="ruby">def foo(x=0, y=x, flag=true) p [x,y,flag] end |
|||
foo #=> [0, 0, true] |
|||
foo(1) #=> [1, 1, true] |
|||
foo(1,2) #=> [1, 2, true] |
|||
foo 1,2,false #=> [1, 2, false]</syntaxhighlight> |
|||
*Calling a function with a variable number of arguments |
|||
:<syntaxhighlight lang="ruby">def foo(*args) p args end |
|||
foo #=> [] |
|||
foo(1,2,3,4,5) #=> [1, 2, 3, 4, 5]</syntaxhighlight> |
|||
*Calling a function with named arguments |
|||
:<syntaxhighlight lang="ruby">def foo(id:0, name:"", age:0) p [id, name, age] end |
|||
foo(age:22, name:"Tom") #=> [0, "Tom", 22]</syntaxhighlight> |
|||
*Using a function in statement context |
|||
::? |
|||
*Using a function in first-class context within an expression |
|||
:The method is not a first-class function. However, there is '''Proc''' object. |
|||
::See [[First-class functions#Ruby]] |
|||
*Obtaining the return value of a function |
|||
:<syntaxhighlight lang="ruby">def foo(a,b) a + b end |
|||
bar = foo 10,20 |
|||
p bar #=> 30 |
|||
p foo("abc","def") #=> "abcdef" |
|||
# return multiple values |
|||
def sum_and_product(a,b) return a+b,a*b end |
|||
x,y = sum_and_product(3,5) |
|||
p x #=> 8 |
|||
p y #=> 15</syntaxhighlight> |
|||
*Distinguishing built-in functions and user-defined functions |
|||
::There is no distinction. |
|||
*Distinguishing subroutines and functions |
|||
:Subroutine and function don't exist at ruby. It is only a method that there is. |
|||
::The Kernel module is included by class Object, so its methods are available in every Ruby object. |
|||
::These methods are called without a receiver and thus can be called in functional form. |
|||
::<syntaxhighlight lang="ruby">puts "OK!" # Kernel#puts |
|||
raise "Error input" # Kernel#raise |
|||
Integer("123") # Kernel#Integer |
|||
rand(6) # Kernel#rand |
|||
throw(:exit) # Kernel#throw |
|||
# method which can be seen like a reserved word. |
|||
attr_accessor # Module#attr_accessor |
|||
include # Module#include |
|||
private # Module#private |
|||
require # Kernel#require |
|||
loop { } # Kernel#loop</syntaxhighlight> |
|||
*Stating whether arguments are passed by value or by reference |
|||
::passed by value of object reference. |
|||
*Is partial application possible and how |
|||
::However something similar can be done, see [[Partial function application#Ruby]] |
|||
*Others |
|||
:Block Argument: |
|||
::The block argument sends a closure from the calling scope to the method. |
|||
::The block argument is always last when sending a message to a method. A block is sent to a method using <code>do ... end</code> or <code>{ ... }</code>. |
|||
::<syntaxhighlight lang="ruby">class Array |
|||
def sum(init=0, &blk) |
|||
if blk |
|||
inject(init){|s, n| s + blk.call(n)} |
|||
else |
|||
inject(init){|s, n| s + n} |
|||
end |
|||
end |
|||
end |
|||
ary = [1,2,3,4,5] |
|||
p ary.sum #=> 15 |
|||
p ary.sum(''){|n| (-n).to_s} #=> "-1-2-3-4-5" |
|||
p (ary.sum do |n| n * n end) #=> 55</syntaxhighlight> |
|||
:Splat operator: |
|||
::You can turn an Array into an argument list with * (or splat) operator. |
|||
::<syntaxhighlight lang="ruby">def foo(a,b,c) p [a,b,c] end |
|||
args = [1,2,3] |
|||
foo *args #=> [1, 2, 3] |
|||
args = [1,2] |
|||
foo(0,*args) #=> [0, 1, 2]</syntaxhighlight> |
|||
:Syntax sugar: |
|||
::In Ruby, many operators are actually method calls. |
|||
::<syntaxhighlight lang="ruby"># return value substance |
|||
i = 3 |
|||
p 1 + i #=> 4 1.+(i) |
|||
p i < 5 #=> true i.<(5) |
|||
p 2 ** i #=> 8 2.**(i) |
|||
p -i #=> -3 i.-@() |
|||
a = [1,2,3] |
|||
p a[0] #=> 1 a.[](0) |
|||
a[2] = "0" # a.[]=(2,"0") |
|||
p a << 5 #=> [1, 2, "0", 5] a.<<(5) |
|||
p a & [4,2] #=> [2] a.&([4,2]) |
|||
p "abcde"[1..3] #=> "bcd" "abcde".[](1..3) |
|||
p "%2d %4s" % [1,"xyz"] #=> " 1 xyz" "%2d %4s".%([1,"xyz"])</syntaxhighlight> |
|||
::Method call which was displayed in the comment is usable actually. |
|||
=={{header|Rust}}== |
|||
<syntaxhighlight lang="rust">fn main() { |
|||
// Rust has a lot of neat things you can do with functions: let's go over the basics first |
|||
fn no_args() {} |
|||
// Run function with no arguments |
|||
no_args(); |
|||
// Calling a function with fixed number of arguments. |
|||
// adds_one takes a 32-bit signed integer and returns a 32-bit signed integer |
|||
fn adds_one(num: i32) -> i32 { |
|||
// the final expression is used as the return value, though `return` may be used for early returns |
|||
num + 1 |
|||
} |
|||
adds_one(1); |
|||
// Optional arguments |
|||
// The language itself does not support optional arguments, however, you can take advantage of |
|||
// Rust's algebraic types for this purpose |
|||
fn prints_argument(maybe: Option<i32>) { |
|||
match maybe { |
|||
Some(num) => println!("{}", num), |
|||
None => println!("No value given"), |
|||
}; |
|||
} |
|||
prints_argument(Some(3)); |
|||
prints_argument(None); |
|||
// You could make this a bit more ergonomic by using Rust's Into trait |
|||
fn prints_argument_into<I>(maybe: I) |
|||
where I: Into<Option<i32>> |
|||
{ |
|||
match maybe.into() { |
|||
Some(num) => println!("{}", num), |
|||
None => println!("No value given"), |
|||
}; |
|||
} |
|||
prints_argument_into(3); |
|||
prints_argument_into(None); |
|||
// Rust does not support functions with variable numbers of arguments. Macros fill this niche |
|||
// (println! as used above is a macro for example) |
|||
// Rust does not support named arguments |
|||
// We used the no_args function above in a no-statement context |
|||
// Using a function in an expression context |
|||
adds_one(1) + adds_one(5); // evaluates to eight |
|||
// Obtain the return value of a function. |
|||
let two = adds_one(1); |
|||
// In Rust there are no real built-in functions (save compiler intrinsics but these must be |
|||
// manually imported) |
|||
// In rust there are no such thing as subroutines |
|||
// In Rust, there are three ways to pass an object to a function each of which have very important |
|||
// distinctions when it comes to Rust's ownership model and move semantics. We may pass by |
|||
// value, by immutable reference, or mutable reference. |
|||
let mut v = vec![1, 2, 3, 4, 5, 6]; |
|||
// By mutable reference |
|||
fn add_one_to_first_element(vector: &mut Vec<i32>) { |
|||
vector[0] += 1; |
|||
} |
|||
add_one_to_first_element(&mut v); |
|||
// By immutable reference |
|||
fn print_first_element(vector: &Vec<i32>) { |
|||
println!("{}", vector[0]); |
|||
} |
|||
print_first_element(&v); |
|||
// By value |
|||
fn consume_vector(vector: Vec<i32>) { |
|||
// We can do whatever we want to vector here |
|||
} |
|||
consume_vector(v); |
|||
// Due to Rust's move semantics, v is now inaccessible because it was moved into consume_vector |
|||
// and was then dropped when it went out of scope |
|||
// Partial application is not possible in rust without wrapping the function in another |
|||
// function/closure e.g.: |
|||
fn average(x: f64, y: f64) -> f64 { |
|||
(x + y) / 2.0 |
|||
} |
|||
let average_with_four = |y| average(4.0, y); |
|||
average_with_four(2.0); |
|||
}</syntaxhighlight> |
|||
=={{header|Scala}}== |
|||
{{libheader|Scala}} |
|||
<syntaxhighlight lang="scala">def ??? = throw new NotImplementedError // placeholder for implementation of hypothetical methods |
|||
def myFunction0() = ??? |
|||
myFunction0() // function invoked with empty parameter list |
|||
myFunction0 // function invoked with empty parameter list omitted |
|||
def myFunction = ??? |
|||
myFunction // function invoked with no arguments or empty arg list |
|||
/* myFunction() */ // error: does not take parameters |
|||
def myFunction1(x: String) = ??? |
|||
myFunction1("foobar") // function invoked with single argument |
|||
myFunction1 { "foobar" } // function invoked with single argument provided by a block |
|||
// (a block of code within {}'s' evaluates to the result of its last expression) |
|||
def myFunction2(first: Int, second: String) = ??? |
|||
val b = "foobar" |
|||
myFunction2(6, b) // function with two arguments |
|||
def multipleArgLists(first: Int)(second: Int, third: String) = ??? |
|||
multipleArgLists(42)(17, "foobar") // function with three arguments in two argument lists |
|||
def myOptionalParam(required: Int, optional: Int = 42) = ??? |
|||
myOptionalParam(1) // function with optional param |
|||
myOptionalParam(1, 2) // function with optional param provided |
|||
def allParamsOptional(firstOpt: Int = 42, secondOpt: String = "foobar") = ??? |
|||
allParamsOptional() // function with all optional args |
|||
/* allParamsOptional */ // error: missing arguments for method allParamsOptional; |
|||
// follow with `_' if you want to treat it as a partially applied function |
|||
def sum[Int](values: Int*) = values.foldLeft(0)((a, b) => a + b) |
|||
sum(1, 2, 3) // function accepting variable arguments as literal |
|||
val values = List(1, 2, 3) |
|||
sum(values: _*) // function acception variable arguments from collection |
|||
sum() // function accepting empty variable arguments |
|||
def mult(firstValue: Int, otherValues: Int*) = otherValues.foldLeft(firstValue)((a, b) => a * b) |
|||
mult(1, 2, 3) // function with non-empty variable arguments |
|||
myOptionalParam(required = 1) // function called with named arguments (all functions have named arguments) |
|||
myFunction2(second = "foo", first = 1) // function with re-ordered named arguments |
|||
mult(firstValue = 1, otherValues = 2, 3) // function with named variable argument as literal |
|||
val otherValues = Seq(2, 3) |
|||
mult(1, otherValues = otherValues: _*) // function with named variable argument from collection |
|||
val result = myFunction0() // function called in an expression context |
|||
myFunction0() // function called in statement context |
|||
/* myOptionalParam(optional = 1, 2) */ // error: positional after named argument. |
|||
def transform[In, Out](initial: In)(transformation: In => Out) = transformation(initial) |
|||
val result = transform(42)(x => x * x) // function in first-class context within an expression |
|||
def divide(top: Double, bottom: Double) = top / bottom |
|||
val div = (divide _) // partial application -- defer application of entire arg list |
|||
val halve = divide(_: Double, 2) // partial application -- defer application of some arguments |
|||
class Foo(var value: Int) |
|||
def incFoo(foo: Foo) = foo.value += 1 // function showing AnyRef's are passed by reference |
|||
/* def incInt(i: Int) = i += 1 */ // error: += is not a member of Int |
|||
// (All arguments are passed by reference, but reassignment |
|||
// or setter must be defined on a type or a field |
|||
// (respectively) in order to modify its value.) |
|||
// No distinction between built-in functions and user-defined functions |
|||
// No distinction between subroutines and functions</syntaxhighlight> |
|||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
* Seed7 provides two kinds of subroutines: ''proc'', which has no return value, and ''func'', which has a return value. The return value of a ''func'' must be used by the caller (e.g. assigned to a variable). If you don't want do deal with the return value, use a ''proc'' instead. |
* Seed7 provides two kinds of subroutines: ''proc'', which has no return value, and ''func'', which has a return value. The return value of a ''func'' must be used by the caller (e.g. assigned to a variable). If you don't want do deal with the return value, use a ''proc'' instead. |
||
Line 1,327: | Line 5,945: | ||
* All parameters are positional. |
* All parameters are positional. |
||
* There are no differences between between calling built-in vs. user defined functions.< |
* There are no differences between between calling built-in vs. user defined functions.<syntaxhighlight lang="seed7">env := environment; # Call a function that requires no arguments. |
||
env := environment(); # Alternative possibility to call of a function with no arguments. |
env := environment(); # Alternative possibility to call of a function with no arguments. |
||
cmp := compare(i, j); # Call a function with a fixed number of arguments.</ |
cmp := compare(i, j); # Call a function with a fixed number of arguments.</syntaxhighlight> |
||
* There are no optional arguments, but a similar effect can be achieved with overloading.< |
* There are no optional arguments, but a similar effect can be achieved with overloading.<syntaxhighlight lang="seed7">write(aFile, "asdf"); # Variant of write with a parameter to specify a file. |
||
write("asdf"); # Variant of write which writes to the file OUT.</ |
write("asdf"); # Variant of write which writes to the file OUT.</syntaxhighlight> |
||
* Seed7 does not support functions with a variable number of arguments. But a function argument can be an array with as many values as you want:< |
* Seed7 does not support functions with a variable number of arguments. But a function argument can be an array with as many values as you want:<syntaxhighlight lang="seed7">const func integer: sum (in array integer: intElems) is func |
||
result |
result |
||
var integer: sum is 0; |
var integer: sum is 0; |
||
Line 1,346: | Line 5,964: | ||
s := sum([] (1, 2, 3)); # Use an aggregate to generate an array. |
s := sum([] (1, 2, 3)); # Use an aggregate to generate an array. |
||
t := sum([] (2, 3, 5, 7));</ |
t := sum([] (2, 3, 5, 7));</syntaxhighlight> |
||
* Concatenation operators can be used to concatenate arguments. This solution is used to provide the write function:< |
* Concatenation operators can be used to concatenate arguments. This solution is used to provide the write function:<syntaxhighlight lang="seed7">write("Nr: " <& num); # Use operators to concatenate arguments.</syntaxhighlight> |
||
* The procedure ignore can be used to ignore a return value.< |
* The procedure ignore can be used to ignore a return value.<syntaxhighlight lang="seed7">ignore(getln(IN)); # Using a function in statement context (ignore the result).</syntaxhighlight> |
||
* Call-by-name parameters use a function in first-class context. The function [http://seed7.sourceforge.net/examples/map.htm doMap] from the examples section of the Seed7 homepage uses a given expression to modify the elements of an array:<syntaxhighlight lang="seed7">seq := doMap([](1, 2, 4, 6, 10, 12, 16), x, succ(x));</syntaxhighlight> |
|||
=={{header|SenseTalk}}== |
|||
* If no variable is specified, `put` prints the variable to stdout |
|||
<syntaxhighlight lang="sensetalk">put zeroArgsFn() |
|||
// Function calls can also be made using the following syntax: |
|||
put the zeroArgsFn |
|||
function zeroArgsFn |
|||
put "This function was run with zero arguments." |
|||
return "Return value from zero argument function" |
|||
end zeroArgsFn</syntaxhighlight> |
|||
* Running a function requires a keyword such as `put; if no variable is return, put into e.g. _ |
|||
<syntaxhighlight lang="sensetalk">put TwoArgFn("variable", (3, 4)) into _ |
|||
// Alternatively, the function can be called like so: |
|||
put the TwoArgFn of "variable", (3, 4) |
|||
// The parameter list is flexible, allowing any amount of variable to be passed in. |
|||
// These can be accessed with the keyword `the parameterList` |
|||
// The specified parameters only limits to named parameters |
|||
get TwoArgFn("variable", (3, 4), "hello") |
|||
get the TwoArgFn of "variable", (3, 4), "hello" |
|||
function TwoArgFn arg1, arg2 |
|||
put "2 argument function: arg1 = " & arg1 & "; arg2 = " & arg2 |
|||
put "Parameters = " & the parameterList |
|||
end TwoArgFn</syntaxhighlight> |
|||
* A parameter is set to "" if nothing is specified |
|||
<syntaxhighlight lang="sensetalk">get ThreeArgFn("variable", (3, 4)) |
|||
function ThreeArgFn arg1, arg2, arg3 |
|||
put "3 argument function: arg1 = " & arg1 & "; arg2 = " & arg2 & "; arg3 = " & arg3 |
|||
end ThreeArgFn</syntaxhighlight> |
|||
* Using this, default parameter values can be set up if a check if done at the start of the function |
|||
<syntaxhighlight lang="sensetalk">get OneArgFn() -- arg1 is 5 |
|||
get OneArgFn(10) -- arg1 is now 10 |
|||
function OneArgFn arg1 |
|||
if arg1 is "" |
|||
set arg1 to 5 |
|||
end if |
|||
put "One argument function; arg1 = " & arg1 |
|||
end OneArgFn</syntaxhighlight> |
|||
* All variables are, by default, passed by value |
|||
* If the argument prefixed by 'container', the variable is passed by reference |
|||
<syntaxhighlight lang="sensetalk">put 3 into a |
|||
get AddOne(a) |
|||
put "Value of a = " & a |
|||
// Value of a = 3 |
|||
put 5 into b |
|||
get AddOne(container b) |
|||
put "Value of b = " & b |
|||
// Value of b = 6 |
|||
function AddOne n |
|||
add 1 to n |
|||
end AddOne</syntaxhighlight> |
|||
SenseTalk also distinguishes between functions and subroutines, which it calls handlers: |
|||
<syntaxhighlight lang="sensetalk">CustomHandler 1, 2, 3 |
|||
// Prints: 1 - 2 - 3 |
|||
to handle CustomHandler arg1, arg2, arg3 |
|||
put arg1 && "-" && arg2 && "-" && arg3 |
|||
end CustomHandler</syntaxhighlight> |
|||
Subroutines can be called as a command, without storing the output |
|||
<syntaxhighlight lang="sensetalk"> |
|||
MyCommand 1, "variable", (4, 5, 6) |
|||
to MyCommand args |
|||
... |
|||
end MyCommand |
|||
</syntaxhighlight> |
|||
Functions/subroutines can also be defined with the to, on or function keywords: |
|||
<syntaxhighlight lang="sensetalk">to MyFn args |
|||
... |
|||
end MyFn |
|||
function MyFn args |
|||
... |
|||
end args |
|||
on MyFn args |
|||
... |
|||
end args |
|||
</syntaxhighlight> |
|||
=={{header|Sidef}}== |
|||
All functions in Sidef are first-class closures |
|||
<syntaxhighlight lang="ruby">foo(); # without arguments |
|||
foo(1, 2); # with two arguments |
|||
foo(args...); # with a variable number of arguments |
|||
foo(name: 'Bar', age: 42); # with named arguments |
|||
var f = foo; # store the function foo inside 'f' |
|||
var result = f(); # obtain the return value of a function |
|||
var arr = [1,2,3]; |
|||
foo(arr); # the arguments are passed by object-reference</syntaxhighlight> |
|||
Partial application is possible by using a curry function: |
|||
<syntaxhighlight lang="ruby">func curry(f, *args1) { |
|||
func (*args2) { |
|||
f(args1..., args2...); |
|||
} |
|||
} |
|||
func add(a, b) { |
|||
a + b |
|||
} |
|||
var adder = curry(add, 1); |
|||
say adder(3); #=>4</syntaxhighlight> |
|||
=={{header|Slope}}== |
|||
Define and call a procedure: |
|||
<syntaxhighlight lang="slope">(define hello-world (lambda () (display "Hello, world!\n")) |
|||
(hello-world)</syntaxhighlight> |
|||
Call an anonymous procedure/lambda: |
|||
<syntaxhighlight lang="slope">((lambda () (display "Hello, world!\n")))</syntaxhighlight> |
|||
Define and call a procedure with arguments: |
|||
<syntaxhighlight lang="slope">(define hello (lambda (name) (display "Hello, " name "!\n"))) |
|||
(hello "Rosetta Code")</syntaxhighlight> |
|||
Define and call an anonymous procedure with arguments: |
|||
<syntaxhighlight lang="slope">((lambda (name) (display "Hello, " name "!\n")) "Rosetta Code")</syntaxhighlight> |
|||
Defining a procedure that takes option arguments and defining one |
|||
that takes a variable number of arguments works the same. `...` |
|||
as a paramater represents a list of all arguments passed in from that |
|||
paramater forward. Here is an example usage for variable arguments: |
|||
<syntaxhighlight lang="slope">((lambda (op ...) |
|||
(if (null? ...) |
|||
(! "At least one argument is required") |
|||
(apply op ...))) |
|||
* 1 2 3 4)</syntaxhighlight> |
|||
Here is an example with an optional value: |
|||
<syntaxhighlight lang="slope">((lambda (first ...) |
|||
(define last (if (null? ...) "" (append " " (car ...)))) |
|||
(display "Hello " first last "\n")) "John" "Kimball")</syntaxhighlight> |
|||
Partial application varies by procedure. Some built-ins use partial application |
|||
(such as `or`). Macros created with `macro` do not evaluate any arguments and the |
|||
macro definition is responsible for evaluating what it needs to. But macros likely |
|||
fall into a different category than the scope of this task. |
|||
=={{header|SmallBASIC}}== |
|||
<syntaxhighlight lang="basic"> |
|||
func F1() |
|||
return 1 |
|||
end |
|||
func F2(a) |
|||
return a + 1 |
|||
end |
|||
func F3(a, b) |
|||
return a + b |
|||
end |
|||
func F4(byref a) |
|||
a = 5 |
|||
return a + 1 |
|||
end |
|||
sub S1(a, b) |
|||
print a, b |
|||
end |
|||
sub S2(byref a) |
|||
a = 5 |
|||
end |
|||
var1 = 1 |
|||
var2 = 2 |
|||
' Functions return a result and return-value must be assigned to a variable |
|||
result = F1() |
|||
result = F2(var1) |
|||
result = F3(var1, var2) |
|||
' Parameters are passed by reference if byref is used in function definition |
|||
result = F4(var1) ' result = 6 and var1 = 5 |
|||
' Subroutines can't return a result |
|||
S1(var1, var2) |
|||
' Parameters are passed by reference if byref is used in sub definition. |
|||
' This can be used to return a result indirectly |
|||
S2(var1) ' var1 = 5 |
|||
' Functions and subroutines can take expressions as parameter |
|||
result = F2(1 + 2) |
|||
</syntaxhighlight> |
|||
* Call-by-name parameters use a function in first-class context. The function [http://seed7.sourceforge.net/examples/map.htm doMap] from the examples section of the Seed7 homepage uses a given expression to modify the elements of an array:<lang seed7>seq := doMap([](1, 2, 4, 6, 10, 12, 16), x, succ(x));</lang> |
|||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
Where f is a closure and arguments is an array of values for f to operate on. |
Where f is a closure and arguments is an array of values for f to operate on. |
||
<lang |
<syntaxhighlight lang="smalltalk">f valueWithArguments: arguments.</syntaxhighlight> |
||
=={{header|SSEM}}== |
|||
Assuming the subroutine has been set up in accordance with the Wheeler jump technique as described in the SSEM [[Function definition]] entry, calling it requires simply loading the return address into the accumulator and jumping out to the subroutine. Parameters must be passed using "global variables", i.e. storage locations; results may be passed the same way, although it is also possible to pass a return value in the accumulator. |
|||
This code fragment, beginning (for the sake of argument) at address 10, performs a Wheeler jump to a subroutine beginning at address 20. The return address is coded in negative (two's complement) form because the SSEM negates values in the process of loading them into the accumulator. As always on the SSEM, jump targets are one less than the actual intended target: this is because the CI ("Current Instruction") register is incremented after an instruction has been executed rather than before. |
|||
<syntaxhighlight lang="ssem">00110000000000100000000000000000 10. -12 to c |
|||
10110000000000000000000000000000 11. 13 to CI |
|||
11001111111111111111111111111111 12. -13 |
|||
11001000000000000000000000000000 13. 19</syntaxhighlight> |
|||
=={{header|Swift}}== |
|||
<syntaxhighlight lang="swift">// call a function with no args |
|||
noArgs() |
|||
// call a function with one arg with no external name |
|||
oneArgUnnamed(1) |
|||
// call a function with one arg with external name |
|||
oneArgNamed(arg: 1) |
|||
// call a function with two args with no external names |
|||
twoArgsUnnamed(1, 2) |
|||
// call a function with two args and external names |
|||
twoArgsNamed(arg1: 1, arg2: 2) |
|||
// call a function with an optional arg |
|||
// with arg |
|||
optionalArguments(arg: 1) |
|||
// without |
|||
optionalArguments() // defaults to 0 |
|||
// function that takes another function as arg |
|||
funcArg(noArgs) |
|||
// variadic function |
|||
variadic(opts: "foo", "bar") |
|||
// getting a return value |
|||
let foo = returnString() |
|||
// getting a bunch of return values |
|||
let (foo, bar, baz) = returnSomeValues() |
|||
// getting a bunch of return values, discarding second returned value |
|||
let (foo, _, baz) = returnSomeValues()</syntaxhighlight> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">aCallToACommandWithNoArguments |
||
aCallToACommandWithOne argument |
aCallToACommandWithOne argument |
||
aCallToACommandWith arbitrarily many arguments |
aCallToACommandWith arbitrarily many arguments |
||
Line 1,365: | Line 6,230: | ||
aCallToACommandWith -oneNamed argument -andAnother namedArgument |
aCallToACommandWith -oneNamed argument -andAnother namedArgument |
||
aCallToACommandWith theNameOfAnotherCommand |
aCallToACommandWith theNameOfAnotherCommand |
||
aCallToOneCommand [withTheResultOfAnother]</ |
aCallToOneCommand [withTheResultOfAnother]</syntaxhighlight> |
||
Tcl does differentiate between functions and other types of commands in expressions: |
Tcl does differentiate between functions and other types of commands in expressions: |
||
< |
<syntaxhighlight lang="tcl">expr {func() + [cmd]} |
||
expr {func(1,2,3} + [cmd a b c]}</ |
expr {func(1,2,3} + [cmd a b c]}</syntaxhighlight> |
||
However, there are no deep differences between the two: functions are translated into commands that are called in a particular namespace (thus <tt>foo()</tt> becomes <tt>tcl::mathfunc::foo</tt>). |
However, there are no deep differences between the two: functions are translated into commands that are called in a particular namespace (thus <tt>foo()</tt> becomes <tt>tcl::mathfunc::foo</tt>). |
||
There are no differences in usage between built-in commands and user-defined ones, and parameters are passed to commands by value conceptually (and read-only reference in the implementation). |
There are no differences in usage between built-in commands and user-defined ones, and parameters are passed to commands by value conceptually (and read-only reference in the implementation). |
||
=={{header|True BASIC}}== |
|||
{{trans|FreeBASIC}} |
|||
<syntaxhighlight lang="qbasic">FUNCTION Copialo$ (txt$, siNo, final$) |
|||
FOR cont = 1 TO ROUND(siNo) |
|||
LET nuevaCadena$ = nuevaCadena$ & txt$ |
|||
NEXT cont |
|||
LET Copialo$ = LTRIM$(RTRIM$(nuevaCadena$)) & final$ |
|||
END FUNCTION |
|||
SUB Saludo |
|||
PRINT "Hola mundo!" |
|||
END SUB |
|||
SUB testCadenas (txt$) |
|||
FOR cont = 1 TO ROUND(LEN(txt$)) |
|||
PRINT (txt$)[cont:cont+1-1]; ""; |
|||
NEXT cont |
|||
END SUB |
|||
SUB testNumeros (a, b, c) |
|||
PRINT a, b, c |
|||
END SUB |
|||
CALL Saludo |
|||
PRINT Copialo$("Saludos ", 6, "") |
|||
PRINT Copialo$("Saludos ", 3, "! !") |
|||
PRINT |
|||
CALL testNumeros(1, 2, 3) |
|||
CALL testNumeros(1, 2, 0) |
|||
PRINT |
|||
CALL testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'") |
|||
END</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Igual que la entrada de FreeBASIC. |
|||
</pre> |
|||
=={{header|UNIX Shell}}== |
=={{header|UNIX Shell}}== |
||
In the shell, there are no argument specifications for functions. Functions obtain their arguments using the positional parameter facilities and functions are simply called by name followed by any arguments that are to be passed: |
In the shell, there are no argument specifications for functions. Functions obtain their arguments using the positional parameter facilities and functions are simply called by name followed by any arguments that are to be passed: |
||
< |
<syntaxhighlight lang="sh">sayhello # Call a function in statement context with no arguments |
||
multiply 3 4 # Call a function in statement context with two arguments</ |
multiply 3 4 # Call a function in statement context with two arguments</syntaxhighlight> |
||
The shell does not support the use of named parameters. There is no lookahead in the shell, so functions cannot be called until their definition has been run. |
The shell does not support the use of named parameters. There is no lookahead in the shell, so functions cannot be called until their definition has been run. |
||
=={{header|VBA}}== |
|||
<syntaxhighlight lang="vb">'definitions/declarations |
|||
'Calling a function that requires no arguments |
|||
Function no_arguments() As String |
|||
no_arguments = "ok" |
|||
End Function |
|||
'Calling a function with a fixed number of arguments |
|||
Function fixed_number(argument1 As Integer, argument2 As Integer) |
|||
fixed_number = argument1 + argument2 |
|||
End Function |
|||
'Calling a function with optional arguments |
|||
Function optional_parameter(Optional argument1 = 1) As Integer |
|||
'Optional parameters come at the end of the parameter list |
|||
optional_parameter = argument1 |
|||
End Function |
|||
'Calling a function with a variable number of arguments |
|||
Function variable_number(arguments As Variant) As Integer |
|||
variable_number = UBound(arguments) |
|||
End Function |
|||
'Calling a function with named arguments |
|||
Function named_arguments(argument1 As Integer, argument2 As Integer) As Integer |
|||
named_arguments = argument1 + argument2 |
|||
End Function |
|||
'Using a function in statement context |
|||
Function statement() As String |
|||
Debug.Print "function called as statement" |
|||
statement = "ok" |
|||
End Function |
|||
'Using a function in first-class context within an expression |
|||
'see call the functions |
|||
'Obtaining the return value of a function |
|||
Function return_value() As String |
|||
return_value = "ok" |
|||
End Function |
|||
'Distinguishing built-in functions and user-defined functions |
|||
'There is no way to distinguish built-in function and user-defined functions |
|||
'Distinguishing subroutines And functions |
|||
'subroutines are declared with the reserved word "sub" and have no return value |
|||
Sub foo() |
|||
Debug.Print "subroutine", |
|||
End Sub |
|||
'functions are declared with the reserved word "function" and can have a return value |
|||
Function bar() As String |
|||
bar = "function" |
|||
End Function |
|||
'Stating whether arguments are passed by value or by reference |
|||
Function passed_by_value(ByVal s As String) As String |
|||
s = "written over" |
|||
passed_by_value = "passed by value" |
|||
End Function |
|||
'By default, parameters in VBA are by reference |
|||
Function passed_by_reference(ByRef s As String) As String |
|||
s = "written over" |
|||
passed_by_reference = "passed by reference" |
|||
End Function |
|||
'Is partial application possible and how |
|||
'I don't know |
|||
'calling a subroutine with arguments does not require parentheses |
|||
Sub no_parentheses(myargument As String) |
|||
Debug.Print myargument, |
|||
End Sub |
|||
'call the functions |
|||
Public Sub calling_a_function() |
|||
'Calling a function that requires no arguments |
|||
Debug.Print "no arguments", , no_arguments |
|||
Debug.Print "no arguments", , no_arguments() |
|||
'Parentheses are not required |
|||
'Calling a function with a fixed number of arguments |
|||
Debug.Print "fixed_number", , fixed_number(1, 1) |
|||
'Calling a function with optional arguments |
|||
Debug.Print "optional parameter", optional_parameter |
|||
Debug.Print "optional parameter", optional_parameter(2) |
|||
'Calling a function with a variable number of arguments |
|||
Debug.Print "variable number", variable_number([{"hello", "there"}]) |
|||
'The variable number of arguments have to be passed as an array |
|||
'Calling a function with named arguments |
|||
Debug.Print "named arguments", named_arguments(argument2:=1, argument1:=1) |
|||
'Using a function in statement context |
|||
statement |
|||
'Using a function in first-class context within an expression |
|||
s = "no_arguments" |
|||
Debug.Print "first-class context", Application.Run(s) |
|||
'A function name can be passed as argument in a string |
|||
'Obtaining the return value of a function |
|||
returnvalue = return_value |
|||
Debug.Print "obtained return value", returnvalue |
|||
'Distinguishing built-in functions and user-defined functions |
|||
'Distinguishing subroutines And functions |
|||
foo |
|||
Debug.Print , bar |
|||
'Stating whether arguments are passed by value or by reference |
|||
Dim t As String |
|||
t = "unaltered" |
|||
Debug.Print passed_by_value(t), t |
|||
Debug.Print passed_by_reference(t), t |
|||
'Is partial application possible and how |
|||
'I don 't know |
|||
'calling a subroutine with arguments does not require parentheses |
|||
no_parentheses "calling a subroutine" |
|||
Debug.Print "does not require parentheses" |
|||
Call no_parentheses("deprecated use") |
|||
Debug.Print "of parentheses" |
|||
End Sub |
|||
</syntaxhighlight>{{out}} |
|||
<pre>no arguments ok |
|||
no arguments ok |
|||
fixed_number 2 |
|||
optional parameter 1 |
|||
optional parameter 2 |
|||
variable number 2 |
|||
named arguments 2 |
|||
function called as statement |
|||
first-class context ok |
|||
obtained return value ok |
|||
subroutine function |
|||
passed by value unaltered |
|||
passed by reference written over |
|||
calling a subroutine does not require parentheses |
|||
deprecated use of parentheses</pre> |
|||
=={{header|WDTE}}== |
|||
<syntaxhighlight lang="wdte">let noargs => + 2 5; |
|||
noargs -- print; |
|||
let fixedargs a b => + a b; |
|||
fixedargs 3 5 -- print; |
|||
let m => import 'math'; |
|||
m.cos 3 -- print; |
|||
# WDTE only has expressions, not statements, so statement vs. |
|||
# first-class context doesn't make sense. |
|||
# Arguments in WDTE are technically passed by reference, in a way, but |
|||
# because it's a functional language and everything's immutable |
|||
# there's no real usability difference from that. |
|||
# Partial application is possible. For example, the following |
|||
# evaluates `+ 3` and then passes 7 to the resulting partially applied |
|||
# function. |
|||
(+ 3) 7 -- print;</syntaxhighlight> |
|||
=={{header|WebAssembly}}== |
|||
<syntaxhighlight lang="webassembly">(func $main (export "_start") |
|||
(local $result i32) |
|||
;;Call a function with no arguments |
|||
call $noargfunc |
|||
;;Multiply two numbers and store the result, flat syntax |
|||
i32.const 12 |
|||
i32.const 3 |
|||
call $multipy |
|||
set_local $result |
|||
;;Multiply two numbers and store the result, indented syntax |
|||
(set_local $result |
|||
(call $multipy |
|||
(i32.const 12) |
|||
(i32.const 3) |
|||
) |
|||
) |
|||
;;Add two numbers in linear memory (similar to using pointers) |
|||
(i32.store (i32.const 0) (i32.const 5)) |
|||
(i32.store (i32.const 4) (i32.const 7)) |
|||
(call $addinmemory |
|||
(i32.const 0) |
|||
(i32.const 4) |
|||
(i32.const 8) |
|||
) |
|||
)</syntaxhighlight> |
|||
=={{header|Wren}}== |
|||
Wren distinguishes between functions and methods. |
|||
The former are first-class standalone objects which cannot be overloaded whereas the latter are always members of a class and can be overloaded by ''arity'' (i.e. the number of arguments they require). As Wren is dynamically typed and doesn't support type annotations, methods cannot be overloaded by parameter type. Methods can either be instance or static members of their class. |
|||
As well as 'ordinary' methods which always have a (possibly empty) parameter list, Wren also has the following types of methods: |
|||
1. 'constructors' which always have a parameter list and are really a pair of methods - a static method which creates a new instance of the class and then invokes an initializer on that instance. |
|||
2. 'getters' which leave off the parameter list. |
|||
3. 'setters' which have '=' after the name followed by a parameter list with just a single parameter. |
|||
4. 'operators' which, if they're infix operators, always have a parameter list with a single parameter. However, if they're prefix operators, they have no parameter list. |
|||
Wren does not support optional arguments, a variable number of arguments or named arguments though these can be respectively simulated by overloading, passing lists or passing maps. |
|||
Arguments are always passed by value though, if they're mutable reference types, it's the reference which gets copied so the function or method can mutate the object itself. |
|||
There are no built-in functions but all built-in classes have methods. Unless you know what they are, there is no way to distinguish between them and methods of user-defined classes. |
|||
The only way to distinguish between sub-routines and functions it to check whether they return a concrete value. The former always return null by default. |
|||
Partial function application is not supported ''per se'' but can be simulated as in the task of that name. |
|||
Here are some examples: |
|||
<syntaxhighlight lang="wren">var f1 = Fn.new { System.print("Function 'f1' with no arguments called.") } |
|||
var f2 = Fn.new { |a, b| |
|||
System.print("Function 'f2' with 2 arguments called and passed %(a) & %(b).") |
|||
} |
|||
var f3 = Fn.new { 42 } // function which returns a concrete value |
|||
f1.call() // statement context |
|||
f2.call(2, 3) // ditto |
|||
var v1 = 8 + f3.call() // calling function within an expression |
|||
var v2 = f3.call() // obtaining return value |
|||
System.print([v1, v2]) // print last two results as a list |
|||
class MyClass { |
|||
static m() { System.print("Static method 'm' called.") } |
|||
construct new(x) { _x = x } // stores 'x' in a field |
|||
x { _x } // gets the field |
|||
x=(y) { _x = y } // sets the field to 'y' |
|||
- { MyClass.new(-_x) } // prefix operator |
|||
+(o) { MyClass.new(_x + o.x) } // infix operator |
|||
toString { _x.toString } // instance method |
|||
} |
|||
MyClass.m() // call static method 'm' |
|||
var mc1 = MyClass.new(40) // construct 'mc1' |
|||
var mc2 = MyClass.new(8) // construct 'mc2' |
|||
System.print(mc1.x) // print mc1's field using getter |
|||
mc1.x = 42 // change mc1's field using setter |
|||
System.print(-mc1.x) // invoke prefix operator - |
|||
System.print(mc1 + mc2) // invoke infix operator +</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Function 'f1' with no arguments called. |
|||
Function 'f2' with 2 arguments called and passed 2 & 3. |
|||
[50, 42] |
|||
Static method 'm' called. |
|||
40 |
|||
-42 |
|||
50 |
|||
</pre> |
|||
=={{header|XLISP}}== |
|||
<syntaxhighlight lang="lisp">; call a function (procedure) with no arguments: |
|||
(foo) |
|||
; call a function (procedure) with arguments: |
|||
(foo bar baz) |
|||
; the first symbol after "(" is the name of the function |
|||
; the other symbols are the arguments |
|||
; call a function on a list of arguments formed at run time: |
|||
(apply foo bar) |
|||
; In a REPL, the return value will be printed. |
|||
; In other contexts, it can be fed as argument into a further function: |
|||
(foo (bar baz)) |
|||
; this calls bar on the argument baz and then calls foo on the return value |
|||
; or it can simply be discarded |
|||
(foo bar) |
|||
; nothing is done with the return value</syntaxhighlight> |
|||
=={{header|XSLT}}== |
|||
<syntaxhighlight lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
|||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> |
|||
<xsl:output method="xml" indent="yes"/> |
|||
<xsl:template match="/"> |
|||
<demo> |
|||
<!-- |
|||
XSLT 1.0 actually defines two function-like constructs that |
|||
are used variously depending on the context. |
|||
--> |
|||
<xsl:call-template name="xpath-function-demos"/> |
|||
<xsl:call-template name="xslt-template-demos"/> |
|||
</demo> |
|||
</xsl:template> |
|||
<xsl:template name="xpath-function-demos"> |
|||
<!-- |
|||
A 'function' in XSLT 1.0 is a function that can be called from |
|||
an XPath 1.0 expression (such as from "select" or "test" |
|||
attribute of several XSLT elements). The following demos apply |
|||
to these functions. |
|||
--> |
|||
<!-- Calling function that requires no arguments --> |
|||
<!-- false() always returns a boolean false value --> |
|||
<line>This test is <xsl:if test="false()">NOT</xsl:if> OK.</line> |
|||
<!-- Calling a function with a fixed number of arguments --> |
|||
<!-- not() takes exactly 1 argument. starts-with() takes exactly 2 arguments. --> |
|||
<line>'haystack' does <xsl:if test="not(starts-with('haystack', 'hay'))">NOT</xsl:if> start with 'hay'.</line> |
|||
<!-- Calling a function with optional arguments --> |
|||
<!-- If the third argument of substring() is omitted, the length of the string is assumed. --> |
|||
<line>'<xsl:value-of select="substring('haystack', 1, 3)"/>' = 'hay'</line> |
|||
<line>'<xsl:value-of select="substring('haystack', 4)"/>' = 'stack'</line> |
|||
<!-- Calling a function with a variable number of arguments --> |
|||
<!-- concat() accepts two or more arguments. --> |
|||
<line>'<xsl:value-of select="concat('abcd', 'efgh')"/>' = 'abcdefgh'</line> |
|||
<line>'<xsl:value-of select="concat('ij', 'kl', 'mn', 'op')"/>' = 'ijklmnop'</line> |
|||
<!-- |
|||
Aggregate functions such as sum() and count() accept nodesets. |
|||
This isn't quite the same as varargs but are probably worth |
|||
mentioning. |
|||
--> |
|||
<line>The number of root elements in the input document is <xsl:value-of select="count(/*)"/> (should be 1).</line> |
|||
<!-- Calling a function with named arguments --> |
|||
<!-- XPath 1.0 uses only positional parameters. --> |
|||
<!-- Using a function in statement context --> |
|||
<!-- |
|||
In general, XPath 1.0 functions have no side effects, so calling |
|||
them as statements is useless. While implementations often allow |
|||
writing extensions in imperative languages, the semantics of |
|||
calling a function with side effects are, at the very least, |
|||
implementation-dependent. |
|||
--> |
|||
<!-- Using a function in first-class context within an expression --> |
|||
<!-- Functions are not natively first-class values in XPath 1.0. --> |
|||
<!-- Obtaining the return value of a function --> |
|||
<!-- |
|||
The return value of the function is handled as specified by the |
|||
various contexts in which an XPath expression is used. The |
|||
return value can be stored in a "variable" (no destructive |
|||
assignment is allowed), passed as a parameter to a function or a |
|||
template, used as a conditional in an <xsl:if/> or <xsl:when/>, |
|||
interpolated into text using <xsl:value-of/> or into an |
|||
attribute value using brace syntax, and so forth. |
|||
--> |
|||
<!-- Here, concat() is interpolated into an attribute value using braces ({}). --> |
|||
<line foo="{concat('Hello, ', 'Hello, ', 'Hello')}!">See attribute.</line> |
|||
<!-- Distinguishing built-in functions and user-defined functions --> |
|||
<!-- |
|||
Given that functions aren't first-class here, the origin of any |
|||
given function is known before run time. Incidentally, functions |
|||
defined by the standard are generally unprefixed while |
|||
implementation-specific extensions (and user extensions, if |
|||
available) must be defined within a separate namespace and |
|||
prefixed. |
|||
--> |
|||
<!-- Distinguishing subroutines and functions --> |
|||
<!-- |
|||
There are no "subroutines" in this sense—everything that looks |
|||
like a subroutine has some sort of return or result value. |
|||
--> |
|||
<!-- Stating whether arguments are passed by value or by reference --> |
|||
<!-- There is no meaningful distinction since there is no mechanism by which to mutate values. --> |
|||
<!-- Is partial application possible and how --> |
|||
<!-- Not natively. --> |
|||
</xsl:template> |
|||
<xsl:template name="xslt-template-demos"> |
|||
<!-- |
|||
A 'template' in XSLT 1.0 is a subroutine-like construct. When |
|||
given a name (and, optionally, parameters), it can be called |
|||
from within another template using the <xsl:call-template/> |
|||
element. (An unnamed template is instead called according to its |
|||
match and mode attributes.) The following demos apply to named |
|||
templates. |
|||
--> |
|||
<!-- |
|||
Unlike with functions, there are no built-in named templates to |
|||
speak of. The ones used here are defined later in this |
|||
transform. |
|||
--> |
|||
<!-- |
|||
Answers for these prompts are the same as with XPath functions (above): |
|||
Using a function in statement context |
|||
Distinguishing subroutines and functions |
|||
Stating whether arguments are passed by value or by reference |
|||
Is partial application possible and how |
|||
--> |
|||
<!-- Calling function that requires no arguments --> |
|||
<xsl:call-template name="nullary-demo"/> |
|||
<!-- |
|||
Note that even if a template has no parameters, it has access to |
|||
the current node (.) as of the time of the call. This |
|||
<xsl:apply-templates/> runs a matching template above that calls |
|||
the template "nullary-context-demo" with no parameters. Another |
|||
way to manipulate a template's idea of which node is current is |
|||
by calling from inside a <xsl:for-each/> loop. |
|||
--> |
|||
<xsl:apply-templates select="/*" mode="nullary-context-demo-mode"/> |
|||
<!-- |
|||
A template parameter is made optional in the definition of the |
|||
template by supplying an expression as its select attribute, |
|||
which is evaluated and used as its value if the parameter is |
|||
omitted. Note, though, that all template parameters have an |
|||
implicit default value, the empty string, if the select |
|||
attribute is not specified. Therefore, all template parameters |
|||
are always optional, even when semantically they should not be. |
|||
--> |
|||
<!-- Calling a function with a fixed number of arguments --> |
|||
<working note="When all parameters are supplied"> |
|||
<xsl:call-template name="ternary-demo"> |
|||
<xsl:with-param name="a" select="4"/> |
|||
<xsl:with-param name="b">3</xsl:with-param> |
|||
<xsl:with-param name="c" select="2 + 3"/> |
|||
</xsl:call-template> |
|||
</working> |
|||
<broken note="When the third parameter 'c' is omitted"> |
|||
<xsl:call-template name="ternary-demo"> |
|||
<xsl:with-param name="a" select="4"/> |
|||
<xsl:with-param name="b">3</xsl:with-param> |
|||
</xsl:call-template> |
|||
</broken> |
|||
<!-- Calling a function with optional arguments --> |
|||
<!-- With the optional third parameter --> |
|||
<working name="When all parameters are supplied"> |
|||
<xsl:call-template name="binary-or-ternary-demo"> |
|||
<xsl:with-param name="a" select="4"/> |
|||
<xsl:with-param name="b" select="3"/> |
|||
<xsl:with-param name="c" select="5"/> |
|||
</xsl:call-template> |
|||
</working> |
|||
<!-- Without the optional third parameter (which defaults to 0) --> |
|||
<working name="When 'a' and 'b' are supplied but 'c' is defaulted to 0"> |
|||
<xsl:call-template name="binary-or-ternary-demo"> |
|||
<xsl:with-param name="a" select="4"/> |
|||
<xsl:with-param name="b" select="3"/> |
|||
</xsl:call-template> |
|||
</working> |
|||
<!-- Calling a function with a variable number of arguments --> |
|||
<!-- |
|||
Templates are not varargs-capable. Variable numbers of arguments |
|||
usually appear in the form of a nodeset which is then bound to a |
|||
single parameter name. |
|||
--> |
|||
<!-- Calling a function with named arguments --> |
|||
<!-- |
|||
Other than what comes with the current context, template |
|||
arguments are always named and can be supplied in any order. |
|||
Templates do not support positional arguments. Additionally, |
|||
even arguments not specified by the template may be passed; they |
|||
are silently ignored. |
|||
--> |
|||
<!-- Using a function in first-class context within an expression --> |
|||
<!-- Templates are not first-class values in XSLT 1.0. --> |
|||
<!-- Obtaining the return value of a function --> |
|||
<!-- |
|||
The output of a template is interpolated into the place of the |
|||
call. Often, this is directly into the output of the transform, |
|||
as with most of the above examples. However, it is also possible |
|||
to bind the output as a variable or parameter. This is useful |
|||
for using templates to compute parameters for other templates or |
|||
for XPath functions. |
|||
--> |
|||
<!-- Which is the least of 34, 78, 12, 56? --> |
|||
<xsl:variable name="lesser-demo-result"> |
|||
<!-- The variable is bound to the output of this call --> |
|||
<xsl:call-template name="lesser-value"> |
|||
<xsl:with-param name="a"> |
|||
<!-- A call as a parameter to another call --> |
|||
<xsl:call-template name="lesser-value"> |
|||
<xsl:with-param name="a" select="34"/> |
|||
<xsl:with-param name="b" select="78"/> |
|||
</xsl:call-template> |
|||
</xsl:with-param> |
|||
<xsl:with-param name="b"> |
|||
<!-- and again --> |
|||
<xsl:call-template name="lesser-value"> |
|||
<xsl:with-param name="a" select="12"/> |
|||
<xsl:with-param name="b" select="56"/> |
|||
</xsl:call-template> |
|||
</xsl:with-param> |
|||
</xsl:call-template> |
|||
</xsl:variable> |
|||
<!-- The variable is used here in an XPath expression --> |
|||
<line> |
|||
<xsl:value-of select="concat('And the answer, which should be 12, is ', $lesser-demo-result, ', of course.')"/> |
|||
</line> |
|||
<!-- Distinguishing built-in functions and user-defined functions --> |
|||
<!-- Virtually all templates are user-defined. --> |
|||
</xsl:template> |
|||
<!-- Templates supporting template demos above --> |
|||
<xsl:template match="/*" mode="nullary-context-demo-mode"> |
|||
<xsl:call-template name="nullary-context-demo"/> |
|||
</xsl:template> |
|||
<xsl:template name="nullary-demo"> |
|||
<line>No parameters needed here!</line> |
|||
</xsl:template> |
|||
<xsl:template name="nullary-context-demo"> |
|||
<!-- When a template is called it has access to the current node of the caller --> |
|||
<xsl:for-each select="self::*"> |
|||
<line>The context element here is named "<xsl:value-of select="local-name()"/>"</line> |
|||
</xsl:for-each> |
|||
</xsl:template> |
|||
<xsl:template name="ternary-demo"> |
|||
<!-- This demo requires, at least semantically, all three parameters. --> |
|||
<xsl:param name="a"/> |
|||
<xsl:param name="b"/> |
|||
<xsl:param name="c"/> |
|||
<line>(<xsl:value-of select="$a"/> * <xsl:value-of select="$b"/>) + <xsl:value-of select="$c"/> = <xsl:value-of select="($a * $b) + $c"/></line> |
|||
</xsl:template> |
|||
<xsl:template name="binary-or-ternary-demo"> |
|||
<!-- This demo requires the first two parameters, but defaults the third to 0 if it is not supplied. --> |
|||
<xsl:param name="a"/> |
|||
<xsl:param name="b"/> |
|||
<xsl:param name="c" select="0"/> |
|||
<line>(<xsl:value-of select="$a"/> * <xsl:value-of select="$b"/>) + <xsl:value-of select="$c"/> = <xsl:value-of select="($a * $b) + $c"/></line> |
|||
</xsl:template> |
|||
<xsl:template name="lesser-value"> |
|||
<xsl:param name="a"/> |
|||
<xsl:param name="b"/> |
|||
<xsl:choose> |
|||
<xsl:when test="number($a) < number($b)"> |
|||
<xsl:value-of select="$a"/> |
|||
</xsl:when> |
|||
<xsl:otherwise> |
|||
<xsl:value-of select="$b"/> |
|||
</xsl:otherwise> |
|||
</xsl:choose> |
|||
</xsl:template> |
|||
</xsl:stylesheet> |
|||
</syntaxhighlight> |
|||
=={{header|Yabasic}}== |
|||
<syntaxhighlight lang="yabasic"> |
|||
sub test(a, b, c) : print a, b, c : end sub |
|||
test(1, 2, 3) // show 1 2 3 |
|||
test(1, 2) // show 1 2 0 |
|||
execute("test", 1, 2, 3) // show 1 2 3 |
|||
sub test$(a$) // show all members of a "list" |
|||
local n, i, t$(1) |
|||
n = token(a$, t$(), ", ") |
|||
for i = 1 to n |
|||
print t$(i), " "; |
|||
next |
|||
end sub |
|||
test$("1, 2, 3, 4, text, 6, 7, 8, \"include text\"") |
|||
print</syntaxhighlight> |
|||
=={{header|Z80 Assembly}}== |
|||
Like most assembly languages, the concept of functions are too "high-level" for most of the task to apply. However, subroutines do exist and they are used like a function in a high-level language would be. |
|||
* Functions that require no arguments are the simplest. They are simply <code>CALL</code>ed without any special input. |
|||
* Functions that take a fixed number of arguments usually require the programmer to load the arguments into registers or push them to the stack prior to calling the function. |
|||
<syntaxhighlight lang="z80">PackNibbles: |
|||
;input: B = top nibble, C = bottom nibble. Outputs to accumulator. |
|||
;usage: B = &0X, C = &0Y, => A = &XY |
|||
LD A,B |
|||
AND %00001111 |
|||
RLCA |
|||
RLCA |
|||
RLCA |
|||
RLCA |
|||
OR C |
|||
RET</syntaxhighlight> |
|||
* Assembly language in general has difficulty with optional and variable numbers of arguments (unless it is written by a compiler, of course). Prior to the function call, an optional argument would most likely be set to zero if intended to be unused in a particular instance of a function. |
|||
* Z80 Assembly does not support named arguments directly, but this can be achieved with assembly macros and labels. |
|||
* Getting a function's return value depends on how it was programmed. The concept of "return values" is a high-level construct that isn't enforced by assembly languages in general, and Z80 is no exception. The programmer is free to choose which register or section of memory the return value of a function is stored, if one even exists. Generally speaking the accumulator is usually used for this purpose but it depends on the data type as well as the needs of the program. |
|||
<syntaxhighlight lang="z80">AddTwoNumbers |
|||
;input registers: A,B. Outputs to A. |
|||
ADD a,b |
|||
RET</syntaxhighlight> |
|||
* Some implementations of Z80 Assembly have built-in functions. These are essentially just subroutines located in ROM at a specific memory address. Functions stored in low memory can be called with the <code>RST #</code> instruction. Anything in high memory will need to be <code>CALL</code>ed like any other user-created subroutine. On the Amstrad CPC, <code>CALL &BB5A</code> will print the accumulator to the screen as an ASCII character. |
|||
* Whether an argument is passed by value or by reference is again up to the programmer. By default, Z80 Assembly is pass-by-value, since it's much easier to operate on registers than directly on memory. The function would have to explicitly store the updated values back into memory for them to be altered. However, some Z80 instructions do directly alter memory, such as <code>RLD</code>,<code>RRD</code>,<code>LDIR</code>,etc. |
|||
=={{header|zkl}}== |
|||
The syntax and semantics of function calls is the always the same: name/object(parameters). All calls are varargs, it is up to the callee to do default/optional parameter handling (but that is hidden from the programmer). No named parameters. Pass by reference or value, depending. |
|||
Using f has a function, method or object: |
|||
<syntaxhighlight lang="zkl">f(); f(1,2,3,4); |
|||
fcn f(a=1){}() // define and call f, which gets a set to 1 |
|||
fcn{vm.arglist}(1,2,3,4) // arglist is L(1,2,3,4) |
|||
fcn{a1:=vm.nthArg(1)}(1,2,3) // a1 == 2 |
|||
(f() == True); (f() and 1 or 2) |
|||
if (f()) println() |
|||
f(f) // pass f to itself |
|||
s:=f() |
|||
fcn{}.isType(self.fcn) //True |
|||
fcn{}.len.isType(self.fcn) //False, len is a Method</syntaxhighlight> |
|||
Partial application is done with the .fp* methods or the 'wrap keyword |
|||
<syntaxhighlight lang="zkl"> |
|||
fcn(a,b,c).fp(1)() // call function with a always set to 1 |
|||
fcn(a,b,c).fp1(2,3)() // call function with b & c always set to 2 & 3 |
|||
fcn(a,b,c,d).fpN(3,5)() // call function with d always set to 5 |
|||
fcn{vm.arglist}.fpN(3,66)(1,2,3,4,5) //-->L(1,2,3,66,4,5) |
|||
fcn{}.fpM("01-",5) // use a mask to select parameters |
|||
// 1 is supplied, 0 is get upon call, - is chop arglist |
|||
fcn{vm.arglist}.fpM("01-",66)(1,2,3,4) //-->L(1,66) |
|||
a:=5; f('wrap(b){a+b}) // 'wrap is syntactic sugar for .fpN |
|||
// to create a lexical closure --> f(fcn(b,a){a+b}.fpN(1,a))</syntaxhighlight> |
|||
=={{header|zonnon}}== |
|||
<syntaxhighlight lang="zonnon"> |
|||
module CallingProcs; |
|||
type |
|||
{public} Vector = array {math} * of integer; |
|||
var |
|||
nums: array {math} 4 of integer; |
|||
ints: Vector; |
|||
total: integer; |
|||
procedure Init(): boolean; (* private by default *) |
|||
begin |
|||
nums := [1,2,3,4]; |
|||
ints := new Vector(5); |
|||
ints := [2,4,6,8,10]; |
|||
return true; |
|||
end Init; |
|||
(* function *) |
|||
procedure Sum(v: Vector): integer; |
|||
var |
|||
i,s: integer; |
|||
begin |
|||
s := 0; |
|||
for i := 0 to len(v) - 1 do |
|||
(* inc is a predefined subroutine *) |
|||
inc(s,v[i]) |
|||
end; |
|||
return s |
|||
end Sum; |
|||
(* subroutine |
|||
* @param v: by value |
|||
* @param t: by reference |
|||
*) |
|||
procedure Sum2(v: array {math} * of integer; var t: integer); |
|||
var |
|||
i: integer; |
|||
begin |
|||
t := 0; |
|||
for i := 0 to len(v) - 1 do |
|||
inc(t,v[i]) |
|||
end |
|||
end Sum2; |
|||
begin |
|||
Init; (* calling a function without parameters *) |
|||
total := Sum(nums); |
|||
writeln(total); |
|||
(* optional arguments not supported *) |
|||
(* variable arguments through open arrays *) |
|||
writeln(Sum(ints)); |
|||
(* named arguments not supported *) |
|||
ints := [1,3,5,7,9]; |
|||
Sum2(ints,total); |
|||
writeln(total); |
|||
end CallingProcs. |
|||
</syntaxhighlight> |
|||
=={{header|ZX Spectrum Basic}}== |
=={{header|ZX Spectrum Basic}}== |
||
On the ZX Spectrum, functions and subroutines are separate entities. A function is limited to being a single expression that generates a return value. Statements are not allowed within a function. A subroutine can perform input and output and can contain statements. |
On the ZX Spectrum, functions and subroutines are separate entities. A function is limited to being a single expression that generates a return value. Statements are not allowed within a function. A subroutine can perform input and output and can contain statements. |
||
< |
<syntaxhighlight lang="zxbasic">10 REM functions cannot be called in statement context |
||
20 PRINT FN a(5): REM The function is used in first class context. Arguments are not named |
20 PRINT FN a(5): REM The function is used in first class context. Arguments are not named |
||
30 PRINT FN b(): REM Here we call a function that has no arguments |
30 PRINT FN b(): REM Here we call a function that has no arguments |
||
Line 1,396: | Line 7,006: | ||
100 PRINT SIN(50): REM here we pass a parameter to a builtin function |
100 PRINT SIN(50): REM here we pass a parameter to a builtin function |
||
110 PRINT RND(): REM here we use a builtin function without parameters |
110 PRINT RND(): REM here we use a builtin function without parameters |
||
120 RANDOMIZE: REM statements are not functions and cannot be used in first class context.</ |
120 RANDOMIZE: REM statements are not functions and cannot be used in first class context.</syntaxhighlight> |
||
{{omit from|GUISS}} |
{{omit from|GUISS}} |
Latest revision as of 18:54, 1 May 2024
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Demonstrate the different syntax and semantics provided for calling a function.
This may include:
- Calling a function that requires no arguments
- Calling a function with a fixed number of arguments
- Calling a function with optional arguments
- Calling a function with a variable number of arguments
- Calling a function with named arguments
- Using a function in statement context
- Using a function in first-class context within an expression
- Obtaining the return value of a function
- Distinguishing built-in functions and user-defined functions
- Distinguishing subroutines and functions
- Stating whether arguments are passed by value or by reference
- Is partial application possible and how
This task is not about defining functions.
11l
F no_args() {}
// call
no_args()
F fixed_args(x, y)
print(‘x=#., y=#.’.format(x, y))
// call
fixed_args(1, 2) // x=1, y=2
// named arguments
fixed_args(x' 1, y' 2)
F opt_args(x = 1)
print(x)
// calls
opt_args() // 1
opt_args(3.141) // 3.141
360 Assembly
Due to assembler, argument are passed by reference.
With:
X DS F
Y DS F
Z DS F
If you do not want to use the CALL macro instruction and for a link-edited object-module:
L R15,=V(MULTPLIC)
LA R1,PARMLIST address of the paramter list
BALR R14,R15 branch and link
ST R0,Z Z=MULTPLIC(X,Y)
* ...
PARMLIST DC A(X)
DC A(Y)
If you call a link-edited object-module:
CALL MULTPLIC,(X,Y) call MULTPLIC(X,Y)
ST R0,Z Z=MULTPLIC(X,Y)
If you call an load-module at execution time:
LOAD EP=MULTPLIC load load-module
LR R15,R0 retrieve entry address
CALL (R15),(X,Y) call MULTPLIC(X,Y)
ST R0,Z Z=MULTPLIC(X,Y)
6502 Assembly
To call a function, you use JSR
followed by the pointer to its beginning. Most of the time this will be a labeled line of code that your assembler will convert to an actual memory address for you during the assembly process.
JSR myFunction
Function arguments are often passed in through registers, the zero page, or the stack. Given how awkward it is to work with the stack on the 6502, it's best not to use the hardware stack as a means of parameter passing. CC65 uses a software stack in the upper half of zero page, which is indexed using the X register.
sum:
;adds the values in zero page address $00 and $01, outputs to accumulator.
LDA $00 ;load the byte stored at memory address $0000
CLC
ADC $01 ;add the byte at memory address $0001
RTS ;return
The return value is usually stored in the accumulator if it will fit in 8 bits. If not, it's often stored in a dedicated section of the zero page. Since the 6502 has very few registers and all are 8-bit, it's common to set aside a few zero page memory addresses for holding 16-bit return values.
Statements like PRINT SIN(45)
, or expressions where you assign a variable to a function's output don't exist in assembly. You have to perform the functions individually, working from the inside out, and process them one at a time. In other words, a BASIC statement like PRINT SIN(45)
would have to compute SIN(45)
first, then pass the return value to PRINT
. This is just as true with modern CPUs as it was with the 6502.
The closest thing 6502 has to true "built-in functions" are the interrupt vectors whose pointers are stored at the very end of memory. They are, in order: Non-maskable interrupt (NMI), reset, and IRQ (Interrupt Request). They are no different than other functions except they end in RTI
rather than RTS
. With "bare-metal programming" like on the NES this is all you have, but most computers of the 80s had some sort of kernel or operating system that had pre-defined functions you could use simply by JSR
ing their memory address. The actual memory locations of these, and what they did, varies by implementation.
8086 Assembly
A function that requires no arguments is simply CALL
ed:
call foo
Functions with a fixed number of arguments have their arguments pushed onto the stack prior to the call. This is how C compilers generate 8086 assembly code. Assembly written by a person can use the stack or registers to pass arguments. Passing via registers is faster but more prone to errors and clobbering, which can cause other functions to not operate correctly.
push ax ;second argument
push bx ;first argument - typically arguments are pushed in the reverse order they are listed.
call foo
pop bx
pop ax
foo:
push bp
mov bp,sp
;now bp+4 = the value pushed from BX, and bp+6 = the value pushed from AX
The 8086 cannot support named arguments directly. However it is possible to label a section of RAM, and use that as the argument for a function.
foo:
ld ax,word ptr[ds:bar] ;load from bar, which is a 16 bit storage location in the data segment (DS), into AX
Built-in functions are typically called using the INT
instruction. This instruction takes a numeric constant as its primary argument, and the value in AH
as a selector of sorts. This command is used to exit a program and return to MS-DOS:
mov AH,4Ch
mov AL,00h
int 21h
68000 Assembly
To call a function, you use JSR
followed by the pointer to its beginning. Most of the time this will be a labeled line of code that your assembler will convert to an actual memory address for you during the assembly process.
JSR myFunction
Function arguments are often passed in through the stack. When looking at the function in C or a similar language that compiles to 68000 Assembly, the arguments are pushed in the reverse order they are listed. Return values typically go into the D0 register if they're 32-bit or smaller. The CPU does not enforce this, so it's up to the programmer or compiler to use calling conventions to ensure compatibility between software.
AArch64 Assembly
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program callfonct.s */
/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
/***********************/
/* Initialized data */
/***********************/
.data
szMessage: .asciz "Hello. \n" // message
szRetourLigne: .asciz "\n"
szMessResult: .asciz "Resultat : " // message result
/***********************/
/* No Initialized data */
/***********************/
.bss
sZoneConv: .skip 100
.text
.global main
main:
ldr x0,=szMessage // adresse of message short program
bl affichageMess // call function with 1 parameter (x0)
// call function with parameters in register
mov x0,#5
mov x1,#10
bl fonction1 // call function with 2 parameters (x0,x1)
ldr x1,qAdrsZoneConv // result in x0
bl conversion10S // call function with 2 parameter (x0,x1)
ldr x0,=szMessResult
bl affichageMess // call function with 1 parameter (x0)
ldr x0,qAdrsZoneConv
bl affichageMess
ldr x0,qAdrszRetourLigne
bl affichageMess
// call function with parameters on stack
mov x0,#5
mov x1,#10
stp x0,x1,[sp,-16]! // store registers on stack
bl fonction2 // call function with 2 parameters on the stack
// result in x0
ldr x1,qAdrsZoneConv
bl conversion10S // call function with 2 parameter (x0,x1)
ldr x0,=szMessResult
bl affichageMess // call function with 1 parameter (x0)
ldr x0,qAdrsZoneConv
bl affichageMess
ldr x0,qAdrszRetourLigne
bl affichageMess
// end of program
mov x0, #0 // return code
mov x8, #EXIT // request to exit program
svc 0 // perform the system call
qAdrsZoneConv: .quad sZoneConv
qAdrszRetourLigne: .quad szRetourLigne
/******************************************************************/
/* call function parameter in register */
/******************************************************************/
/* x0 value one */
/* x1 value two */
/* return in x0 */
fonction1:
stp x2,lr,[sp,-16]! // save registers
mov x2,#20
mul x0,x0,x2
add x0,x0,x1
ldp x2,lr,[sp],16 // restaur 2 registres
ret // retour adresse lr x30
/******************************************************************/
/* call function parameter in the stack */
/******************************************************************/
/* return in x0 */
fonction2:
stp fp,lr,[sp,-16]! // save registers
add fp,sp,#16 // address parameters in the stack
stp x1,x2,[sp,-16]! // save others registers
ldr x0,[fp] // second paraméter
ldr x1,[fp,#8] // first parameter
mov x2,#-20
mul x0,x0,x2
add x0,x0,x1
ldp x1,x2,[sp],16 // restaur 2 registres
ldp fp,lr,[sp],16 // restaur 2 registres
add sp,sp,#16 // very important, for stack aligned
ret // retour adresse lr x30
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
- Output:
Hello. Resultat : +110 Resultat : -90
ActionScript
myfunction(); /* function with no arguments in statement context */
myfunction(6,b); // function with two arguments in statement context
stringit("apples"); //function with a string argument
Ada
- Ada provides two kinds of subroutines: procedures without return values and functions with return values. The return values of functions must be used by the callers. If you don't want to deal with the return value, call a procedure instead.
- As a rule of thumb, an Ada compiler is free to pass arguments either by value or by reference. Parameters have a mode however: either 'in' or 'out' or 'in out'. It is prohibited to write anything to an 'in' parameter. The next language Standard, Ada 2012, will support functions with 'out' and 'in out' mode parameters, so far, only procedures could have parameters with non-'in' modes. So any of the following statements for Ada functions holds for Ada procedures as well.
- There are no differences between calling built-in vs. user defined functions.
- Functions without parameters can be called by omitting the parameter list (no empty brackets!):
S: String := Ada.Text_IO.Get_Line;
- Ada supports functions with optional parameters:
function F(X: Integer; Y: Integer := 0) return Integer; -- Y is optional ... A : Integer := F(12); B : Integer := F(12, 0); -- the same as A C : Integer := F(12, 1); -- something different
- If the number of parameters of F were fixed to two (by omitting the ":= 0" in the specification), then B and C would be OK, but A wouldn't.
- Ada does not support functions with a variable number of arguments. But a function argument can be an unconstrained array with as many values as you want:
type Integer_Array is array (Positive range <>) of Integer; function Sum(A: Integer_Array) return Integer is S: Integer := 0; begin for I in A'Range loop S := S + A(I); end loop; return S; end Sum; ... A := Sum((1,2,3)); -- A = 6 B := Sum((1,2,3,4)); -- B = 10
- One can realize first-class functions by defining an access to a function as a parameter:
function H (Int: Integer; Fun: not null access function (X: Integer; Y: Integer) return Integer); return Integer; ... X := H(A, F'Access) -- assuming X and A are Integers, and F is a function -- taking two Integers and returning an Integer.
- The caller is free to use either positional parameters or named parameters, or a mixture of both (with positional parameters first)
Positional := H(A, F'Access); Named := H(Int => A, Fun => F'Access); Mixed := H(A, Fun=>F'Access);
ALGOL 68
# Note functions and subroutines are called procedures (or PROCs) in Algol 68 #
# A function called without arguments: #
f;
# Algol 68 does not expect an empty parameter list for calls with no arguments, "f()" is a syntax error #
# A function with a fixed number of arguments: #
f(1, x);
# variable number of arguments: #
# functions that accept an array as a parameter can effectively provide variable numbers of arguments #
# a "literal array" (called a row-display in Algol 68) can be passed, as is often the case for the I/O #
# functions - e.g.: #
print( ( "the result is: ", r, " after ", n, " iterations", newline ) );
# the outer brackets indicate the parameters of print, the inner brackets indicates the contents are a "literal array" #
# ALGOL 68 does not support optional arguments, though in some cases an empty array could be passed to a function #
# expecting an array, e.g.: #
f( () );
# named arguments - see the Algol 68 sample in: http://rosettacode.org/wiki/Named_parameters #
# In "Talk:Call a function" a statement context is explained as
"The function is used as an instruction (with a void context),
rather than used within an expression."
Based on that, the examples above are already in a statement context.
Technically, when a function that returns other than VOID (i.e. is not a subroutine)
is called in a statement context, the result of the call is "voided" i.e. discarded.
If desired, this can be made explicit using a cast, e.g.: #
VOID(f);
# A function's return value being used: #
x := f(y);
# There is no distinction between built-in functions and user-defined functions. #
# A subroutine is simply a function that returns VOID. #
# If the function is declared with argument(s) of mode REF MODE,
then those arguments are being passed by reference. #
# Technically, all parameters are passed by value, however the value of a REF MODE is a reference... #
See First-Class Functions for an example of first-class functions in ALGOL 68.
See Partial Function Application for an example of partial function application in ALGOL 68.
See Optional Parameters for an example of optional parameters in Algol 68.
See Named Parameters for an example of named parameters in Algol 68.
ALGOL W
% Note, in Algol W, functions are called procedures %
% calling a function with no parameters: %
f;
% calling a function with a fixed number of parameters %
g( 1, 2.3, "4" );
% Algol W does not support optional parameters in general, however constructors for records can %
% be called wither with parameters (one for each field in the record) or no parameters #
% Algol W does not support variable numbers of parameters, except for the built-in I/O functions #
% Algol W does not support named arguments %
% A function can be used in a statement context by calling it, as in the examples above %
% First class context: A function can be passed as a parameter to another procedure, e.g.: %
v := integrate( sin, 0, 1 )
% assuming a suitable definition of integrate %
% Algol W does not support functions returning functions %
% obtaining the return value of a function: e.g.: %
v := g( x, y, z );
% There is no syntactic distinction between user-defined and built-in functions %
% Subroutines and functions are both procedures, a subroutine is a procedure with no return type %
% (called a proper procedure in Algol W) %
% There is no syntactic distinction between a call to a function and a call to a subroutine %
% other than the context %
% In Algol W, parameters are passed by value, result or value result. This must be stated in the %
% definition of the function/subroutine. Value parameters are passed by value, result and value result %
% are effectively passed by reference and assigned on function exit. Result parameters are "out" parameters %
% and value result parameters are "in out". %
% Algol W also has "name" parameters (not to be confused with named parameters). Functions with name %
% parameters are somewhat like macros %
% Partial application is not possible in Algol W %
AntLang
AntLang provides two ways to apply a function. One way is infix application.
2*2+9
Infix application is right associative, so x f y g z means x f (y g z) and not (x f y) g z. You can break this rule using parenthesis. The other way is prefix application.
*[2;+[2;9]]
echo["Hello!"]
time[]
ARM Assembly
/* ARM assembly Raspberry PI */
/* program callfonct.s */
/* Constantes */
.equ STDOUT, 1
.equ WRITE, 4
.equ EXIT, 1
/***********************/
/* Initialized data */
/***********************/
.data
szMessage: .asciz "Hello. \n" @ message
szRetourLigne: .asciz "\n"
szMessResult: .ascii "Resultat : " @ message result
sMessValeur: .fill 12, 1, ' '
.asciz "\n"
/***********************/
/* No Initialized data */
/***********************/
.bss
iValeur: .skip 4 @ reserve 4 bytes in memory
.text
.global main
main:
ldr r0,=szMessage @ adresse of message short program
bl affichageMess @ call function with 1 parameter (r0)
@ call function with parameters in register
mov r0,#5
mov r1,#10
bl fonction1 @ call function with 2 parameters (r0,r1)
ldr r1,=sMessValeur @ result in r0
bl conversion10S @ call function with 2 parameter (r0,r1)
ldr r0,=szMessResult
bl affichageMess @ call function with 1 parameter (r0)
@ call function with parameters on stack
mov r0,#5
mov r1,#10
push {r0,r1}
bl fonction2 @ call function with 2 parameters on the stack
@ result in r0
ldr r1,=sMessValeur
bl conversion10S @ call function with 2 parameter (r0,r1)
ldr r0,=szMessResult
bl affichageMess @ call function with 1 parameter (r0)
/* end of program */
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
swi 0 @ perform the system call
/******************************************************************/
/* call function parameter in register */
/******************************************************************/
/* r0 value one */
/* r1 value two */
/* return in r0 */
fonction1:
push {fp,lr} /* save des 2 registres */
push {r1,r2} /* save des autres registres */
mov r2,#20
mul r0,r2
add r0,r0,r1
pop {r1,r2} /* restaur des autres registres */
pop {fp,lr} /* restaur des 2 registres */
bx lr /* retour procedure */
/******************************************************************/
/* call function parameter in the stack */
/******************************************************************/
/* return in r0 */
fonction2:
push {fp,lr} /* save des 2 registres */
add fp,sp,#8 /* address parameters in the stack*/
push {r1,r2} /* save des autres registres */
ldr r0,[fp]
ldr r1,[fp,#4]
mov r2,#-20
mul r0,r2
add r0,r0,r1
pop {r1,r2} /* restaur des autres registres */
pop {fp,lr} /* restaur des 2 registres */
add sp,#8 /* very important, for stack aligned */
bx lr /* retour procedure */
/******************************************************************/
/* affichage des messages avec calcul longueur */
/******************************************************************/
/* r0 contient l adresse du message */
affichageMess:
push {fp,lr} /* save des 2 registres */
push {r0,r1,r2,r7} /* save des autres registres */
mov r2,#0 /* compteur longueur */
1: /*calcul de la longueur */
ldrb r1,[r0,r2] /* recup octet position debut + indice */
cmp r1,#0 /* si 0 c est fini */
beq 1f
add r2,r2,#1 /* sinon on ajoute 1 */
b 1b
1: /* donc ici r2 contient la longueur du message */
mov r1,r0 /* adresse du message en r1 */
mov r0,#STDOUT /* code pour écrire sur la sortie standard Linux */
mov r7, #WRITE /* code de l appel systeme 'write' */
swi #0 /* appel systeme */
pop {r0,r1,r2,r7} /* restaur des autres registres */
pop {fp,lr} /* restaur des 2 registres */
bx lr /* retour procedure */
/***************************************************/
/* conversion registre en décimal signé */
/***************************************************/
/* r0 contient le registre */
/* r1 contient l adresse de la zone de conversion */
conversion10S:
push {fp,lr} /* save des 2 registres frame et retour */
push {r0-r5} /* save autres registres */
mov r2,r1 /* debut zone stockage */
mov r5,#'+' /* par defaut le signe est + */
cmp r0,#0 /* nombre négatif ? */
movlt r5,#'-' /* oui le signe est - */
mvnlt r0,r0 /* et inversion en valeur positive */
addlt r0,#1
mov r4,#10 /* longueur de la zone */
1: /* debut de boucle de conversion */
bl divisionpar10 /* division */
add r1,#48 /* ajout de 48 au reste pour conversion ascii */
strb r1,[r2,r4] /* stockage du byte en début de zone r5 + la position r4 */
sub r4,r4,#1 /* position précedente */
cmp r0,#0
bne 1b /* boucle si quotient different de zéro */
strb r5,[r2,r4] /* stockage du signe à la position courante */
subs r4,r4,#1 /* position précedente */
blt 100f /* si r4 < 0 fin */
/* sinon il faut completer le debut de la zone avec des blancs */
mov r3,#' ' /* caractere espace */
2:
strb r3,[r2,r4] /* stockage du byte */
subs r4,r4,#1 /* position précedente */
bge 2b /* boucle si r4 plus grand ou egal a zero */
100: /* fin standard de la fonction */
pop {r0-r5} /*restaur des autres registres */
pop {fp,lr} /* restaur des 2 registres frame et retour */
bx lr
/***************************************************/
/* division par 10 signé */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*
/* and http://www.hackersdelight.org/ */
/***************************************************/
/* r0 contient le dividende */
/* r0 retourne le quotient */
/* r1 retourne le reste */
divisionpar10:
/* r0 contains the argument to be divided by 10 */
push {r2-r4} /* save autres registres */
mov r4,r0
ldr r3, .Ls_magic_number_10 /* r1 <- magic_number */
smull r1, r2, r3, r0 /* r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0) */
mov r2, r2, ASR #2 /* r2 <- r2 >> 2 */
mov r1, r0, LSR #31 /* r1 <- r0 >> 31 */
add r0, r2, r1 /* r0 <- r2 + r1 */
add r2,r0,r0, lsl #2 /* r2 <- r0 * 5 */
sub r1,r4,r2, lsl #1 /* r1 <- r4 - (r2 * 2) = r4 - (r0 * 10) */
pop {r2-r4}
bx lr /* leave function */
.align 4
.Ls_magic_number_10: .word 0x66666667
Arturo
printHello: $[][
print "Hello World!"
]
sayHello: $[name][
print ["Hello" name "!"]
]
printAll: $[args][
loop args [arg][
print arg
]
]
getNumber: $[][3]
; Calling a function that requires no arguments
printHello
; Calling a function with a fixed number of arguments
sayHello "John"
; Calling a function with a variable number of arguments
printAll ["one" "two" "three"]
; Using a function in statement context
if true [printHello]
print getNumber
; Using a function in first-class context within an expression
if getNumber=3 [print "yep, it worked"]
; Obtaining the return value of a function:
num: getNumber
print num
- Output:
Hello World! Hello John ! one two three Hello World! 3 yep, it worked 3
AutoHotkey
; Call a function without arguments:
f()
; Call a function with a fixed number of arguments:
f("string", var, 15.5)
; Call a function with optional arguments:
f("string", var, 15.5)
; Call a function with a variable number of arguments:
f("string", var, 15.5)
; Call a function with named arguments:
; AutoHotkey does not have named arguments. However, in v1.1+,
; we can pass an object to the function:
f({named: "string", otherName: var, thirdName: 15.5})
; Use a function in statement context:
f(1), f(2) ; What is statement context?
; No first-class functions in AHK
; Obtaining the return value of a function:
varThatGetsReturnValue := f(1, "a")
; Cannot distinguish built-in functions
; Subroutines are called with GoSub; functions are called as above.
; Subroutines cannot be passed variables
; Stating whether arguments are passed by value or by reference:
; [v1.1.01+]: The IsByRef() function can be used to determine
; whether the caller supplied a variable for a given ByRef parameter.
; A variable cannot be passed by value to a byRef parameter. Instead, do this:
f(tmp := varIdoNotWantChanged)
; the function f will receive the value of varIdoNotWantChanged, but any
; modifications will be made to the variable tmp.
; Partial application is impossible.
AWK
The awk interpreter reads the entire script prior to processing, so functions can be called from sections of code appearing before the definition.
BEGIN {
sayhello() # Call a function with no parameters in statement context
b=squareit(3) # Obtain the return value from a function with a single parameter in first class context
}
In awk, scalar values are passed by value, but arrays are passed by reference. Note that if a function has no arguments, then empty parentheses are required.
The awk extraction and reporting language does not support the use of named parameters.
Axe
In Axe, up to six arguments are passed as the variables r₁ through r₆. As with all variables in Axe, these exist in the global scope, which makes nested function calls and recursion quite difficult.
NOARG()
ARGS(1,5,42)
Since arguments are simply global variables, they are always optional and can be omitted from right to left.
OPARG(1,2,3,4,5,6)
OPARG(1,2,3)
OPARG()
Somewhat similar to TI-83 BASIC, the last evaluated expression becomes the return value of the function. However, this is distinct from the Ans variable. Return values can be captured just like any other expression.
MATHS(2,4)→A
Disp GETSTR()
User-defined functions can be distinguished from language-defined functions by the fact that language-defined function names are composed of atomic tokens (usually with built-in parentheses) whereas user-defined function names are composed of individual characters. Also, because only uppercase letters are available by default in the OS, most user-defined names are all uppercase while language-defined names are mixed case.
USER()
axeFunc()
BASIC
BASIC256
function Copialo$ (txt$, siNo, final$)
nuevaCadena$ = ""
for cont = 1 to siNo
nuevaCadena$ += txt$
next cont
return trim(nuevaCadena$) + final$
end function
subroutine Saludo()
print "Hola mundo!"
end subroutine
subroutine testCadenas (txt$)
for cont = 1 to length(txt$)
print mid(txt$, cont, 1); "";
next cont
end subroutine
subroutine testNumeros (a, b, c)
print a, b, c
end subroutine
call Saludo()
print Copialo$("Saludos ", 6, "")
print Copialo$("Saludos ", 3, "!!")
print
call testNumeros(1, 2, 3)
call testNumeros(1, 2, 0)
print
call testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \#incluye texto\#")
end
- Output:
Igual que la entrada de FreeBASIC.
Batch File
Batch files do not have a traditional "function" system like OOP languages, however this is the closest thing to it. The only difference between a block of code and a function is the way method you choose to invoke it. It's also worth noting that all batch files can be called from any other batch file, performing a function. A function should be put somewhere in the code where it will not be parsed unless the script is redirected there.
:: http://rosettacode.org/wiki/Call_a_function
:: Demonstrate the different syntax and semantics provided for calling a function.
@echo off
echo Calling myFunction1
call:myFunction1
echo.
echo Calling myFunction2 11 8
call:myFunction2 11 8
echo.
echo Calling myFunction3 /fi and saving the output into %%filecount%%
call:myFunction3 /fi
echo.%filecount%
echo.
echo Calling myFunction4 1 2 3 4 5
call:myFunction4 1 2 3 4 5
echo.
echo Calling myFunction5 "filename=test.file" "filepath=C:\Test Directory\"
call:myFunction5 "filename=test.file" "filepath=C:\Test Directory\"
echo.
echo Calling myFunction5 "filepath=C:\Test Directory\" "filename=test.file"
call:myFunction5 "filepath=C:\Test Directory\" "filename=test.file"
echo.
pause>nul
exit
:: Requires no arguments
:myFunction1
echo myFunction1 has been called.
goto:eof
:: Fixed number of arguments (%a% & %b%)
:myFunction2
:: Returns %a% + %b%
setlocal
set /a c=%~1+%~2
endlocal & echo %c%
goto:eof
:: Optional arguments
:myFunction3
:: Returns the amount of folders + files in the current directory
:: /fi Returns only file count
:: /fo Returns only folder count
setlocal
set count=0
if "%~1"=="" set "command=dir /b"
if "%~1"=="/fi" set "command=dir /b /A-d"
if "%~1"=="/fo" set "command=dir /b /Ad"
for /f "usebackq" %%i in (`%command%`) do set /a count+=1
endlocal & set filecount=%count%
goto:eof
:: Variable number of arguments
:myFunction4
:: Returns sum of arguments
setlocal
:myFunction4loop
set sum=0
for %%i in (%*) do set /a sum+=%%i
endlocal & echo %sum%
goto:eof
:: Named Arguments (filepath=[path] & filename=[name])
:myFunction5
:: Returns the complete path based off the 2 arguments
if "%~1"=="" then goto:eof
setlocal enabledelayedexpansion
set "param=%~1"
for /l %%i in (1,1,2) do (
for /f "tokens=1,2 delims==" %%j in ("!param!") do set %%j=%%k
set "param=%~2"
)
endlocal & echo.%filepath%%filename%
goto:eof
Output:
Calling myFunction1 myFunction1 has been called. Calling myFunction2 11 8 19 Calling myFunction3 /fi and saving the output into %filecount% 1 Calling myFunction4 1 2 3 4 5 15 Calling myFunction5 "filename=test.file" "filepath=C:\Test Directory\" C:\Test Directory\test.file Calling myFunction5 "filepath=C:\Test Directory\" "filename=test.file" C:\Test Directory\test.file
BBC BASIC
BBC BASIC distinguishes between functions (which return one value), procedures (which may return an arbitrary number of values including zero), and subroutines. Functions can be built-in or user-defined. A call to a built-in function (for example, the square root function) is an expression:
PRINT SQR(2)
The parentheses can often be omitted:
PRINT SQR 2
The name of a user-defined function must begin with FN. A call to it is also an expression:
PRINT FN_foo(bar$, baz%)
(The sigils $ and % identify the variables' types.) A function that takes no arguments can be called omitting the parentheses:
PRINT FN_foo
The name of a procedure must begin with PROC. A call to it is a statement, not an expression:
PROC_foo
If it has arguments, they come in parentheses just as with a function:
PROC_foo(bar$, baz%, quux)
Note that you cannot tell from this syntax which of the variables bar$, baz%, and quux are arguments provided to the procedure and which of them are return values from it. You have to look at where it is defined:
DEF PROC_foo(a$, RETURN b%, RETURN c)
Subroutines are provided for compatibility with older, unstructured dialects of BASIC; otherwise they are never really used. They require statements to be numbered, and they can neither receive arguments nor return values: they can only manipulate global variables. The GOSUB and RETURN statements in fact mirror assembly language 'jump to subroutine' and 'return from subroutine' instructions quite closely.
200 GOSUB 30050
Binary Lambda Calculus
Function calling is the sole primitive in the Lambda Calculus. The application of function f on argument a is denoted 01 f a in Binary Lambda Calculus. Multi argument functions are achieved by currying, i.e. a function of the first argument returns a function of the 2nd argument, etc. A good example is the Church numeral 2, which given a function f and an argument x, applies f twice on x: C2 = \f. \x. f (f x). This is written in BLC as
00 00 01 110 01 110 01
BQN
BQN's functions take one or two arguments, and the behave like the primitive functions of the language.
Calling a function that requires no arguments: BQN does not have zero argument functions. Having a function that does so is done with the help of a dummy argument, like so:
{𝕊 ·: 1 + 1}0
The dot symbol ·
indicates that the argument is nothing, and hence is discarded. Hence, the zero provided to it is discarded, and 1 + 1 = 2 is returned.
Calling a function with a fixed number of arguments: BQN functions always take 1 or two arguments, and their names must always start with a capital letter. A function is called like a primitive function, by writing its name or the function itself between the arguments. For example, given a function named F
:
F 1
is an example of a single argument call.
2 F 1
is an example of a two argument call.
Calling a function with optional arguments: optional arguments are not supported by BQN.
Calling a function with a variable number of arguments: A function supporting variable arguments can be made by taking an array as any of the arguments.
Calling a function with named arguments: BQN has block headers, which destructure an input array into given variables using pattern matching. These can then be referenced later by the names given.
{
𝕊 one‿two‿three:
one∾two∾three
}
Given a three element array, the above example will concatenate them all together.
Using a function in statement context: BQN user defined functions have the same syntactic roles as primitive functions in an expression, so they can be used like any primitive.
1 {𝕨+𝕩} 2
is the same as
1 + 2
Using a function in first-class context within an expression: BQN supports lisp-style functional programming, and hence supports first class usage of functions.
⟨+, -, ∾⟩
is an example of a list of functions, which can later be called with the help of a higher order function.
Obtaining the return value of a function: A block function will always return the value of the last statement within it. To obtain the return value of a function, you can assign it to a variable, or modify an existing variable with the return value.
var ← Func # insert arg here
Arguments are passed to BQN functions by value only.
Partial Application: BQN has two combinators for this purpose. Before (⊸
) returns a function with a constant left argument, and After (⟜
) returns a function with a constant right argument.
+⟜2
will add two to the number given to it.
2⊸-
will subtract its input from two.
Bracmat
- Calling a function that requires no arguments:
Strictly speaking, all Bracmat functions receive at least one argument. But empty strings are valid expressions, so you can do
aFunctionWithoutArguments$
or
aFunctionWithoutArguments'
Both function calls pass the right and side of the $
or '
operator. This is in fact still something: an empty string.
The $
operator always evaluates its right hand side before passing it to the function, while the '
does not. Therefore it is slightly faster to use the functionName'
variant.
- Calling a function with a fixed number of arguments:
Bracmat passes exactly one argument to a function, called arg
. The argument can be any Bracmat expression. In patterns, if a function call expression is a pattern component, a second argument sjt
is added, the part of the subject that the pattern component is going trying to match.
- Calling a function with optional arguments
There is no special syntax for that. It is up to the programmer to define a datastructure with a variable part, e.g., a list.
- Calling a function with a variable number of arguments
Same answer.
- Calling a function with named arguments
There is no special syntax for that. You could pass a list of (name.value) pairs.
- Using a function in statement context
A f...
You can do
func$!myargument;
The ;
marks the end of a Bracmat statement.
- Using a function in first-class context within an expression
(Copied from JavaScript:) Bracmat functions are first-class citizens; they can be stored in variables and passed as arguments. Assigning to a variable yourfunc
can be done in a few ways. The most common one is
(yourfunc=local vars.function body)
If there is already a function myfunc
that you want to assign to yourfunc
as well, do
('$myfunc:(=?yourfunc))
- Obtaining the return value of a function
myfunc$!myarg:?myresult
Notice that the returned value can be any evaluated expression.
- Distinguishing built-in functions and user-defined functions
You cannot list built-in functions that are implemented directly in C. Nor can such functions be passed as arguments or assigned to variables. There are also a number of built-in functions that are written in Bracmat. They are nothing special and can be deleted or redefined. You can see a list of all currently defined functions that are written in Bracmat with the function call cat'
.
- Distinguishing subroutines and functions
You can ignore the return value of a function myfunc
as follows:
myfunc$!myarg&yourfunc$!yourarg
But notice that if myfunc
fails, the above expression returns the value produced by myfunc
! To also ignore the success/failure of a function, do
`(myfunc$!myarg)&yourfunc$!yourarg
- Stating whether arguments are passed by value or by reference
Values are passed by reference, or by value if the reference counter, which is a very small integer, overflows. Most values are immutable, so for those there is no practical difference between passing by reference or value. The single exception of a mutable value is always passed by reference, and has an enormous reference counter. (The binary operator =
introduces a mutable value and can be used for an object oriented style of programming.)
- Is partial application possible and how
There is no special syntax for that, but you can write a function that e.g., can take a list with one or with two elements and that returns a function in the first case.
( ( plus
= a b
. !arg:%?a ?b
& !b:
& '(.!arg+$a)
| !a+!b
)
& out$("1+2, not partial:" plus$(1 2))
& out$("1+2, partial:" (plus$1)$2)
);
Output:
1+2, not partial: 3 1+2, partial: 3
C
/* function with no argument */
f();
/* fix number of arguments */
g(1, 2, 3);
/* Optional arguments: err...
Feel free to make sense of the following. I can't. */
int op_arg();
int main()
{
op_arg(1);
op_arg(1, 2);
op_arg(1, 2, 3);
return 0;
}
int op_arg(int a, int b)
{
printf("%d %d %d\n", a, b, (&b)[1]);
return a;
} /* end of sensible code */
/* Variadic function: how the args list is handled solely depends on the function */
void h(int a, ...)
{
va_list ap;
va_start(ap);
...
}
/* call it as: (if you feed it something it doesn't expect, don't count on it working) */
h(1, 2, 3, 4, "abcd", (void*)0);
/* named arguments: this is only possible through some pre-processor abuse
*/
struct v_args {
int arg1;
int arg2;
char _sentinel;
};
void _v(struct v_args args)
{
printf("%d, %d\n", args.arg1, args.arg2);
}
#define v(...) _v((struct v_args){__VA_ARGS__})
v(.arg2 = 5, .arg1 = 17); // prints "17,5"
/* NOTE the above implementation gives us optional typesafe optional arguments as well (unspecified arguments are initialized to zero)*/
v(.arg2=1); // prints "0,1"
v(); // prints "0,0"
/* as a first-class object (i.e. function pointer) */
printf("%p", f); /* that's the f() above */
/* return value */
double a = asin(1);
/* built-in functions: no such thing. Compiler may interally give special treatment
to bread-and-butter functions such as memcpy(), but that's not a C built-in per se */
/* subroutines: no such thing. You can goto places, but I doubt that counts. */
/* Scalar values are passed by value by default. However, arrays are passed by reference. */
/* Pointers *sort of* work like references, though. */
C#
/* a function that has no argument */
public int MyFunction();
/* a function with a fixed number of arguments */
FunctionWithArguments(4, 3, 2);
/* a function with optional arguments */
public void OptArg();
public static void Main()
{
OptArg(1);
OptArg(1, 2);
OptArg(1, 2, 3);
}
public void ExampleMethod(int required,
string optionalstr = "default string",
int optionalint = 10)
/* If you know the first and the last parameter */
ExampleMethod(3, optionalint: 4);
/* If you know all the parameter */
ExampleMethod(3, "Hello World", 4);
/* Variable number of arguments use array */
public static void UseVariableParameters(params int[] list)
/* Obtain return value from function */
public internal MyFunction();
int returnValue = MyFunction();
C++
/* function with no arguments */
foo();
/* passing arguments by value*/
/* function with one argument */
bar(arg1);
/* function with multiple arguments */
baz(arg1, arg2);
/* get return value of a function */
variable = function(args);
#include <iostream>
using namespace std;
/* passing arguments by reference */
void f(int &y) /* variable is now passed by reference */
{
y++;
}
int main()
{
int x = 0;
cout<<"x = "<<x<<endl; /* should produce result "x = 0" */
f(x); /* call function f */
cout<<"x = "<<x<<endl; /* should produce result "x = 1" */
}
Clojure
Note: I ran all these examples in the REPL so there is no printed output; instead I have denoted the value of each expression evaluated using `;=>'.
Calling a function that requires no arguments
(defn one []
"Function that takes no arguments and returns 1"
1)
(one); => 1
Calling a function with a fixed number of arguments
(defn total-cost [item-price num-items]
"Returns the total price to buy the given number of items"
(* item-price num-items))
(total-cost 1 5); => 5
Calling a function with optional arguments The syntax is exactly the same for the calling code; here's an example of the exact same function as above, except now it takes an optional third argument (discount-percentage)
(defn total-cost-with-discount [item-price num-items & [discount-percentage]]
"Returns total price to buy the items after discount is applied (if given)"
(let [discount (or discount-percentage 0)] ;; Assign discount to either the discount-percentage (if given) or default 0 if not
(-> item-price
(* num-items) ;; Calculate total cost
(* (- 100 discount)) ;; Apply discount
(/ 100.0))))
;; Now we can use the function without the optional arguments, and see the same behaviour as our total-cost function
(total-cost-with-discount 1 5); => 5
;; Or we can add the third parameter to calculate the cost with 20% discount
(total-cost-with-discount 1 5 20); => 4
Calling a function with a variable number of arguments You can use the optional argument syntax seen above to implement variable numbers, but here's another way to do it by writing multiple functions with different arguments all in one.
Once again, calling the function is the same, but you need to know what types of arguments are expected for each arity.
(defn make-address
([city place-name] (str place-name ", " city))
([city street house-number] (str house-number " " street ", " city))
([city street house-number apartment] (str house-number " " street ", Apt. " apartment ", " city)))
;; To call the function you just need to pass whatever arguments you are supplying as you would with a fixed number
;; First case- the queen doesn't need a street name
(make-address "London" "Buckingham Palace"); => "Buckingham Palace, London"
;; Second case
(make-address "London" "Downing Street" 10); => "10 Downing Street, London"
;; Third case
(make-address "London" "Baker Street" 221 "B"); => "221 Baker Street, Apt. B, London"
Calling a function with named arguments The way to do this in clojure is to pass the arguments as a map and destructure them by name in the function definition. The syntax is the same, but it requires you to pass a single map argument containing all of your arguments and their names.
(defn make-mailing-label [{:keys [name address country]}]
"Returns the correct text to mail a letter to the addressee"
(str name "\n" address "\n" (or country "UK"))) ;; If country is nil, assume it is the UK
;; We can call it with all three arguments in a map to get mickey's international address
(make-mailing-label {:name "Mickey Mouse"
:address "1 Disney Avenue, Los Angeles"
:country "USA"}); => "Mickey Mouse\n1 Disney Avenue, Los Angeles\nUSA"
;; Or we can call it with fewer arguments for domestic mail
(make-mailing-label {:name "Her Majesty"
:address "Buckingham Palace, London"}); => "Her Majesty\nBuckingham Palace, London\nUK"
Using a function in statement context I'm not really sure what this means - you can use a function to assign a variable, but there aren't really statements
(defn multiply-by-10 [number]
(* 10 number))
(def fifty (multiply-by-10 5))
fifty; => 50
Using a function in first-class context within an expression
Functions are always first-class, here are some examples of how they can be used in first class context:
You can use one function to create another
(defn make-discount-function [discount-percent]
"Returns a function that takes a price and applies the given discount"
(fn [price] (-> price
(* (- 100 discount-percent))
(/ 100.0))))
;; Now we can create a '20% off' function to calculate prices with your discount card
(def discount-20pc (make-discount-function 20))
;; Use the function to calculate some discount prices
(discount-20pc 100); => 80
(discount-20pc 5); => 4
;; Your friend has a better discount card, we can use the same function to create their discount card function
(def discount-50pc (make-discount-function 50))
(discount-50pc 100); => 50
(discount-50pc 5); => 2.5
You can store functions in collections as if they were variables
;; Continuing on the same example, let's imagine Anna has a 20% discount card and Bill has 50%. Charlie pays full price
;; We can store their discount functions in a map
(def discount-cards {"Anna" discount-20pc
"Bill" discount-50pc
"Charlie" identity}) ;; Identity returns whatever value was passed to the function (in this case it will be price)
;; Now we can access them by cardholder name in another function
(defn calculate-discounted-price [price shopper-name]
"Applies the correct discount for the person"
(let [discount-fn (get discount-cards shopper-name)] ;; Get the right discount function
(discount-fn price))) ;; Apply discount function to the price
(calculate-discounted-price 100 "Anna"); => 80
(calculate-discounted-price 100 "Bill"); => 50
(calculate-discounted-price 100 "Charlie"); => 100
You can pass functions as arguments to other functions
;; Here we have two functions to format a price depending on the country
(defn format-price-uk [price]
(str "£" price))
(defn format-price-us [price]
(str "$" price))
;; And one function that takes a price formatting function as an argument
(defn format-receipt [item-name price price-formatting-function]
"Return the item name and price formatted according to the function"
(str item-name
" "
(price-formatting-function price))) ;; Call the format function to get the right representation of the price
(format-receipt "Loo Roll" 5 format-price-uk); => "Loo Roll £5"
(format-receipt "Toilet Paper" 5 format-price-us); => "Toilet Paper $5"
Obtaining the return value of a function
;;You can assign it to a variable:
(def receipt-us (format-receipt "Toilet Paper" 5 format-price-us))
;; Then the variable holds the value
receipt-us; => "Toilet Paper $5"
;; Or you can use it in a call to another function
(defn add-store-name [receipt]
"A function to add a footer to the receipt"
(str receipt "\n Thanks for shopping at Safeway" ))
;; Calls add-store-name with the result of the format function
(add-store-name (format-receipt "Toilet Paper" 5 format-price-us)); => "Toilet Paper $5\n Thanks for shopping at Safeway"
Distinguishing built-in functions and user-defined functions
;; They are indistinguishable in Clojure, and you can even override a built in one
;; Using built-in addition
(+ 5 5); => 10
;; Using custom defined addition
(defn ? [a b]
"Returns the sum of two numbers"
(+ a b))
(? 5 5); => 10
;; Overriding a built in function is possible but not recommended
(defn * [a b] ;; Redefining the multiplication operator
"Returns the sum of two numbers"
(+ a b))
(* 5 5); => 10
Distinguishing subroutines and functions
;; They are the same thing - indeed, everything in clojure is a function
;; Functions without return values simply return nil
(defn no-return-value [a]
(print (str "Your argument was" a "; now returning nil")))
(no-return-value "hi"); => nil
Stating whether arguments are passed by value or by reference All data structures are immutable, so they are passed by value only. The value returned from the function does not change the original input
;; Set up a variable that we will pass to a function
(def the-queen {:name "Elizabeth"
:title "Your Majesty"
:address "Buckingham Palace"
:pets ["Corgi" "Horse"]})
;; A function to modify the data
(defn adopt-pet [person pet]
"Adds pet to the person's list of pets"
(update person
:pets
#(conj % pet)))
;; Calling the function returns a new data structure with the modified pets
(adopt-pet the-queen "Ferret"); => {:name "Elizabeth":title "Your Majesty" :address "Buckingham Palace" :pets ["Corgi" "Horse" "Ferret]}
;; The original data structure is not changed
the-queen; => {:name "Elizabeth" :title "Your Majesty" :address "Buckingham Palace" :pets ["Corgi" "Horse"]}
Is partial application possible and how
Yes, it is similar to the discount card case we saw earlier. Instead of having a function return another function, we can use partial:
(defn apply-discount [discount-percentage price]
"Function to apply a discount to a price"
(-> price
(* (- 100 discount-percentage)) ;; Apply discount
(/ 100.0)))
;; Here we have assigned the variable to a partial function
;; It means 'call apply-discount with 10 as the first argument'
(def discount-10pc-option-1 (partial apply-discount 10))
;; And is equivalent to this:
(defn discount-10pc-option-2 [price]
(apply-discount 10 price))
(discount-10pc-option-1 100); => 90
(discount-10pc-option-2 100); => 90
COBOL
CALL "No-Arguments"
*> Fixed number of arguments.
CALL "2-Arguments" USING Foo Bar
CALL "Optional-Arguments" USING Foo
CALL "Optional-Arguments" USING Foo Bar
*> If an optional argument is omitted and replaced with OMITTED, any following
*> arguments can still be specified.
CALL "Optional-Arguments" USING Foo OMITTED Bar
*> Interestingly, even arguments not marked as optional can be omitted without
*> a compiler warning. It is highly unlikely the function will still work,
*> however.
CALL "2-Arguments" USING Foo
*> COBOL does not support a variable number of arguments, or named arguments.
*> Values to return can be put in either one of the arguments or, in OpenCOBOL,
*> the RETURN-CODE register.
*> A standard function call cannot be done in another statement.
CALL "Some-Func" USING Foo
MOVE Return-Code TO Bar
*> Intrinsic functions can be used in any place a literal value may go (i.e. in
*> statements) and are optionally preceded by FUNCTION.
*> Intrinsic functions that do not take arguments may optionally have a pair of
*> empty parentheses.
*> Intrinsic functions cannot be defined by the user.
MOVE FUNCTION PI TO Bar
MOVE FUNCTION MEDIAN(4, 5, 6) TO Bar
*> Built-in functions/subroutines typically have prefixes indicating which
*> compiler originally incorporated it:
*> - C$ - ACUCOBOL-GT
*> - CBL_ - Micro Focus
*> - CBL_OC_ - OpenCOBOL
*> Note: The user could name their functions similarly if they wanted to.
CALL "C$MAKEDIR" USING Foo
CALL "CBL_CREATE_DIR" USING Foo
CALL "CBL_OC_NANOSLEEP" USING Bar
*> Although some built-in functions identified by numbers.
CALL X"F4" USING Foo Bar
*> Parameters can be passed in 3 different ways:
*> - BY REFERENCE - this is the default way in OpenCOBOL and this clause may
*> be omitted. The address of the argument is passed to the function.
*> The function is allowed to modify the variable.
*> - BY CONTENT - a copy is made and the function is passed the address
*> of the copy, which it can then modify. This is recomended when
*> passing a literal to a function.
*> - BY VALUE - the function is passed the address of the argument (like a
*> pointer). This is mostly used to provide compatibility with other
*> languages, such as C.
CALL "Modify-Arg" USING BY REFERENCE Foo *> Foo is modified.
CALL "Modify-Arg" USING BY CONTENT Foo *> Foo is unchanged.
CALL "C-Func" USING BY VALUE Bar
*> Partial application is impossible as COBOL does not support first-class
*> functions.
*> However, as functions are called using a string of their PROGRAM-ID,
*> you could pass a 'function' as an argument to another function, or store
*> it in a variable, or get it at runtime.
ACCEPT Foo *> Get a PROGRAM-ID from the user.
CALL "Use-Func" USING Foo
CALL Foo USING Bar
CoffeeScript
# Calling a function that requires no arguments
foo()
# Calling a function with a fixed number of arguments
foo 1
# Calling a function with optional arguments
# (Optional arguments are done using an object with named keys)
foo 1, optionalBar: 1, optionalBaz: 'bax'
# Calling a function with a variable number of arguments
# for a function `foo` defined as `foo = ( args... ) ->`
foo 1, 2, 3, 4
# Calling a function with named arguments
# (Named arguments are done using an object with named keys)
foo bar: 1, bax: 'baz'
# Using a function in statement context
x = foo 1
# Using a function in first-class context within an expression
# (For `foo` defined as `foo = ( x ) -> x + 1`
x = [ 1, 2, 3 ].map foo
# Obtaining the return value of a function
x = foo 1
# Arguments are passed by value, even objects. Objects
# are passed as the _value_ of the reference to an object.
# Example:
bar = ( person ) ->
# Since `person` is a reference
# to the person passed in, we can assign
# a new value to its `name` key.
person.name = 'Bob'
# Since `person` is just the value of
# the original reference, assigning to it
# does not modify the original reference.
person = new Person 'Frank'
# Partial application is only possible manually through closures
curry = ( f, fixedArgs... ) ->
( args... ) -> f fixedArgs..., args...
# Example usage
add = ( x, y ) -> x + y
add2 = curry add, 2
add2 1 #=> 3
Common Lisp
;Calling a function that requires no arguments
(defun a () "This is the 'A' function")
(a)
;Calling a function with a fixed number of arguments
(defun b (x y) (list x y))
(b 1 2)
;Calling a function with optional arguments
(defun c (&optional x y) (list x y))
(c 1)
;Calling a function with a variable number of arguments
(defun d (&rest args) args)
(d 1 2 3 4 5 6 7 8)
;Calling a function with named arguments
(defun e (&key (x 1) (y 2)) (list x y))
(e :x 10 :y 20)
;Using a function in first-class context within an expression
(defun f (func) (funcall func))
(f #'a)
;Obtaining the return value of a function
(defvar return-of-a (a))
;Is partial application possible and how
(defun curry (function &rest args-1)
(lambda (&rest args-2)
(apply function (append args-1 args-2))))
(funcall (curry #'+ 1) 2)
Cubescript
// No arguments
myfunction
// All functions can take a variable number of arguments.
// These can be accessed from within the function with the aliases:
// $arg1, $arg2, $arg3... $numargs tells the amount of args passed.
myfunction word "text string" 1 3.14
// Getting a function's return value
retval = (myfunction)
// Trying to do a variable lookup on a builtin function will return an empty
// string. This can be used to distinguish builtin functions from user-defined
// ones.
if (strcmp $echo "") [echo builtin function] // true
if (strcmp $myfunction "") [echo builtin function] // false
D
import std.traits;
enum isSubroutine(alias F) = is(ReturnType!F == void);
void main() {
void foo1() {}
// Calling a function that requires no arguments:
foo1();
foo1; // Alternative syntax.
void foo2(int x, int y) {}
immutable lambda = function int(int x) => x ^^ 2;
// Calling a function with a fixed number of arguments:
foo2(1, 2);
foo2(1, 2);
cast(void)lambda(1);
void foo3(int x, int y=2) {}
// Calling a function with optional arguments:
foo3(1);
foo3(1, 3);
int sum(int[] arr...) {
int tot = 0;
foreach (immutable x; arr)
tot += x;
return tot;
}
real sum2(Args...)(Args arr) {
typeof(return) tot = 0;
foreach (immutable x; arr)
tot += x;
return tot;
}
// Calling a function with a variable number of arguments:
assert(sum(1, 2, 3) == 6);
assert(sum(1, 2, 3, 4) == 10);
assert(sum2(1, 2.5, 3.5) == 7);
// Calling a function with named arguments:
// Various struct or tuple-based tricks can be used for this,
// but currently D doesn't have named arguments.
// Using a function in statement context (?):
if (1)
foo1;
// Using a function in first-class context within an expression:
assert(sum(1) == 1);
auto foo4() { return 1; }
// Obtaining the return value of a function:
immutable x = foo4;
// Distinguishing built-in functions and user-defined functions:
// There are no built-in functions, beside the operators, and
// pseudo-functions like assert().
int myFynction(int x) { return x; }
void mySubroutine(int x) {}
// Distinguishing subroutines and functions:
// (A subroutine is merely a function that has no explicit
// return statement and will return void).
pragma(msg, isSubroutine!mySubroutine); // Prints: true
pragma(msg, isSubroutine!myFynction); // Prints: false
void foo5(int a, in int b, ref int c, out int d, lazy int e, scope int f) {}
// Stating whether arguments are passed by value, by reference, etc:
alias STC = ParameterStorageClass;
alias psct = ParameterStorageClassTuple!foo5;
static assert(psct.length == 6); // Six parameters.
static assert(psct[0] == STC.none);
static assert(psct[1] == STC.none);
static assert(psct[2] == STC.ref_);
static assert(psct[3] == STC.out_);
static assert(psct[4] == STC.lazy_);
static assert(psct[5] == STC.scope_);
// There are also inout and auto ref.
int foo6(int a, int b) { return a + b; }
// Is partial application possible and how:
import std.functional;
alias foo6b = partial!(foo6, 5);
assert(foo6b(6) == 11);
}
- Output:
true false
Dart
void main() {
// Function definition
// See the "Function definition" task for more info
void noArgs() {}
void fixedArgs(int arg1, int arg2) {}
void optionalArgs([int arg1 = 1]) {}
void namedArgs({required int arg1}) {}
int returnsValue() {return 1;}
// Calling a function that requires no arguments
noArgs();
// Calling a function with a fixed number of arguments
fixedArgs(1, 2);
// Calling a function with optional arguments
optionalArgs();
optionalArgs(2);
// Calling a function with named arguments
namedArgs(arg1: 1);
// Using a function in statement context
if (true) {
noArgs();
}
// Obtaining the return value of a function
var value = returnsValue();
}
Delphi
Delphi allows everything what Pascal allows. In addition, the following is also possible:
Calling a function without arguments and obtaining its return value:
foo()
Calling a function with optional arguments:
foo(1)
Calling a function with a variable number of arguments:
foo(1, 2, 3, 4, 5)
Using a function in a statement context:
writeLn('Hello world.');
foo;
writeLn('Goodbye world')
Like above, an empty parameter list, i. e. (), could be supplied too.
Dragon
- Calling a function that requires no arguments
myMethod()
- Calling a function with a fixed number of arguments
myMethod(97, 3.14)
Dyalect
Calling a function that requires no arguments:
func foo() { }
foo()
Calling a function with a fixed number of arguments:
func foo(x, y, z) { }
foo(1, 2, 3)
Calling a function with optional arguments:
func foo(x, y = 0, z = 1) { }
foo(1)
Calling a function with a variable number of arguments:
func foo(args...) { }
foo(1, 2, 3)
Calling a function with named arguments:
func foo(x, y, z) { }
foo(z: 3, x: 1, y: 2)
Using a function in statement context:
func foo() { }
if true {
foo()
}
Using a function in first-class context within an expression:
func foo() { }
var x = if foo() {
1
} else {
2
}
Obtaining the return value of a function:
func foo(x) { x * 2 }
var x = 2
var y = foo(x)
Distinguishing built-in functions and user-defined functions:
//Built-in functions are regular functions from an implicitly imported "lang" module
//There is no actual difference between these functions and user-defined functions
//You can however write a function that would check if a given function is declared in "lang" module:
func isBuiltin(fn) =>
fn.Name is not nil && fn.Name in lang && lang[fn.Name] == fn
//Usage:
func foo() { } //A user-defined function
print(isBuiltin(foo)) //Prints: false
print(isBuiltin(assert)) //Prints: true
Distinguishing subroutines and functions:
//There is no difference between subroutines and functions:
func foo() { } //doesn't explicitly return something (but in fact returns nil)
func bar(x) { return x * 2 } //explicitly returns value (keyword "return" can be omitted)
Stating whether arguments are passed by value or by reference:
//All arguments are passed by reference
Is partial application possible and how:
//Using a closure:
func apply(fun, fst) { snd => fun(fst, snd) }
//Usage:
func sum(x, y) { x + y }
var sum2 = apply(sum, 2)
var x = sum2(3) //x is 5
//By second argument
func flip(fun) { (y, x) => fun(x, y) }
func sub(x, y) { x - y }
var sub3 = apply(flip(sub), 3)
x = sub3(9) //x is 6
Déjà Vu
# all functions used are from the standard library
# calling a function with no arguments:
random-int
# calling a function with a fixed number of arguments:
+ 1 2
# calling a function with optional arguments:
# optional arguments are not really possible as such
# generally differently named functions are used:
sort [ 3 2 1 ]
sort-by @len [ "Hello" "World" "Bob" ]
# calling a function with a variable number of arguments:
# generally with a special terminator value, which one depends
# on the function called
concat( 1 2 3 )
[ 1 2 3 ]
set{ :foo :bar :spam }
# calling a function with named arguments: not possible
# using a function in first-class context within an expression
$ @-- @len # $ is "compose", so the function returned is "one less than the length"
# obtaining the return value of a function
# return values are always pushed on the stack, so you don't need anything special
random-int
# discarding the return value of a function
drop random-int
# method call:
local :do { :nuthin @pass }
do!nuthin
!import!fooModule # same as eva!import :fooModule
# arguments are passed by object-identity, like in Python and Lua
# partial application is not possible, due to the fact that
# a function's arity is a property of its behavior and not
# of its definition
EasyLang
func sqr n .
return n * n
.
print sqr 3
#
proc divmod a b . q r .
q = a div b
r = a mod b
.
divmod 11 3 q r
print q & " " & r
#
subr sqr2
a = a * a
.
a = 5
sqr2
print a
Ecstasy
Calling a function that requires no arguments:
foo(); // <-- this is "invoking a function in statement context"
Int x = bar(); // <-- this is "invoking a function in expression context"
Calling a function with a fixed number of arguments:
foo(1, 2, 3);
Int x = bar(4, 5, 6);
Calling a function with optional arguments:
module CallOptArgsFunc {
static Int foo(Int a=0, Int b=99, Int c=-1) {
return a + b + c;
}
void run() {
@Inject Console console;
console.print($"{foo()=}");
console.print($"{foo(1)=}");
console.print($"{foo(1, 2)=}");
console.print($"{foo(1, 2, 3)=}");
}
}
- Output:
foo()=98 foo(1)=99 foo(1, 2)=2 foo(1, 2, 3)=6
Calling a function with a variable number of arguments:
module CallVarArgsFunc {
// Ecstasy does not have a var-args concept; instead, array notation is used
static Int foo(Int[] args = []) {
return args.size;
}
void run() {
@Inject Console console;
console.print($"{foo()=}");
console.print($"{foo([])=}");
console.print($"{foo([1])=}");
console.print($"{foo([1, 2])=}");
console.print($"{foo([1, 2, 3])=}");
}
}
- Output:
foo()=0 foo([])=0 foo([1])=1 foo([1, 2])=2 foo([1, 2, 3])=3
Calling a function with named arguments:
module CallNamedArgsFunc {
static String foo(Int a=1, Int b=2, Int c=3) {
return $"a:{a}, b:{b}, c:{c}";
}
void run() {
@Inject Console console;
console.print($"{foo(c=9, b=8, a=7)=}");
console.print($"{foo(4, c=6, b=5)=}");
console.print($"{foo(c=99)=}");
}
}
- Output:
foo(c=9, b=8, a=7)=a:7, b:8, c:9 foo(4, c=6, b=5)=a:4, b:5, c:6 foo(c=99)=a:1, b:2, c:99
Using a function in first-class context within an expression: Functions are always first class in Ecstasy; everything (including classes, types, methods, properties, functions, variables, etc.) is an object.
module FirstClassFunctions {
@Inject Console console;
void run() {
function Int(String) stringLen = s -> s.size;
function Int(Int, Int) sum = (n1, n2) -> n1+n2;
String[] testData = ["abc", "easy", "as", "123"];
console.print($|total string length of values in {testData} =\
| {testData.map(stringLen).reduce(0, sum)}
);
}
}
- Output:
total string length of values in [abc, easy, as, 123] = 12
Obtaining the return value of a function:
module ObtainReturnValues {
(Int, String, Dec) foo() {
return 3, "hello!", 9.87;
}
void run() {
foo(); // ignore return values
Int i1 = foo(); // only use first returned value
(Int i2, String s2) = foo(); // only use first two returned values
(Int i3, String s3, Dec d3) = foo(); // use all returned values
Tuple<Int, String, Dec> t = foo(); // alternatively, get the tuple instead
@Inject Console console;
console.print($"{i3=}, {s3=}, {d3=}, {t=}");
}
}
- Output:
i3=3, s3=hello!, d3=9.87, t=(3, hello!, 9.87)
Distinguishing built-in functions and user-defined functions:
// Ecstasy does not have any built-in functions. However, there are two keywords
// ("is" and "as") that use a function-like syntax:
module IsAndAs {
Int|String foo() {
return "hello";
}
void run() {
@Inject Console console;
Object o = foo();
if (o.is(String)) { // <- looks like a function call
String s = o.as(String); // <- looks like a function call
console.print($"foo returned the string: {s.quoted()}");
}
}
}
- Output:
foo returned the string: "hello"
Distinguishing subroutines and functions: There is no such thing as a subroutine in Ecstasy. There are only methods (virtual functions with a "this"), functions, and object constructors.
Stating whether arguments are passed by value or by reference: Ecstasy does not specify whether arguments are passed by value or by reference. However, since all Ecstasy types are conceptually reference types, the behavior is defined as if all arguments are references passed by value; this is the same model used by Java for all of its reference types.
Is partial application possible and how:
module PartialApplication {
void foo(String s, Int i, Dec d) {
@Inject Console console;
console.print($"inside call to foo({s=}, {i=}, {d=})");
}
void run() {
// note that the "&" obtains the reference to the function, and suppresses the
// invocation thereof, so it is *allowed* in all three of these cases, but it
// is *required* in the third case:
function void(String, Int, Dec) unbound = foo; // or "foo(_, _, _)"
function void(String, Dec) partBound = unbound(_, 99, _);
function void() allBound = &partBound("world", 3.14);
unbound("nothing", 0, 0.0);
partBound("hello", 2.718);
allBound();
}
}
- Output:
inside call to foo(s=nothing, i=0, d=0) inside call to foo(s=hello, i=99, d=2.718) inside call to foo(s=world, i=99, d=3.14)
Elena
ELENA 4.1: Declaring closures
var c0 := { console.writeLine("No argument provided") };
var c2 := (int a, int b){ console.printLine("Arguments ",a," and ",b," provided") };
Calling a closure without arguments
c0();
Calling a closure with arguments
c2(2,4);
Passing arguments by reference:
var exch := (ref object x){ x := 2 };
var a := 1;
exch(ref a);
Elixir
# Anonymous function
foo = fn() ->
IO.puts("foo")
end
foo() #=> undefined function foo/0
foo.() #=> "foo"
# Using `def`
defmodule Foo do
def foo do
IO.puts("foo")
end
end
Foo.foo #=> "foo"
Foo.foo() #=> "foo"
# Calling a function with a fixed number of arguments
defmodule Foo do
def foo(x) do
IO.puts(x)
end
end
Foo.foo("foo") #=> "foo"
# Calling a function with a default argument
defmodule Foo do
def foo(x \\ "foo") do
IO.puts(x)
end
end
Foo.foo() #=> "foo"
Foo.foo("bar") #=> "bar"
# There is no such thing as a function with a variable number of arguments. So in Elixir, you'd call the function with a list
defmodule Foo do
def foo(args) when is_list(args) do
Enum.each(args, &(IO.puts(&1)))
end
end
# Calling a function with named arguments
defmodule Foo do
def foo([x: x]) do
IO.inspect(x)
end
end
EMal
fun task = void by text about, fun code
writeLine(0U00b7 + " " + about)
code()
end
fun answer = void by var message do writeLine(" " + message) end
# few definitions
fun noArgumentsFunction = int by block do return 97 end
fun fixedArgumentsFunction = void by var a, var b do end
fun variadicFunction = void by text a, some var values do end
fun funArgumentFunction = var by fun f, var b do return f() + b end
task("Calling a function that requires no arguments", void by block
answer("Is supported.")
noArgumentsFunction()
end)
task("Calling a function with a fixed number of arguments", void by block
answer("Is supported.")
fixedArgumentsFunction(97, 3.14)
end)
task("Calling a function with optional arguments", void by block
answer("Not supported in EMal.")
end)
task("Calling a function with a variable number of arguments", void by block
answer("Variadic functions are supported.")
variadicFunction("mandatory", 97, 3.14)
variadicFunction("mandatory", 97)
end)
task("Calling a function with named arguments", void by block
answer("Not supported in EMal.")
end)
task("Using a function in statement context", void by block
answer("Is supported.")
if true do noArgumentsFunction()
else do fixedArgumentsFunction(97, 3.14) end
end)
task("Using a function in first-class context within an expression", void by block
answer("Functions are first class, can be passed as arguments and returned.")
answer(funArgumentFunction(noArgumentsFunction, 3.14))
end)
task("Obtaining the return value of a function", void by block
answer("Is supported.")
int value = noArgumentsFunction()
answer(value)
end)
task("Distinguishing built-in functions and user-defined functions", void by block
answer("No distinction.")
end)
task("Distinguishing subroutines and functions", void by block
answer("No distinction, we support void return type.")
end)
task("Stating whether arguments are passed by value or by reference", void by block
answer("Pass by value, but text, blob, objects hold a reference.")
end)
task("Is partial application possible and how", void by block
answer("Is supported.")
^|I had some confusion about partial application and currying, thanks to these links:
| https://stackoverflow.com/questions/218025/what-is-the-difference-between-currying-and-partial-application
| https://web.archive.org/web/20161023205431/http://www.uncarved.com/articles/not_curryin
|^
# Partial applying
fun add = int by int a, int b do return a + b end
fun partial = fun by fun f, int a
return int by int b
return add(a, b)
end
end
fun add7 = partial(add, 7)
answer(add(7, 5))
answer(add7(5))
# Currying
fun addN = fun by int n
return int by int x
return x + n
end
end
fun plus = int by int a, int b
fun addA = addN(a)
return addA(b)
end
answer(plus(7, 5))
end)
- Output:
· Calling a function that requires no arguments Is supported. · Calling a function with a fixed number of arguments Is supported. · Calling a function with optional arguments Not supported in EMal. · Calling a function with a variable number of arguments Variadic functions are supported. · Calling a function with named arguments Not supported in EMal. · Using a function in statement context Is supported. · Using a function in first-class context within an expression Functions are first class, can be passed as arguments and returned. 100.14 · Obtaining the return value of a function Is supported. 97 · Distinguishing built-in functions and user-defined functions No distinction. · Distinguishing subroutines and functions No distinction, we support void return type. · Stating whether arguments are passed by value or by reference Pass by value, but text, blob, objects hold a reference. · Is partial application possible and how Is supported. 12 12 12
Erlang
no_argument()
one_argument( Arg )
optional_arguments( Arg, [{opt1, Opt1}, {another_opt, Another}] )
variable_arguments( [Arg1, Arg2 | Rest] )
names_arguments([{name1, Arg1}, {another_name, Another}] )
% Statement context?
% First class context?
Result = obtain_result( Arg1 )
% No way to distinguish builtin/user functions
% Subroutines?
% Arguments are passed by reference, but you can not change them.
% Partial application is possible (a function returns a function that has one argument bound)
F#
// No arguments
noArgs()
// Fixed number of arguments
oneArg x
// Optional arguments
// In a normal function:
optionalArgs <| Some(5) <| None
// In a function taking a tuple:
optionalArgsInTuple(Some(5), None)
// In a function in a type:
foo.optionalArgs 5;;
// However, if you want to pass more than one paramter, the arguments must be
// passed in a tuple:
foo.optionalArgs(5, 6)
// Function with a variable number of arguments
variableArgs 5 6 7 // etc...
// Named arguments can only be used in type methods taking a tuple. The
// arguments can appear in any order.
foo.namedArgs(x = 5, y = 6)
// Using a function in a statement
for i = 0 to someFunc() do
printfn "Something"
// Using a function in a first-class context
funcArgs someFunc
// Obtaining a return value
let x = someFunc()
// Built-in functions: do functions like (+) or (-) count?
// Parameters are normally passed by value (as shown in the previous examples),
// but they can be passed by reference.
// Passing by reference:
refArgs &mutableVal
// Partial application example
let add2 = (+) 2
Factor
- Calling a word with no arguments:
foo
- Calling a word with a fixed number of arguments. This will pull as many objects as it needs from the stack. If there are not enough, it will result in a stack underflow.
foo
- No special support for optional arguments.
- Variable arguments are achieved by defining a word that takes an integer, and operates on that many items at the top of the stack:
"a" "b" "c" 3 narray
! { "a" "b" "c" }
- The named arguments idiom is to define a tuple, set its slots, and pass it to a word:
<email>
"jack@aol.com" >>from
{ "jill@aol.com" } >>to
"Hello there" >>subject
body >>body
send-email
- First-class context: this pushes a word to the stack. Use execute to evaluate.
\ foo
Additionally, you can put words directly inside sequences and quotations for deferred execution:
{ foo } [ foo ]
- Obtaining the return value, which will be placed on the stack:
foo
- Returns true if the word is defined in the Factor VM as opposed to in a vocabulary. It should be noted that there are very few primitives.
\ foo primitive?
- Factor makes no distinction between subroutines and functions.
- It's not perfectly accurate to think of words as passing arguments by reference (or at all), since all words simply operate on the data stack. However, it is still important for the programmer to understand that words which make duplicates of objects such as dup and over do so by copying references. If one wishes for a shallow copy of a non-immediate object, one may use clone.
- Partial application is possible by use of curry. Here, the object 2 is curried into the left side of the quotation (anonymous function) [ - ]:
{ 1 2 3 } 2 [ - ] curry map .
! { -1 0 1 }
Forth
a-function \ requiring no arguments
a-function \ with a fixed number of arguents
a-function \ having optional arguments
a-function \ having a variable number of arguments
a-function \ having such named arguments as we have in Forth
' a-function var ! \ using a function in a first-class context (here: storing it in a variable)
a-function \ in which we obtain a function's return value
\ forth lacks 'statement contenxt'
\ forth doesn't distinguish between built-in and user-defined functions
\ forth doesn't distinguish between functions and subroutines
\ forth doesn't care about by-value or by-reference
\ partial application is achieved by creating functions and manipulating stacks
: curried 0 a-function ;
: only-want-third-argument 1 2 rot a-function ;
\ Realistic example:
: move ( delta-x delta-y -- )
y +! x +! ;
: down ( n -- ) 0 swap move ;
: up ( n -- ) negate down ;
: right ( n -- ) 0 move ;
: left ( n -- ) negate right ;
Fortran
Examples
program main
implicit none
integer :: a
integer :: f, g
logical :: lresult
interface
integer function h(a,b,c)
integer :: a, b
integer, optional :: c
end function
end interface
write(*,*) 'no arguments: ', f()
write(*,*) '-----------------'
write(*,*) 'fixed arguments: ', g(5,8,lresult)
write(*,*) '-----------------'
write(*,*) 'optional arguments: ', h(5,8), h(5,8,4)
write(*,*) '-----------------'
write(*,*) 'function with variable arguments: Does not apply!'
write(*,*) 'An option is to pass arrays of variable lengths.'
write(*,*) '-----------------'
write(*,*) 'named arguments: ', h(c=4,b=8,a=5)
write(*,*) '-----------------'
write(*,*) 'function in statement context: Does not apply!'
write(*,*) '-----------------'
write(*,*) 'Fortran passes memory location of variables as arguments.'
write(*,*) 'So an argument can hold the return value.'
write(*,*) 'function result: ', g(5,8,lresult) , ' function successful? ', lresult
write(*,*) '-----------------'
write(*,*) 'Distinguish between built-in and user-defined functions: Does not apply!'
write(*,*) '-----------------'
write(*,*) 'Calling a subroutine: '
a = 30
call sub(a)
write(*,*) 'Function call: ', f()
write(*,*) '-----------------'
write(*,*) 'All variables are passed as pointers.'
write(*,*) 'Problems can arise if instead of sub(a), one uses sub(10).'
write(*,*) '-----------------'
end program
!no argument
integer function f()
f = 10
end function
!fixed number of arguments
integer function g(a, b, lresult)
integer :: a, b
logical :: lresult
g = a+b
lresult = .TRUE.
end function
!optional arguments
integer function h(a, b, c)
integer :: a, b
integer, optional :: c
h = a+b
if(present(c)) then
h = h+10*c
end if
end function
!subroutine
subroutine sub(a)
integer :: a
a = a*100
write(*,*) 'Output of subroutine: ', a
end subroutine
no arguments: 10 ----------------- fixed arguments: 13 ----------------- optional arguments: 13 53 ----------------- function with variable arguments: Does not apply! An option is to pass arrays of variable lengths. ----------------- named arguments: 53 ----------------- function in statement context: Does not apply! ----------------- Fortran passes memory location of variables as arguments. So an argument can hold the return value. function result: 13 function successful? T ----------------- Distinguish between built-in and user-defined functions: Does not apply! ----------------- Calling a subroutine: Output of subroutine: 3000 Function call: 10 ----------------- All variables are passed as pointers. Problems can arise if instead of sub(a), one uses sub(10). -----------------
In other words
As described in Naming Conventions, First Fortran (1958) allowed user-written functions but with restrictions on the names so that an ordinary variable called SIN would be disallowed because it was deemed to be in conflict with the library function SINF. These constraints were eased with Fortran II, and the rule became that a user could employ any correct-form name, such as SQRT, for a variable's name (simple or array) but then the library function SQRT would become inaccessible in such a routine. Similarly, there would be no point in the user writing a function called SQRT, because it could not be invoked - the compiler would take any invocation as being for the library routine SQRT. Thus, a user-written function could perhaps chance to have the name of an obscure (i.e. one forgotten about) library function, but if you were lucky it would have conflicting parameters and the compiler will complain.
A special case is provided by the "arithmetic statement function" that is defined after declarations but before executable statements in a routine and which has access to all the variables of the routine. Consider
REAL this,that
DIST(X,Y,Z) = SQRT(X**2 + Y**2 + Z**2) + this/that !One arithmetic statement, possibly lengthy.
...
D = 3 + DIST(X1 - X2,YDIFF,SQRT(ZD2)) !Invoke local function DIST.
In this case, even if "DIST" happened to be the name of some library function, invocations within the routine defining it would not be of the library function.
This flexibility in naming can be turned the other way around. For example, some compilers offer the intrinsic function SIND which calculates sine in degrees. Simply defining an array REAL SIND(0:360)
(and properly initialising it) enables the slowish SIND function to be approximated by the faster indexing of an array. Put another way, an array is a function of a limited span of integer-valued arguments and is called in arithmetic expressions with the same syntax as is used for functions, be they intrinsic or user-written. Those writing in Pascal would be blocked by its insistence that arrays employ [] rather than (). Similarly, when testing, an array's declaration might be commented out and a function of that name defined, which function could check its arguments, write to a log file, note time stamps, or whatever else comes to mind. But alas, there is no "palindromic" or reverse-entry facility whereby a function could handle the assignment of a value to an array that would make this fully flexible.
Within a function there are some delicacies. The usual form is to assign the desired result to the name of the variable as in H = A + B
where H
is the name of the function. However, during evaluation the desired result might be developed over many stages and with reference to prior values. Suppose function H is to combine results from separate statements and it is not convenient to achieve this via one lengthy expression, perhaps because of conditional tests. Something like
H = A + B
IF (blah) H = 3*H - 7
As written, the appearance of H
on the right-hand side of an expression does not constitute a call of function H
at all. Some compilers fail to deal with this as hoped, and so one must use a scratch variable such as FH
to develop the value, then remember to ensure that the assignment H = FH
is executed before exiting the function, by whatever route. If the result is a large datum (a long character variable, say) this is annoying.
With the belated recognition of recursive possibilities (introduced by Algol in the 1960s) comes the possibility of a function invoking itself. In the above example, H(3.7,5.5,6.6)
would clearly be a function invocation (because of the parentheses) whereas H
would not be. Actually, Fortran routines have always been able to engage in recursion, it is just the returns that will fail - except on a stack-based system such as the Burroughs 6700 in the 1970s.
Fortran also offers the ability to pass a function as a parameter such that the recipient routine can call it, as in
REAL FUNCTION INTG8(F,A,B,DX) !Integrate function F.
EXTERNAL F !Some function of one parameter.
REAL A,B !Bounds.
REAL DX !Step.
INTEGER N !A counter.
INTG8 = F(A) + F(B) !Get the ends exactly.
N = (B - A)/DX !Truncates. Ignore A + N*DX = B chances.
DO I = 1,N !Step along the interior.
INTG8 = INTG8 + F(A + I*DX) !Evaluate the function.
END DO !On to the next.
INTG8 = INTG8/(N + 2)*(B - A) !Average value times interval width.
END FUNCTION INTG8 !This is not a good calculation!
FUNCTION TRIAL(X) !Some user-written function.
REAL X
TRIAL = 1 + X !This will do.
END FUNCTION TRIAL !Not the name of a library function.
PROGRAM POKE
INTRINSIC SIN !Thus, not an (undeclared) ordinary variable.
EXTERNAL TRIAL !Likewise, but also, not an intrinsic function.
REAL INTG8 !Don't look for the result in an integer place.
WRITE (6,*) "Result=",INTG8(SIN, 0.0,8*ATAN(1.0),0.01)
WRITE (6,*) "Linear=",INTG8(TRIAL,0.0,1.0, 0.01)
END
This involves a fair amount of juggling special declarations so that the compiler will make the desired assumptions that a function is being called upon, rather than the value of some variable. This is eased somewhat with F90 onwards if the MODULE protocol is used so that at least you do not have to remember to declare INTG8 as REAL. Certain library functions are not allowed as candidates for passing to INTG8 (for instance, the compiler may render them as in-line code, bypassing the protocol used for functions) and arithmetic statement functions are usually rejected, as would be an array masquerading as a function. Arithmetic expressions are not allowable as possible "functions" either - how might something like sin(x) + 3*sqrt(x) + 7
be recognised as a function instead? As INTG8(SIN + 3*SQRT + 7,etc...
? Unlike Algol, Fortran does not offer the call-by-name facility as used in Jensen's Device, which would be something like INTG8(SIN(X) + 3*SQRT(X) + 7,etc...
and would also require passing variable X. Perhaps a keyword BYNAME might be introduced one day. Until then a properly-named function must be declared and its name only be given. And of course, candidate functions must have the correct number and type of parameters, or else...
This works because Fortran passes parameters by reference (i.e. by giving the machine address of the entity), so that for functions, the code's entry point for the function is passed. With normal variables this means that a function (or subroutine) might modify the value of a parameter, as well as returning the function's result - and also mess with any COMMON data or other available storage, so a function EATACARD(IN) might read a line of data into a shared work area (called say ACARD) from I/O unit number IN and return true, otherwise false should it hit end-of-file.
But it is also possible that parameters are passed via copy-in copy-out instead of by reference, with subtle changes in behaviour. This may also be done even on systems that do employ passing by reference. For instance, with
TYPE MIXED
CHARACTER*12 NAME
INTEGER STUFF
END TYPE MIXED
TYPE(MIXED) LOTS(12000)
One might hope to try IT = BCHOP(LOTS.NAME,"Fred")
where BCHOP is a well-tested function for performing a binary search that should run swiftly. Alas, no. The successive values of NAME are not contiguous while BCHOP expects to receive an array of values that are contiguous - that is, with a "stride" of one. So, the compiler inserts code to copy all the LOTS.NAME elements into such a work area and passes the location of that to BCHOP (which searches it swiftly), then on return, the work area is copied back to LOTS.NAME just in case there had been a change. This latter can be avoided if within BCHOP its array is given the attribute INTENT(IN) for read-only but the incoming copy still means an effort of order N, while for the search the effort is just Log(N). This can have a less-than-subtle effect if large arrays are involved.
Fortress
component call_a_function
export Executable
(* Declaring test functions that allow the various ways to call functions in Fortress to be demonstrated. *)
addition(i:ZZ32, j:ZZ32): ZZ32 = i+j
addition(i:ZZ32): ZZ32 = i+1
(* Strings are concatenated by using a space as an infix operator. *)
addition(i:String, j:String): String = i j
printAString(s:String): () = println(s)
(* Functions can be passed to other functions as arguments. When passing a function as an argument, the argument's type should be
represented as follows: "typeOfArgument(s)->returnType," which, in this case, is "String->()." You could also technically use the
"Any" type, but that isn't type-safe. *)
printAString(s:String, f:String->()) = f(s)
(* Defined functions can then be called as follows. *)
var x:ZZ32 = addition(1, 2)
var str:String = addition("This is ", "another string.")
run() = do
(* You can call built-in functions the same way that you call functions that you define. *)
println("x at start: " x)
x := addition(x, 2)
println("x at middle: " x)
printAString("This " "is " "a " "string.")
printAString(str)
printAString("\nThis is a string that is being printed by a function of the same name \nthat takes a function as an argument.\n",
printAString)
x := addition(4)
println("x at end: " x)
end
end
Free Pascal
See Delphi. Note, calling a function as if it was a procedure [i. e. discarding the return value] is only permitted if you set the compiler setting {$extendedSyntax on}/{$X+}. This is the default.
FreeBASIC
Sub Saludo()
Print "Hola mundo!"
End Sub
Function Copialo(txt As String, siNo As Short, final As String = "") As String
Dim nuevaCadena As String
For cont As Short = 1 To siNo
nuevaCadena &= txt
Next
Return Trim(nuevaCadena) & final
End Function
Sub testNumeros(a As Integer, b As Integer, c As Integer = 0)
Print a, b, c
End Sub
Sub testCadenas(txt As String)
For cont As Byte = 0 To Len(txt)
Print Chr(txt[cont]); "";
Next cont
End Sub
Saludo
Print Copialo("Saludos ", 6)
Print Copialo("Saludos ", 3, "!!")
?
testNumeros(1, 2, 3)
testNumeros(1, 2)
?
testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")
- Output:
Hola mundo! Saludos Saludos Saludos Saludos Saludos Saludos Saludos Saludos Saludos!! 1 2 3 1 2 0 1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'
FutureBasic
No arguments
void local fn MyFunction
print @"MyFunction"
end fn
fn MyFunction
HandleEvents
Fixed arguments - args passed by value
void local fn MyFunction( arg1 as long, arg2 as long, arg3 as long )
print @"MyFunction"
end fn
fn MyFunction( 1, 2, 3 )
HandleEvents
Variable arguments - args passed by value
void local fn MyFunction( count as long, ... )
va_list ap
long i, value
va_start( ap, count )
for i = 1 to count
value = fn va_arglong( ap )
print value
next
va_end( ap )
end fn
fn MyFunction( 3, 12, 24, 36 )
HandleEvents
Return value - arg passed by value
local fn MultiplyByThree( value as long ) as long
end fn = value * 3
print fn MultiplyByThree( 13 )
HandleEvents
Argument passed by reference
void local fn MultiplyByThree( value as ^long )
*value *= 3
end fn
long num
num = 9
fn MultiplyByThree( @num )
print num
HandleEvents
Gambas
Click this link to run this code
Some of the uses of Procedures/Functions in Gambas
Public Sub Main()
Hello
Print CopyIt("Hello ", 6)
Print CopyIt("Hello ", 3, "!!")
End
'_____________________________________________________________________________________
Public Sub CopyIt(sString As String, siNo As Short, Optional sEnd As String) As String
Dim siCount As Short
Dim sNewString As String
For siCount = 1 To siNo
sNewString &= sString
Next
Return Trim(sNewString) & sEnd
End
'_____________________________________________________________________________________
Public Sub Hello()
Print "Hello world!"
End
Output:
Hello world! Hello Hello Hello Hello Hello Hello Hello Hello Hello!!
Go
The following examples use functions from the standard packages plus a few dummy local functions:
import ( "image" "image/gif" "io/ioutil" "strings" "unicode" ) func f() (int, float64) { return 0, 0 } func g(int, float64) int { return 0 } func h(string, ...int) {}
- Calling with no arguments and calling with a fixed number of arguments:
f() g(1, 2.0) // If f() is defined to return exactly the number and type of // arguments that g() accepts than they can be used in place: g(f()) // But only without other arguments, this won't compile: //h("fail", f()) // But this will: g(g(1, 2.0), 3.0)
- Calling with a variable number of arguments:
- This is only possible with functions defined with a trailing optional/variable length argument of a single type (as
h
above).h("ex1") h("ex2", 1, 2) h("ex3", 1, 2, 3, 4) // such functions can also be called by expanding a slice: list := []int{1,2,3,4} h("ex4", list...) // but again, not mixed with other arguments, this won't compile: //h("fail", 2, list...)
- This is only possible with functions defined with a trailing optional/variable length argument of a single type (as
- Optional arguments and named arguments are not supported.
- However, it is reasonably common to see a structure used for this. In this example
gif.Options
is a structure with multiple members which can initialized/assigned by name or omitted (or the whole third argument can just benil
).gif.Encode(ioutil.Discard, image.Black, &gif.Options{NumColors: 16})
- However, it is reasonably common to see a structure used for this. In this example
- Optional arguments are supported.
package main import "fmt" type Params struct { a, b, c int } func doIt(p Params) int { return p.a + p.b + p.c } func main() { fmt.Println(doIt(Params{a: 1, c: 9})) // prt 10 }
- Named arguments are supported.
package main import "fmt" func bar(a, b, c int) { fmt.Printf("%d, %d, %d", a, b, c) } func main() { args := make(map[string]int) args["a"] = 3 args["b"] = 2 args["c"] = 1 bar(args["a"], args["b"], args["c"]) // prt 3, 2, 1 }
- Within a statement context.
- Assignment statements are shown later. Only functions returning a single value can be used in a single value context:
if 2*g(1, 3.0)+4 > 0 {}
- Assignment statements are shown later. Only functions returning a single value can be used in a single value context:
- In a first-class context:
fn := func(r rune) rune { if unicode.IsSpace(r) { return -1 } return r } strings.Map(fn, "Spaces removed") strings.Map(unicode.ToLower, "Test") strings.Map(func(r rune) rune { return r + 1 }, "shift")
- Obtaining the value:
a, b := f() // multivalue return _, c := f() // only some of a multivalue return d := g(a, c) // single return value e, i := g(d, b), g(d, 2) // multiple assignment
- Built-in functions and user defined functions can not be distinguished.
- Functions from the standard packages look like any other. The few truly built-in functions are only different in that they have no package specifier like local functions (and they sometimes have extra capabilities).
list = append(list, a, d, e, i) i = len(list)
- Functions from the standard packages look like any other. The few truly built-in functions are only different in that they have no package specifier like local functions (and they sometimes have extra capabilities).
- Go has no subroutines, just functions and methods.
- Go arguments are passed by value.
- As with C, a pointer can be used to achieve the effect of reference passing. (Like pointers, slice arguments have their contents passed by reference, it's the slice header that is passed by value).
- Go arguments are passed by value or by reference
package main import "fmt" // int parameter, so arguments will be passed to it by value. func zeroval(ival int) { ival = 0 } // has an *int parameter, meaning that it takes an int pointer. func zeroptr(iptr *int) { *iptr = 0 } func main() { i := 1 fmt.Println("initial:", i) // prt initial: 1 zeroval(i) fmt.Println("zeroval:", i) // prt zeroval: 1 zeroptr(&i) fmt.Println("zeroptr:", i) // prt zeroptr: 0 fmt.Println("pointer:", &i) // prt pointer: 0xc0000140b8 }
- Partial and Currying is not directly supported.
- However something similar can be done, see Partial function application#Go
package main import "fmt" func mkAdd(a int) func(int) int { return func(b int) int { return a + b } } func sum(x, y int) int { return x + y } func partialSum(x int) func(int) int { return func(y int) int { return sum(x, y) } } func main() { // Is partial application possible and how add2 := mkAdd(2) add3 := mkAdd(3) fmt.Println(add2(5), add3(6)) // prt 7 9 // Currying functions in go partial := partialSum(13) fmt.Println(partial(5)) //prt 18 }
Groovy
There are two types of first-class functions in Groovy.
- The first are functions defined in scripts, although they behave as if they are methods of the script "class".
- The second are closures, which are similar to lambdas in Java, except that they are defined as their own class type and must be explicitly converted to single-method "functional" interfaces. There are many methods within the Groovy API that accept closures as arguments.
- Calling a function that requires no arguments
noArgs()
- Calling a function with a fixed number of arguments
fixedArgs(1, "Zing", Color.BLUE, ZonedDateTime.now(), true)
- Calling a function with optional arguments
optArgs("It's", "a", "beautiful", "day")
optArgs("It's", "a", "beautiful")
optArgs("It's", "a")
optArgs("It's")
- Calling a function with a variable number of arguments
varArgs("It's", "a", "beautiful", "day")
varArgs("It's", "a", "beautiful")
varArgs("It's", "a")
varArgs("It's")
- Calling a function with named arguments
It's complicated
- Using a function in statement context
def mean = calcAverage(1.2, 4.5, 3, 8.9, 22, 3)
- Using a function in first-class context within an expression
- Create new functions from preexisting functions at run-time
def oldFunc = { arg1, arg2 -> arg1 + arg2 }
def newFunc = oldFunc.curry(30)
assert newFunc(12) == 42
- Store functions in collections
def funcList = [func1, func2, func3]
- Use functions as arguments to other functions
def eltChangeFunc = { it * 3 - 1 }
def changedList = list.collect(eltChangeFunc)
- Use functions as return values of other functions
def funcMaker = { String s, int reps, boolean caps ->
caps ? { String transString -> ((transString + s) * reps).toUpperCase() }
: { String transString -> (transString + s) * reps }
}
def func = funcMaker("a", 2, true)
assert func("pook") == "POOKAPOOKA"
- Obtaining the return value of a function
def retVal = func(x, y, z)
- Distinguishing built-in functions and user-defined functions
There are no "built-in" functions. All is illusion.
- Stating whether arguments are passed by value or by reference
As with Java everything is passed by value, but object values are actually references (pointers). So,
- if the argument is a primative it is passed by value and changes are not manifested in the caller's context.
- if the argument is an object reference, the reference is passed by value and changes to the reference (re-assignment, for example) are not manifested in the caller's context, but changes in the object are.
- Is partial application possible and how
Partial application in Groovy is performed via currying (demonstrated above)
Haskell
-- Calling a function with a fixed number of arguments
multiply x y = x * y
multiply 10 20 -- returns 200
-- Calling a function that requires no arguments
-- Normally, you use constant instead of function without arguments:
twopi = 6.28
-- But you can also pass special value as the first argument indicating function call:
twopi () = 6.28 -- definition
twopi :: Num a => () -> a -- its type
twopi () -- returns 6.28
-- Partial application and auto-currying is built-in.
multiply_by_10 = (10 * )
map multiply_by_10 [1, 2, 3] -- [10, 20, 30]
multiply_all_by_10 = map multiply_by_10
multiply_all_by_10 [1, 2, 3] -- [10, 20, 30]
-- TODO:
-- Calling a function with optional arguments
-- Calling a function with a variable number of arguments
-- Calling a function with named arguments
-- Using a function in statement context
-- Using a function in first-class context within an expression
-- Obtaining the return value of a function
-- Distinguishing built-in functions and user-defined functions
-- Distinguishing subroutines and functions
-- Stating whether arguments are passed by value or by reference
i
//The type of the function argument determines whether or not the value is passed by reference or not.
//Eg. numbers are passed by value and lists/arrays are passed by reference.
software {
print() //Calling a function with no arguments.
print("Input a number!") //Calling a function with fixed arguments.
print(1,2,3,4,5,6,7,8,9,0) //Calling a function with variable arguments.
input = read() //Obtaining the return value of a function.
myprint = print
myprint("It was: ", input) //Calling first class functions, the same as calling ordinary functions.
//The only distinction that can be made between two functions is if they are 'real' or not.
if type(myprint) = concept
print("myprint is a not a real function")
else if type(myprint) = function
print("myprint is a real function")
end
//Partial functions can be created with static parts.
DebugPrint = print["[DEBUG] ", text]
DebugPrint("partial function!") //This would output '[DEBUG] partial function!'
if type(DebugPrint) = concept
print("DebugPrint is a not a real function")
else if type(DebugPrint) = function
print("DebugPrint is a real function")
end
}
Icon and Unicon
Icon and Unicon have generalized procedures and syntax that are used to implement functions, subroutines and generators.
- Procedures can return values or not and callers may use the returned values or not.
- Procedures in Icon and Unicon are first class values and can be assigned to variables which can then be used to call procedures. This also facilitates some additional calling syntax.
- Additionally, co-expressions are supported which allow for co-routine like transfers of control between two or more procedures. There are some differences in syntax for co-expression calls.
- There are no differences between calling built-in vs. user defined functions
- Named arguments is not natively supported; however, they can be supported using a user defined procedure as shown in Named parameters
- Method calling is similar with some extended syntax
- Arguments are basically passed by value or reference based on their type. Immutable values like strings, and numbers are passed by value. Mutable data types like structures are essentially references and although these are passed by value the effective behavior is like a call by reference.
For more information see Icon and Unicon Introduction on Rosetta
J
A function in J is typically represented by a verb. Under the right circumstances other syntactic entities (nouns, adverbs, conjunctions) can represent functions, but let's focus on the typical case.
A verb, in J, typically supports two syntactic variants:
verb noun
noun verb noun
And a noun, in J, is an array.
An argument list can be represented by an array. Thus, when dealing with multiple arguments, a typical form is:
function argumentList
Here, function
is a verb and argumentList
is a noun.
For example:
sum(1,2,3)
Here sum
is a verb and (1,2,3)
is a noun.
Thus:
A function that requires no arguments can be simulated by calling a function with empty argument list:
f''
Note that an empty list of characters is not the only constant in the language which is an empty list. That said, most operations in the language do not care what type of data is not present, in an array which contains nothing.
A function with a fixed number of arguments gets special treatment in J when the fixed number is 1 or 2.
f 'one argument'
and
'this example has two arguments' f 'the other argument'
Alternatively, the function can be written such that an argument list is an error when it's the wrong length.
A function with a variable number of arguments (varargs): See above.
If argument types conflict they will need to be put in boxes and the function will have to take its arguments out of the boxes. Here's an unboxed example with five arguments:
f 1,2,3,4,5
and here's a boxed example with five arguments:
f (<1),(<2),(<3),(<4),(<5)
Note that the last set of parenthesis is unnecessary
f (<1),(<2),(<3),(<4),<5
Note also that J offers some syntactic sugar for this kind of list
f 1; 2; 3; 4; <5
. Note also that if the last argument in a semicolon list is not boxed there is no need to explicitly box it, since that is unambiguous (it must be boxed so that it conforms with the other members of the list).
f 1; 2; 3; 4; 5
A function with named arguments can be accomplished by calling a function with the names of the arguments.
f 'george';'tom';'howard'
Other interpretations of this concept are also possible. For example, the right argument for a verb might be a list of argument names and the left argument might be a corresponding list of argument values:
1 2 3 f 'george';'tom';'howard'
Or, for example a function which requires an object could be thought of as a function with named arguments since an object's members have names:
obj=: conew'blank'
george__obj=: 1
tom__obj=: 2
howard__obj=: 3
f obj
coerase obj
Name/value pairs can also be used for this purpose and can be implemented in various ways, including passing names followed by values
f 'george';1;'tom';2;'howard';3
and passing a structure of pairs
f ('george';1),('tom';2),:(howard';3)
Or, for example, the pairs could be individually boxed:
f ('george';1);('tom';2);<howard';3
Using a function in command context is no different from using a function in any other context, in J. Using a function in first class context within an expression is no different from using a function in any other context, in J.
Obtaining the return value of a function is no different from using a function in j. For example, here we add 1 to the result of a function:
1 + f 2
The only differences that apply to calling builtin functions rather than user defined functions is spelling of the function names.
There are no differences between calling subroutines and functions because J defines neither subroutines
nor functions
. Instead, J defines verbs
, adverbs
, and conjunctions
which for the purpose of this task are treated as functions. (All of the above examples used verbs. J's adverbs and conjunctions have stronger valence than its verbs.)
Java
"Calling a function that requires no arguments."
The parentheses are required.
Object.methodName();
"Calling a function with a fixed number of arguments."
Object.methodName("rosetta", "code");
"Calling a function with optional arguments."
Java doesn't offer the ability to optionalize parameters, although there is something similar.
A varargs, or "Variable Arguments", parameter, could be of 0 length.
So if you're only parameter is a vararg parameter, it's possible to not supply any input.
This could be viewed, in some situations, as an optional parameter.
"Calling a function with a variable amount of arguments."
There is no special syntax, you simply offer the arguments as required.
"Calling a function with named arguments."
Java does not offer this feature.
"Using a function in a statement context."
Java is not a functional programming language, although Java 8 added basic closures and lambda expressions.
They are not in anyway as robust as functional languages like JavaScript.
A lambda works specifically with an interface
that requires only 1 abstraction.
Consider the following interface.
interface Example {
int add(int valueA, int valueB);
}
You could then implement this interface with a lambda, as opposed to creating an anonymous-class.
Consider the following method.
int sum(Example example) {
return example.add(1, 2);
}
You would then provide the closure, or the functionality of the abstraction, during assignment.
Example example = (valueA, valueB) -> valueA + valueB;
sum(example);
"Using a function in first-class context with an expression."
First-class context is out-of-scope for Java, which is statically-typed.
"Obtaining the return value of a function."
String string = Object.methodName("rosetta", "code");
"Distinguishing built-in functions and user-defined functions."
There is no ambiguity between built-in functions and user-defined functions.
"Distinguishing subroutines and functions."
Java refers to all procedures as methods.
As with other languages, such as Visual Basic, which uses Sub, and Function,
there is no ambiguity from methods which return values and those that don't.
The defining factor is within the method definition.
A return-type is declared before the method name, and void
is used when there is no returned value.
String methodA();
void methodB();
"Stating whether arguments are passed by value or by reference."
The concept of pass-by-value and pass-by-reference is somewhat a redefined measure within Java.
For the most part, everything is pass-by-value; there are no pointers and dereferencing, as with C, C++, and Rust.
Although, if you're passing an object, it can be viewed as pass-by-reference, since the operation is occurring on the actual object,
and a new value is not created.
Java is essentially an language that was influenced by languages which use pass-by-reference, so it's abstraction is lacking.
"Is partial application possible and how."
Not without a closure.
I found the following example on Wikipedia - Partial application.
<X, Y, Z> Function<Y, Z> exampleA(BiFunction<X, Y, Z> exampleB, X value) {
return y -> exampleB.apply(value, y);
}
Here is an alternate demonstration.
Java does not have functions, but Java classes have "methods" which are equivalent.
- Calling a function that requires no arguments
myMethod()
We didn't specify an object (or a class) as the location of the method, so this.myMethod() is assumed. This applies to all the following examples.
- Calling a function with a fixed number of arguments
myMethod(97, 3.14)
- Calling a function with optional arguments
This is possible if the method name is overloaded with different argument lists. For example:
int myMethod(int a, double b){
// return result of doing sums with a and b
}
int myMethod(int a){
return f(a, 1.414);
}
The compiler figures out which method to call based on the types of the arguments, so in this case the second argument appears to be optional. If you omit it, the value 1.414 is used.
System.out.println( myMethod( 97, 3.14 ) );
System.out.println( myMethod( 97 ) );
- Calling a function with a variable number of arguments
This is possible if the method is defined with varargs syntax. For example:
void printAll(String... strings){
for ( String s : strings )
System.out.println( s );
}
The type of strings is actually a string array, but the caller just passes strings:
printAll( "Freeman" );
printAll( "Freeman", "Hardy", "Willis" );
To avoid ambiguity, only the last argument to a function can have varargs.
- Calling a function with named arguments
Not directly possible, but you could simulate this (somewhat verbosely):
int myMethod( Map<String,Object> params ){
return
((Integer)params.get("x")).intValue()
+ ((Integer)params.get("y")).intValue();
}
Called like this:
System.out.println( myMethod(new HashMap<String,Object>(){{put("x",27);put("y",52);}}) );
Yuk.
- Using a function in statement context
If this means "use a function where a statement is expected", see all the other examples
- Using a function in first-class context within an expression
Not possible - must be wrapped in a class
- Obtaining the return value of a function
int i = myMethod(x);
- Distinguishing built-in functions and user-defined functions
No distinction - all methods belong to classes, and there is no real distinction between built-in and user-defined classes.
- Distinguishing subroutines and functions
If the return type is void, you might consider a method as a subroutine rather than a function.
- Stating whether arguments are passed by value or by reference
All arguments are passed by value, but since object variables contain a reference to an object (not the object itself), objects appear to be passed by reference. For example:
myMethod(List<String> list){
// If I change the contents of the list here, the caller will see the change
}
- Is partial application possible and how
Don't know
JavaScript
The arguments to a JavaScript function are stored in a special array-like object which does not enforce arity in any way; a function declared to take n arguments may be called with none‒and vice versa‒without raising an error.
var foo = function() { return arguments.length };
foo() // 0
foo(1, 2, 3) // 3
Neither optional (see above) nor named arguments are supported, though the latter (and the inverse of the former) may be simulated with the use of a helper object to be queried for the existence and/or values of relevant keys. Seriously, what is "statement context"?
JavaScript functions are first-class citizens; they can be stored in variables (see above) and passed as arguments.
var squares = [1, 2, 3].map(function (n) { return n * n }); // [1, 4, 9]
Naturally, they can also be returned, thus partial application is supported.
var make_adder = function(m) {
return function(n) { return m + n }
};
var add42 = make_adder(42);
add42(10) // 52
Calling a user-defined function's toString() method returns its source verbatim; that the implementation is elided for built-ins provides a mechanism for distinguishing between the two.
foo.toString()
"function () { return arguments.length }"
alert.toString()
"function alert() { [native code] }"
Arguments are passed by value, but the members of collections are essentially passed by reference and thus propagate modification.
var mutate = function(victim) {
victim[0] = null;
victim = 42;
};
var foo = [1, 2, 3];
mutate(foo) // foo is now [null, 2, 3], not 42
jq
jq functions are pure functions that are somewhat unusual in two respects:
- They are like commands in modern operating systems, in that they are parameterized filters that can accept input from the previous command and provide output to the next command if there is one in the pipeline of commands.
- Functions can not only process a stream of inputs, one at a time, but each argument can also accept a stream of inputs. The outputs are then a Cartesian product of the various inputs.
In this section, we use the notation fn/N to refer to a function named "fn" with N formal parameters.
Calling a function that requires no arguments
0-arity jq functions are invoked simply by specifying their name.
- Example: .
(Yes, "." is a 0-arity jq function.)
Calling a function with a fixed number of arguments
The conventional syntax is used except that ";" is the parameter separator. "," is used to construct a stream of values.
- Example: range(0;100;2)
Calling a function with optional arguments
Recent versions of jq allow one to define functions with the same name but different arities, and therefore if both fn/1 and fn/2 are defined, we may say that fn requires one parameter but accepts 2. In all cases, the syntax for function invocation is the same.
- Example: range(0; 10) and range(0; 10; 2)
Since jq functions can accept JSON arrays and objects, there are other ways to simulate optional arguments.
Calling a function with a variable number of arguments
See above.
Calling a function with named arguments
This is not directly supported but can be simulated by defining the function to accept JSON objects. For example, if fn were such a function, we might invoke fn like so: fn( {"required": 1, "optional": 2} ).
Using a function in statement context
The assignment to a local variable (e.g. (2*2) as $two) is similar to a statement context in that the expression as a whole does nothing to the flow of values from its input to its output.
Using a function in first-class context within an expression
jq functions cannot be assigned to variables but are otherwise "first-class" in that the composition of functions can be passed as arguments to other functions. No special syntax is required.
- Example: 2 | recurse(. * .) # generate the sequence 2, 4, 16, 256, ...
Obtaining the return value of a function
The value (or stream of values) returned by a function is (or are) automatically available to the next function in the pipeline (e.g. sin | cos); the returned value(s) can also be assigned to a local variable (e.g. sin as $v).
Distinguishing built-in functions and user-defined functions
Currently there is no such distinction, but user-defined functions always have the conventional form, whereas some built-in functions have special syntax.
Distinguishing subroutines and functions
A jq function can be written so as never to return anything (either because it returns without generating a value or because it generates an infinite stream of values), but there is no distinctive marker associated with such functions.
Stating whether arguments are passed by value or by reference
Arguments are in effect passed by value.
Is partial application possible and how
See Currying#jq.
Julia
# Calling a function that requires no arguments:
f() = print("Hello world!")
f()
# Calling a function with a fixed number of arguments:
function f(x, y, z)
x*y - z^2
end
f(3, 4, 2)
# Calling a function with optional arguments:
# Note Julia uses multiple dispatch based on argument number and type, so
# f() is always different from f(x) unless default arguments are used, as in:
pimultiple(mult=1.0) = pi * mult # so pimultiple() defaults to pi * (1.0) or pi
# Calling a function with a variable number of arguments:
f(a,b,x...) = reduce(+, 0, x) - a - b
# here a and b are single arguments, but x is a tuple of x plus whatever follows x, so:
a = b = c = d = e = 3
f(a,b,c) # x within the function is (c) so == 0 + c - a - b
f(a,b,c,d,e) # x is a tuple == (c,d,e) so == (0 + c + d + e) - a - b
f(a,b) # x is () so == 0 - a - b
# Calling a function with named arguments:
# Functions with keyword arguments are defined using a semicolon in the function signature,
# as in
# function plot(x, y; style="solid", width=1, color="black")
#
# When the function is called, the semicolon is optional, so plot here can be
# either called with plot(x, y, width=2) or less commonly as plot(x, y; width=2).
# Using a function in statement context:
# Any function can be used as a variable by its name.
circlearea(x) = x^2 * pi
map(circlearea, [r1, r2, r3, r4])
# Using a function in first-class context within an expression:
cylindervolume = circlearea(r) * h
# Obtaining the return value of a function:
radius = 2.5
area = circlearea(2.5)
# Distinguishing built-in functions and user-defined functions:
# Julia does not attempt to distinguish these in any special way,
# but at the REPL command line there is ? help available for builtin
# functions that would not generally be available for the user-defined ones.
# Distinguishing subroutines and functions:
# All subroutines are called functions in Julia, regardless of whether they return values.
# Stating whether arguments are passed by value or by reference:
# As in Python, all arguments are passed by pointer reference, but assignment to a passed argument
# only changes the variable within the function. Assignment to the values referenced by the argument
## DOES however change those values. For instance:
a = 3
b = [3]
c = [3]
function f(x, y)
a = 0
b[1] = 0
c = [0]
end # a and c are now unchanged but b = [0]
# Is partial application possible and how:
# In Julia, there are many different ways to compose functions. In particular,
# Julia has an "arrow" operator -> that may be used to curry other functions.
f(a, b) = a^2 + a + b
v = [4, 6, 8]
map(x -> f(x, 10), v) # v = [30, 52, 82]
Kotlin
In Kotlin parameters are always passed by value though, apart from the (unboxed) primitive types, the value passed is actually a reference to an object.
fun fun1() = println("No arguments")
fun fun2(i: Int) = println("One argument = $i")
fun fun3(i: Int, j: Int = 0) = println("One required argument = $i, one optional argument = $j")
fun fun4(vararg v: Int) = println("Variable number of arguments = ${v.asList()}")
fun fun5(i: Int) = i * i
fun fun6(i: Int, f: (Int) -> Int) = f(i)
fun fun7(i: Int): Double = i / 2.0
fun fun8(x: String) = { y: String -> x + " " + y }
fun main() {
fun1() // no arguments
fun2(2) // fixed number of arguments, one here
fun3(3) // optional argument, default value used here
fun4(4, 5, 6) // variable number of arguments
fun3(j = 8, i = 7) // using named arguments, order unimportant
val b = false
if (b) fun1() else fun2(9) // statement context
println(1 + fun6(4, ::fun5) + 3) // first class context within an expression
println(fun5(5)) // obtaining return value
println(kotlin.math.round(2.5)) // no distinction between built-in and user-defined functions, though former usually have a receiver
fun1() // calling sub-routine which has a Unit return type by default
println(fun7(11)) // calling function with a return type of Double (here explicit but can be implicit)
println(fun8("Hello")("world")) // partial application isn't supported though you can do this
}
- Output:
No arguments One argument = 2 One required argument = 3, one optional argument = 0 Variable number of arguments = [4, 5, 6] One required argument = 7, one optional argument = 8 One argument = 9 20 25 2.0 No arguments 5.5 Hello world
Lambdatalk
In lambdatalk functions are abstractions {lambda {args} body} whose behaviour is best explained as a part of such a complete expression {{lambda {args} body} values}.
The command
replace :a0 :a1 ... an-1
in expression containing some occurences of :ai
by v0 v1 ... vp-1
is rewritten in a prefixed parenthesized form
{{lambda {:a0 :a1 ... an-1}
expression containing some occurences of :ai}
v0 v1 ... vp-1}
so called IIFE (Immediately Invoked Function Expression), and defines an anonymous function containing a sequence of n arguments :ai, immediately invoked on a sequence of p values vi, and returning the expression in its body as so modified:
1) if p < n (partial application)
• the occurrences of the p first arguments are replaced in the function's body by the corresponding p given values,
• a function waiting for missing n-p values is created,
• and its reference is returned.
• example:
{{lambda {:x :y} ... :y ... :x ...} hello}
-> {lambda {:y} ... :y ... hello ...} // replaces :x by hello
-> LAMB_123 // the new functions's reference
• called with the value world this function will return ... world ... hello ...
2) if p = n (normal application)
• the occurences of the n arguments are replaced in the function's body by the corresponding p given values,
• the body is evaluated and the result is returned.
• example
{{lambda {:x :y} ... :y ... :x ...} hello world}
-> {{lambda {:y} ... :y ... hello ...} world} // replaces :x by hello
-> {{lambda {} ... world ... hello ...} } // replaces :y by world
-> ... world ... hello ... // the value
3) if p > n (variadicity)
• the occurrences of the n-1 first arguments are replaced in the function's body by the corresponding n-1 given values,
• the occurrences of the last argument are replaced in the body by the sequence of p-n supernumerary values,
• the body is evaluated and the result is returned.
• example:
{{lambda {:x :y} ... :y ... :x ...} hello world good morning}
-> {{lambda {:y} ... :y ... hello ...} world good morning}
-> {{lambda {} ... world good morning ... hello ...}}
-> ... world good morning ... hello ... // the value
More can be seen in http://lambdaway.free.fr/lambdawalks/?view=lambda
Lang
fp.noArgs = () -> \!
fp.noArgs()
# For user defined-functions, the argument count is not checked: If too many arguments were provided, they are ignored. If not enough arguments were provided, the last argument will be duplicated (If none was provided, VOID values will be filled in). [This process is is referred to as implict argument duplication]
fp.noArgs(42) # No Error nor Warning
fp.fixArgs = ($x, $y) -> \!
fp.fixArgs(1, 2)
fp.fixArgs(2) # Fix args will be called with $x=2 and $y=2
fp.fixArgs() # Fix args will be called with $x=VOID and $y=VOID
# fn.argCntX (X must be replaced with 0, 1, 2, 3, 4, or 5) can be used to force the caller to provided the exact argument count
# fn.argCntX must be called with the function to apply the constraint to and will return a new function
fp.realFixArgs = fn.argCnt2(fp.fixArgs)
fp.realFixArgs(1, 2)
fp.realFixArgs() # Error
fp.realFixArgs(1) # Error
fp.realFixArgs(1, 2, 3) # Error
# Arrays can be unpacked in function calls
&values $= [1, 2]
fp.fixArgs(&values...) # Fix args will be called with $x=1 and $y=2
# In Lang there are text and array varags parameters
fp.varArgsText = ($text...) -> \!
fp.varArgsText(1) # Var args text will be called with "1"
fp.varArgsText(1, 2) # Var args text will be called with "1, 2"
fp.varArgsText(1,2) # Var args text will be called with "1,2"
fp.varArgsText(1,text ,3) # Var args text will be called with "1,text ,3"
fp.varArgsArray = (&args...) -> \!
fp.varArgsArray(1) # Var args array will be called with [1]
fp.varArgsArray(1, 2) # Var args array will be called with [1, 2]
fp.varArgsArray(1,2) # Var args array will be called with [1, 2]
fp.varArgsArray(1,text ,3) # Var args array will be called with [1, text, 3]
# Functions with named arguments can not be created
# Using a function in a statement context
$x = fp.fixArgs(1, 2)
# Functions (Even predefined and linker functions) can be used as values
fp.retAFunc = () -> {
return ($x) -> \!
}
fp.func = fp.retAFunc()
fp.func(2)
# Multiple call-expressions can be used directly
fp.retAFunc()(2)
fp.retAFunc = () -> return fn.println
fp.retAFunc()(test, values)
fp.retAFunc = () -> return ln.loadModule
fp.retAFunc()(x.lm) # Error, because file not found
# The return value or the thrown error can be obtained with the assignment operator
fp.inc2 = ($x) -> return parser.op($x + 2)
$ret = fp.inc2(40) # $ret is 42
# Built-in (They are called predefined functions in Lang) start with the "func." or "fn." prefix wheras user-defined functions start with "fp."
# Linker functions start with "linker." or "ln."
# Predefined and linker functions can be stored in a user-defined function
fp.userDefinedFunc = fn.println
fp.userDefinedFunc(Called println)
# In Lang there are no subroutines
# In Lang functions can have call-by-pointer values
# $ptr is a pointer to the called value
fp.callByPtr = ($[ptr]) -> \!
fp.callByPtr(42) # This will create a pointer to an anonymous value, therefor it can not be changed
fp.inc2 = ($[ptr]) -> $*ptr += 2
fp.inc2(40) # Error
$val = 40
fp.inc2($val) # $val is now 42
# Functions can also be called with pointers directly
fp.inc2 = ($ptr) -> $*ptr += 2
fp.inc2(40) # Multiple Errors (Value will be dereferenced as NULL -> + is not defined for NULL and INT AND anonymous values can not be changed)
$val = 40
fp.inc2($[val]) # $val is now 42
# Partial apllication of functions is possible by using combinator functions
# The simplest combinator function-family is the A combinator family (Other families change the order of arguments, can call multiple function, ...)
fp.partialAdd = fn.combA2(fn.add) # When all arguments for fn.combA2(a, b, c) are provided, the execution of a(b, c) will begin
fp.add42 = fp.partialAdd(42) # Creates a function which still needs 1 argument
fp.add42(2) # Will return 44
# Without the use of fn.argCntX 0 args can also be provied
fp.add42()()()(2) # Will also return 44
# The function argument auto un-pack operator (▲ or +|) can be used to create a function which must be called with an array value that is automatically unpacked
fp.fixArgs = ($x, $y) -> \!
fp.unpackingFixArgs $= +|fp.fixArgs
fp.unpackingFixArgs(&values) # Fix args will be called with $x=1 and $y=2
# The function argument auto pack operator (▼ or -|) can be used to cerate a function wich must be called with varargs and will call the original function with a single array argument
fp.arrayArg = (&arr) -> \!
fp.packingArrayArg $= -|fp.arrayArg
fp.packingArrayArg(1, 2) # Array arg will be called with [1, 2]
# Functions can also be called with the pipe operators (|, >>, and >>>)
# The "|" and ">>" pipe operators are identical apart from the operator precedence
# The ">>>" pipe operator automatically unpacks array values
fp.func = ($x) -> \!
parser.op(42 | fp.func) # fp.func is called with 42
parser.op(42 >> fp.func) # fp.func is called with 42
parser.op([42] >>> fp.func) # fp.func is called with 42
# Function calls can be concatinated with the concat operator (|||)
fp.incAndPrint $= fn.inc ||| fn.println # Calling fp.incAndPrint($x) has the same effect as calling fn.println(fn.inc($x))
fp.incAndPrint(2) # Prints 3
# The pow operator can be used to call a function multiple times in succession
# This works only with exponents >= 0 (If the exponent is 0 a function will be returned, that always returns VOID)
fp.voidFunc $= fn.inc ** 0
fp.voidFunc(2) # Returns VOID
fn.pow(fn.inc, 1)(2) # Returns 3
fn.pow(fn.inc, 2)(2) # Returns 4
fn.pow(fn.inc, 3)(2) # Returns 5
fn.pow(fn.inc, 10)(2) # Returns 12
langur
User-defined and built-in functions can be called using parentheses.
Built-in functions can also be called using an "unbounded list," which ends at a line return, EOF, closing parenthesis, curly brace, or square bracket, or before a comma preceding a line return.
parentheses
.x()
# call user-defined function
write(.key, ": ", .value)
# call built-in with parentheses
unbounded lists
write .key, ": ", .value
# call built-in with unbounded list
writeln "numbers: ", join ", ", [.a1, .a2, .a3, .a4]
# unbounded lists on writeln and join
# later function join takes remaining arguments
writeln "numbers: ", join(", ", [.a1, .a2, .a3, .a4]), " === "
# unbounded list on writeln
# join using parentheses so it doesn't take remaining arguments
val .sum = foldfrom(
fn(.sum, .i, .c) { .sum + number(.c, 36) * .weight[.i] },
0,
pseries len .code,
split .code,
)
# split, pseries, and len using unbounded lists, ending before comma preceding line return
for .key in sort(keys .tests) {
...
}
# unbounded list on keys bounded by closing parenthesis of sort
Latitude
Like Ruby, Latitude doesn't have functions in the traditional sense, only methods. Methods can be called with parentheses, as in many languages. If a method takes no arguments, the parentheses may be omitted. If a method takes a single argument and that argument is a literal (such as a literal number or string), then the parentheses may also be omitted. Additionally, Latitude provides an alternative syntax for method calls which replaces the parentheses with a colon.
foo (1, 2, 3). ; (1) Ordinary call
foo (). ; (2) No arguments
foo. ; (3) Equivalent to (2)
foo (1). ; (4) Single-argument function
foo 1. ; (5) Equivalent to (4)
foo (bar). ; (6) Parentheses necessary here since bar is not a literal
foo: 1, 2, 3. ; (7) Alternative syntax, equivalent to (1)
Although methods themselves can be passed around as first-class values, the method evaluation semantics often make such an approach suboptimal. If one needs a first-class function in the traditional sense, the usual approach is to wrap it in a Proc
object and then call it explicitly as needed.
myProc := proc { foo. }.
myProc call (1, 2, 3).
If you want to write a function which can accept either a Proc
or a method object (as many standard library functions do, for convenience), you may use the shield
method to ensure that the object is a Proc
. shield
wraps methods in a Proc
while leaving objects which are already procedures alone.
myProc1 := #'foo shield.
myProc2 := proc { foo. }.
myProc3 := proc { foo. } shield.
All three of the above procedures will act the same.
LFE
Calling a function that requires no arguments:
In some module, define the following:
(defun my-func()
(: io format '"I get called with NOTHING!~n"))
Then you use it like so (depending upon how you import it):
> (my-func)
I get called with NOTHING!
ok
Calling a function with a fixed number of arguments: In some module, define the following:
(defun my-func(a b)
(: io format '"I got called with ~p and ~p~n" (list a b)))
Then you use it like so:
> (my-func '"bread" '"cheese")
I got called with "bread" and "cheese"
ok
Calling a function with optional arguments or calling a function with a variable number of arguments:
- Arguments are fixed in LFE/Erlang functions.
- One can have a dictionary, record, or list be the function argument, and use that to achieve something like variable/optional (and named) arguments.
- One can define multiple functions so that it appears that one is calling a function with optional or a variable number of arguments:
(defmodule args
(export all))
(defun my-func ()
(my-func () () ()))
(defun my-func (a)
(my-func a () ()))
(defun my-func (a b)
(my-func a b ()))
(defun my-func (a b c)
(: io format '"~p ~p ~p~n" (list a b c)))
Here is some example usage:
> (slurp '"args.lfe")
#(ok args)
> (my-func)
[] [] []
ok
> (my-func '"apple")
"apple" [] []
ok
> (my-func '"apple" '"banana")
"apple" "banana" []
ok
> (my-func '"apple" '"banana" '"cranberry")
"apple" "banana" "cranberry"
ok
> (my-func '"apple" '"banana" '"cranberry" '"bad arg")
exception error: #(unbound_func #(my-func 4))
Calling a function with named arguments:
- LFE/Erlang doesn't support named arguments, per se.
- However, by using atoms in function argument patterns (a fairly common pattern), one can achieve similar effects.
- One may also use records or dicts as arguments to achieve similar effects.
Using a function in statement context:
...
(cond ((== count limit) (hit-limit-func arg-1 arg-2))
((/= count limit) (keep-going-func count)))
...
Using a function in first-class context within an expression:
From the LFE REPL:
> (>= 0.5 (: math sin 0.5))
true
Obtaining the return value of a function:
There are many, many ways to assign function outputs to variables in LFE. One fairly standard way is with the (let ...)
form:
(let ((x (: math sin 0.5)))
...)
Distinguishing built-in functions and user-defined functions:
- There is no distinction made in LFE/Erlang between functions that are built-in and those that are not.
- "Built-in" for LFE/Erlang usually can be figured out: if a function has the module name
erlang
, e.g.,(: erlang list_to_integer ... )
, then it's built-in. - Most of the functions that come with LFE/Erlang are not even in the
erlang
module, but exist in other modules (e.g.,io
,math
, etc.) and in OTP. - One uses user/third-party modules in exactly the same way as one uses built-ins and modules that come with the Erlang distribution.
Distinguishing subroutines and functions:
- One commonly made distinction between functions and subroutines is that functions return a value (or reference, etc.) and subroutines do not.
- By this definition, LFE/Erlang does not support the concept of a subroutine; all functions return something.
Stating whether arguments are passed by value or by reference:
- Arguments and returns values are passed by reference in LFE/Erlang.
Is partial application possible?
- Not explicitly.
- However, one can use
lambda
s to achieve the same effect.
Liberty BASIC
'Call a function - Liberty BASIC
'First, function result could not be discarded
' that is, you cannot do "f(x)" as a separate statement
'Calling a function that requires no arguments
res = f() 'brackets required
'Calling a function with a fixed number of arguments
res = g(x)
res = h(x,y)
'Calling a function with optional arguments
'impossible for user-defined functions
'Some build-in functions ex. INSTR and MID$ could be called with last argument omitted
'Calling a function with a variable number of arguments
'impossible
'Calling a function with named arguments
'impossible
'Using a function in statement context
'impossible (see starting notice)
'Using a function in first-class context within an expression
'impossible
'Obtaining the return value of a function
res = g(x)
'Distinguishing built-in functions and user-defined functions
'I would say impossible. Though built-in functions could be EVAL'ed,
'while user-defined would not be called (tries address array instead).
'Still cannot distinguish user-defined function from array.
'Distinguishing subroutines and functions
'then defined, subroutines and functions defined with words
'SUB and FUNCTION (case incensitive)
'Then used, function used as expression (with return value),
res = g(x)
'while subroutines called with special keyword CALL and without brackets
call test x, y
'Stating whether arguments are passed by value or by reference
'Variables passed as arguments into functions and subs are passed "by value" by default
'parameters could be passed "by reference" if formal parameter in sub/function definition uses the "byref" specifier
'Then calling a function, you can prevent pass by reference by changing variable to expression
' like x+0, x$+"" or just (x), (x$)
'Is partial application possible and how
'impossible
Lingo
- Calling a function that requires no arguments
foo()
-- or alternatively:
call(#foo, _movie)
- Calling a function with a fixed number of arguments
foo(1,2,3)
-- or alternatively:
call(#foo, _movie, 1, 2, 3)
- Calling a function with optional arguments
on foo (a, b)
if voidP(b) then b = 1
return a * b
end
put foo(23, 2)
-- 46
put foo(23)
-- 23
- Calling a function with a variable number of arguments
on sum ()
res = 0
repeat with i = 1 to the paramCount
res = res + param(i)
end repeat
return res
end
put sum (1,2,3)
-- 6
- Calling a function with named arguments
Not directly supported, but you can of course re-write any function to only accept a single property list (hash) as argument, which can make sense e.g. for functions that have a lot of optional aruments.
- Using a function in statement context
- Using a function in first-class context within an expression
Lingo has no first-class functions, but the call(...) syntax (see above) allows to identify and use functions specified as "symbols" (e.g. #foo). This allows some "first-class alike" features:
----------------------------------------
-- One of the five native iterative methods defined in ECMAScript 5
-- @param {list} tList
-- @param {symbol} cbFunc
-- @param {object} [cbObj=_movie]
-- @return {list}
----------------------------------------
on map (tList, cbFunc, cbObj)
if voidP(cbObj) then cbObj = _movie
res = []
cnt = tList.count
repeat with i = 1 to cnt
res[i] = call(cbFunc, cbObj, tList[i], i, tList)
end repeat
return res
end
on doubleInt (n)
return n*2
end
l = [1,2,3]
put map(l, #doubleInt)
-- [2, 4, 6]
- Obtaining the return value of a function
x = foo(1,2)
- Distinguishing built-in functions and user-defined functions
In Lingo all user-defined (global) functions are 'methods' of the _movie object, and there is AFAIK no direct way to distinguish those from _movie's built-in functions. But by iterating over of all movie scripts in all castlibs you can get a complete list of all user-defined (global) functions, and then any function not in this list is a built-in function:
on getAllUserFunctions ()
res = []
repeat with i = 1 to _movie.castlib.count
c = _movie.castlib(i)
repeat with j = 1 to c.member.count
m = c.member[j]
if m.type<>#script then next repeat
if m.scripttype=#movie then
functions = m.script.handlers()
repeat with f in functions
res.append(f)
end repeat
end if
end repeat
end repeat
return res
end
put getAllUserFunctions()
-- [#sum, #double, #getAllUserFunctions]
- Distinguishing subroutines and functions
In Lingo functions (also called "handlers") don't have to return anything, so there is no distinction. The return value of a function without a "return ..." line is VOID, and not distinguishable from a function with the explicit line "return VOID".
- Stating whether arguments are passed by value or by reference
In lingo 'objects' are always passed by reference, all other types (e.g. strings, integers, floats) by value. 'Objects' are e.g. lists (arrays), property lists (hashes), images and script instances. The built-in function objectP() returns TRUE (1) for objects and FALSE (0) for non-objects. To prevent the effects of call-by-reference, some object types (lists, property lists and images) support the method duplicate() to clone the object before passing it to a function:
on double (someList)
cnt = someList.count
repeat with i = 1 to cnt
someList[i] = someList[i] * 2
end repeat
end
l = [1,2,3]
double(l)
put l
-- [2, 4, 6]
l = [1,2,3]
double(l.duplicate())
put l
-- [1, 2, 3]
Little
The following examples use buldin functions, standard Tcl commands and some local fuctions.
// Calling a function that requires no arguments
void foo() {puts("Calling a function with no arguments");}
foo();
// Calling a function with a fixed number of arguments
abs(-36);
// Calling a function with optional arguments
puts(nonewline: "nonewline is an optional argument");
puts("\n");
// Calling a function with a variable number of arguments
void var_arg_func(...args) {
puts(length(args));
}
var_arg_func(1, 2);
var_arg_func(1, 2, 3);
// Obtaining the return value of a function
int s = clock("seconds"); //current time in seconds
// Calling a function with named arguments
// format is a named argument in Clock_format
int str = Clock_format(s, format: "%B");
puts(str);
// Stating whether arguments are passed by value or by reference
void f(int a, int &b) { a++; b++; }
{
int a = 0;
int b = 0;
f(a, &b);
puts (a);
puts (b);
}
Lua
-- Lua functions accept any number of arguments; missing arguments are nil-padded, extras are dropped.
function fixed (a, b, c) print(a, b, c) end
fixed() --> nil nil nil
fixed(1, 2, 3, 4, 5) --> 1 2 3
-- True vararg functions include a trailing ... parameter, which captures all additional arguments as a group of values.
function vararg (...) print(...) end
vararg(1, 2, 3, 4, 5) -- 1 2 3 4 5
-- Lua also allows dropping the parentheses if table or string literals are used as the sole argument
print "some string"
print { foo = "bar" } -- also serves as a form of named arguments
-- First-class functions in expression context
print(("this is backwards uppercase"):gsub("%w+", function (s) return s:upper():reverse() end))
-- Functions can return multiple values (including none), which can be counted via select()
local iter, obj, start = ipairs { 1, 2, 3 }
print(select("#", (function () end)())) --> 0
print(select("#", unpack { 1, 2, 3, 4 })) --> 4
-- Partial application
function prefix (pre)
return function (suf) return pre .. suf end
end
local prefixed = prefix "foo"
print(prefixed "bar", prefixed "baz", prefixed "quux")
-- nil, booleans, and numbers are always passed by value. Everything else is always passed by reference.
-- There is no separate notion of subroutines
-- Built-in functions are not easily distinguishable from user-defined functions
Luck
/* Calling a function that requires no arguments */
f();;
/* Calling a function with a fixed number of arguments */
f(1,2);;
/* Calling a function with optional arguments
Note: defining the function is cumbersome but will get easier in future versions. */
f(1,2,new {default with x=3, y=4});;
/* Calling a function with a variable number of arguments */
printf("%d %d %d %d":char*,2,3,4,5);;
/* Calling a function with named arguments
Note: may get syntax sugar in future versions */
f(1,2,new {default with x=3, y=4});;
/* Using a function in statement context (what?) */
f();f();f();;
/* Using a function in first-class context within an expression */
[1,2,3].map(string);;
/* Obtaining the return value of a function */
let x:int = f();;
/* Distinguishing built-in functions and user-defined functions */
/* Builtin function i.e. custom calling convention: */
(@ binop "==" l r);;
/* User defined function i.e. normal function */
f(l)(r);;
/* Distinguishing subroutines and functions: both are supported, but compiler is not aware of difference */
sub();;
fun();;
/* Stating whether arguments are passed by value or by reference */
f(value);; /* by value */
f(&value);; /* by pointer reference */
f(ref(value));; /* by managed reference */
/* Is partial application possible and how */
tasty_curry(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);;
M2000 Interpreter
// Calling a function that requires no arguments ModuleA ' introduce a namespace can have modules/functions/subs, anything inside, and threads. Call FunctionA() ' introduce a namespace can have modules/functions/subs, anything inside. Call LambdaA() ' introduce a namespace can have modules/functions/subs, anything inside. SubAlfa() ' subroutine this has the same scope as the caller, we can use Local statement to shadow variables/arrays Print @Simple() ' simple function this has the same scope as the caller, we can use Local statement to shadow variables/arrays Gosub labelA ' Statement Return used to return from a gosub, no arguments and no local statement used, the code is like any other code in the module/function/lambda scope. No jump out of scope allowed. Gosub 10020 ' Statement Return used to return from a gosub,, no arguments and no local statement used, the code is like any other code in the module/function/lambda scope. No jump out of scope allowed. // Calling a function with a fixed number of arguments ModuleA 100 SubAlfa(100) ' subroutine Print @Simple(100) ' simple function Call FunctionA(100) Call LambdaA(100) // Calling a function with optional arguments ModuleA ?,4 SubAlfa(?) ' subroutine Print @Simple(?) ' simple function Call FunctionA(,4) Call LambdaA(,4) // Calling a function with a variable number of arguments Call FunctionA(1,2,3,4,5) Call LambdaA(1,2,3,4,5) // Calling a function with named arguments ModuleA %X=10, %Z=20 // Using a function in statement context Module A SubAlfa() Call Void FunctionA() Call Void LambdaA() // Using a function in first-class context within an expression Print (lambda (x,y)->{=x**y}(2,3))*8=64 // Obtaining the return value of a function A%=FunctionA%() ' integer part from any numeric type. Also A% if get decimals convert to integer using school rounding (0.5, so 3.5 is 4, 2.5 is 3) A=FunctionA() ' numeric or object A$=FunctionA$() ' string or object which return string A=LambdaA() A$=LambdaA$() A=@SimpleA() A$=@SimpleA$() // Distinguishing built-in functions and user-defined functions Def Cos(x)=100*X ' change the build in Print Cos(3), @Cos(3) ' @Cos() is the build in anyway ' we can't use simple function with same name as a bultin function. // Distinguishing subroutines and functions Name without parenthesis like a command or statement is a Module Name with parentesis without operator is a Sub Name with parenthesis in an expression is a function or array (array come first), using a(*10) we say that it is function even an array a() exist. Name with @ as first symbol and parenthesis like @alfa() is a simple function unless has a builtin name, so is that function. // Stating whether arguments are passed by value or by reference Default:By Value By Reference: Using & at both sides (caller and calee) Function Alfa(&x) { =X : X++ } Print Alfa(&counter) Subs and Simple Functions not need a by reference pass because they are in the same scope from the caller, so actuall we pass by value to be local to those entities. But we can use by reference, except for static variables, and array items. Those can only passed by reference on modules and nornal functions and lambdas (which are normal functions plus more). // Is partial application possible and how A=Lambda (X) -> { =Lambda X (Y) -> { =Y**X } } Cube=A(3) : Square=A(2) Print Cube(2)=8, Square(2)=4 OOP: Functions/Modules can be members of objects. Objects may have a name (they live until code get out of scope) Objects may don't have a name but one or more pointers, (they live until counting references are zero) ObjectA.moduleA is a call to an object method (a module) pointerA=>moduleA is a call to an object by a pointer An object may return values, and may accept parameters too. Also objects if they didn't return values other than a copy of them can be use operators defined as object functions. Objects may have events and fire them using Call Event "simpleevent", param1, param2... Functions and lambda (not simple functions), and object functions can be passed by reference as parameters.
Maple
Calling a function with no arguments:
f()
Calling a function with a fixed number of arguments:
f(1,sin(x), g -> int(g(t),t=0..1)
Calling a function with optional arguments:
f(1, sin(x), g -> int(g(t),t=0..1)
Calling a function with a variable number of arguments:
f(1, sin(x), g -> int(g(t),t=0..1)
Calling a function with named arguments:
f(a,b,method = foo)
Calling a function in a statements context:
f(a); f(b);
Using a function in first-class context within an expression:
f(a) + g(b)
Obtaining the return value of a function:
x := f(1)
Distinguishing built-in functions and user-defined functions:
> type( op, 'builtin' );
true
Distinguishing subroutines and functions: There is no distinction.
Stating whether arguments are passed by value or by reference: All values are passed by value. However, if an argument is a name, then it can be assigned to and, if a value is mutable (such as an array), then it can be modified by the function. This is implemented by function definition; there is no distinction when calling the function.
Partial application is supported by the curry
and rcurry
commands.
Mathematica / Wolfram Language
Calling a function that requires no arguments:
f[]
Calling a function with a fixed number of arguments:
f[1,2]
Calling a function with optional arguments:
f[1,Option1->True]
Calling a function with a variable number of arguments:
f[1,Option1->True]
f[1,Option1->True,Option2->False]
Calling a function with named arguments:
f[Option1->True,Option2->False]
Using a function in statement context:
f[1,2];f[2,3]
Using a function in first-class context within an expression:
(#^2)&[3];
The return value of a function can be formally extracted using Return[] Built-in functions names by convention start with a capital letter. No formal distinction between subroutines and functions. Arguments can be passed by value or by reference.
MATLAB / Octave
% Calling a function that requires no arguments
function a=foo();
a=4;
end;
x = foo();
% Calling a function with a fixed number of arguments
function foo(a,b,c);
%% function definition;
end;
foo(x,y,z);
% Calling a function with optional arguments
function foo(a,b,c);
if nargin<2, b=0; end;
if nargin<3, c=0; end;
%% function definition;
end;
foo(x,y);
% Calling a function with a variable number of arguments
function foo(varargin);
for k=1:length(varargin)
arg{k} = varargin{k};
end;
foo(x,y);
% Calling a function with named arguments
%% does not apply
% Using a function in statement context
%% does not apply
% Using a function in first-class context within an expression
% Obtaining the return value of a function
function [a,b]=foo();
a=4;
b='result string';
end;
[x,y] = foo();
% Distinguishing built-in functions and user-defined functions
fun = 'foo';
if (exist(fun,'builtin'))
printf('function %s is a builtin\n');
elseif (exist(fun,'file'))
printf('function %s is user-defined\n');
elseif (exist(fun,'var'))
printf('function %s is a variable\n');
else
printf('%s is not a function or variable.\n');
end
% Distinguishing subroutines and functions
% there are only scripts and functions, any function declaration starts with the keyword function, otherwise it is a script that runs in the workspace
% Stating whether arguments are passed by value or by reference
% arguments are passed by value, however Matlab has delayed evaluation, such that a copy of large data structures are done only when an element is written to.
Nanoquery
// function with no arguments
no_args()
// function with fixed amount of arguments
three_args(a, b, c)
// nanoquery does not support optional, variable, or named arguments
// obtaining a return value
value = returns_value()
// checking if a function called "func" is user-defined
try
type(func)
println "func is user-defined"
catch
println "func is a built-in or doesn't exist"
end
Nemerle
// no arguments
f()
// fixed arguments
def f(a, b) { ... } // as an aside, functions defined with 'def' use type inference for parameters and return types
f(1, 'a')
// optional arguments
def f(a, b = 0) { ... }
f("hello")
f("goodbye", 2)
f("hey", b = 2) // using the name makes more sense if there's more than one optional argument, obviously
// variable number of arguments
def f(params args) { ... }
def g(a, b, params rest) { ... }
f(1, 2, 3) // arguments should all have the same type or may be coerced to a supertype
g(1.0, 2, "a", "hello")
// named arguments
f(a = 'a', b = 0)
f(b = 0, a = 'a')
f('a', b = 0) // if mixing named and unnamed args, unnamed must be first and in correct order
// statement context
if (f(foo) == 42)
WriteLine($"$foo is the meaning to life, the universe and everything.")
else WriteLine($"$foo is meaningless.")
// first class function in an expression
def a = numList.FoldLeft(f)
// obtaining return value
def a = f(3)
// distinguishing built-in from user functions
// N/A?
// distinguishing subroutines from functions
// N/A
// stating whether passed by value or by reference
// .NET distinguishes between value types and reference types; if a reference type is passed by reference (using ref or out),
// the reference is passed by reference, which would allow a method to modify the object to which the reference refers
def f(a, ref b) { ... }
mutable someVar = "hey there" // doesn't make sense to pass immutable value by ref
f(2, ref someVar)
def g(a, out b) { ... }
mutable someOtherVar // if passed by ref using 'out', the variable needn't be initialized
g(2, out someOtherVar)
// partial application
def f(a, b) { ... }
def g = f(2, _)
def h = f(_, 2)
def a = g(3) // equivalent to: def a = f(2, 3)
def b = h(3) // equivalent to: def b = f(3, 2)
Nim
Translated from Python, when possible:
proc no_args() =
discard
# call
no_args()
proc fixed_args(x, y) =
echo x
echo y
# calls
fixed_args(1, 2) # x=1, y=2
fixed_args 1, 2 # same call
1.fixed_args(2) # same call
proc opt_args(x=1.0) =
echo x
# calls
opt_args() # 1
opt_args(3.141) # 3.141
proc var_args(v: varargs[string, `$`]) =
for x in v: echo x
# calls
var_args(1, 2, 3) # (1, 2, 3)
var_args(1, (2,3)) # (1, (2, 3))
var_args() # ()
## Named arguments
fixed_args(y=2, x=1) # x=1, y=2
## As a statement
if true:
no_args()
proc return_something(x): int =
x + 1
var a = return_something(2)
## First-class within an expression
let x = return_something(19) + 10
let y = 19.return_something() + 10
let z = 19.return_something + 10
OCaml
- Calling a function that requires no arguments:
f ()
(In fact it is impossible to call a function without arguments, when there are no particular arguments we provide the type unit
which is a type that has only one possible value. This type is mainly made for this use.)
- Calling a function with a fixed number of arguments:
f 1 2 3
- Calling a function with optional arguments:
For a function that has this signature:
val f : ?a:int -> int -> unit
here is how to call it with or without the first argument omited:
f 10
f ~a:6 10
Due to partial application, an optional argument always has to be followed by a non-optional argument. If the function needs no additional arguments then we use the type unit
:
g ()
g ~b:1.0 ()
- Calling a function with a variable number of arguments:
This is not possible. The strong OCaml type system does not allow this.
The OCaml programmer will instead provide the variable number of arguments in a list, an array, an enumeration, a set or any structure of this kind.
(But if we really need this for a good reason, it is still possible to use a hack, like it has been done for the function Printf.printf
.)
- Calling a function with named arguments:
Named arguments are called labels.
f ~arg:3
If a variable has the same name than the label we can use this simpler syntax:
let arg = 3 in
f ~arg
- Using a function in statement context:
(* TODO *)
- Using a function in first-class context within an expression:
functions in OCaml are first-class citizen.
- Obtaining the return value of a function:
let ret = f ()
let a, b, c = f () (* if there are several returned values given as a tuple *)
let _ = f () (* if we want to ignore the returned value *)
let v, _ = f () (* if we want to ignore one of the returned value *)
- Distinguishing built-in functions and user-defined functions:
There is no difference.
- Distinguishing subroutines and functions:
OCaml only provides functions.
- Stating whether arguments are passed by value or by reference:
OCaml arguments are always passed by reference. OCaml is an impure functional language, for immutable variables there is no difference if the argument is passed by value or by reference, but for mutable variables the programmer should know that a function is able to modify it.
- How to use partial application:
Just apply less arguments than the total number of arguments.
With partial application, the arguments are applied in the same order than they are defined in the signature of the function, except if there are labeled arguments, then it is possible to use these labels to partially apply the arguments in any order.
Oforth
Oforth provides functions (global prodecure, without receiver) and methods (need a receiver).
Oforth uses RPN notation. Arguments must be on the stack before calling a function or method. So, the same syntax is use for calling a function with or without prameters.
If f is a function and c b a ares objects :
a b c f
will push c then b then a on the stack then call f. Calling f does not describe if f will use 1, 2 or 3 arguments (or none).
Oforth adds a notation to describe parameters used by a function. It is only a way to add information about which parameters will be used by f :
f(a, b, c)
Intepreter will replace this second syntax by the first one. It is only "sugar"...
a b c f
a b f(c)
a f(b, c)
f(a, b, c)
are the same call to function f and the interpreter will translate all of them into the first one. Which parameters are really used by f will depend on f implementation.
Methods need a receiver (the object on which the method will apply and the object that will pushed on th stack when self is used into the method body). The receiver must be on the top of the stack before calling the method. If a, b, c and r are objects and m a method :
a b c r m
will call m with r as its receiver. It is also possible to use the same "sugar" notation used by functions :
r m(a, b, c)
Ol
; note: sign "==>" indicates expected output
;;; Calling a function that requires no arguments
(define (no-args-function)
(print "ok."))
(no-args-function)
; ==> ok.
;;; Calling a function with a fixed number of arguments
(define (two-args-function a b)
(print "a: " a)
(print "b: " b))
(two-args-function 8 13)
; ==> a: 8
; ==> b: 13
;;; Calling a function with optional arguments
(define (optional-args-function a . args)
(print "a: " a)
(if (null? args)
(print "no optional arguments"))
(if (less? 0 (length args))
(print "b: " (car args)))
(if (less? 1 (length args))
(print "c: " (cadr args)))
; etc...
)
(optional-args-function 3)
; ==> a: 3
; ==> no optional arguments
(optional-args-function 3 8)
; ==> a: 3
; ==> b: 8
(optional-args-function 3 8 13)
; ==> a: 3
; ==> b: 8
; ==> c: 13
(optional-args-function 3 8 13 77)
; ==> a: 3
; ==> b: 8
; ==> c: 13
;;; Calling a function with a variable number of arguments
; /same as optional arguments
;;; Calling a function with named arguments
; /no named arguments "from the box" is provided, but it can be easily simulated using builtin associative arrays (named "ff")
(define (named-args-function args)
(print "a: " (get args 'a 8)) ; 8 is default value if no variable value given
(print "b: " (get args 'b 13)); same as above
)
(named-args-function #empty)
; ==> a: 8
; ==> b: 13
(named-args-function (list->ff '((a . 3))))
; ==> a: 3
; ==> b: 13
; or nicer (and shorter) form available from ol version 2.1
(named-args-function '{a 3})
; ==> a: 3
; ==> b: 13
(named-args-function '{b 7})
; ==> a: 8
; ==> b: 7
(named-args-function '{a 3 b 7})
; ==> a: 3
; ==> b: 7
;;; Using a function in first-class context within an expression
(define (first-class-arg-function arg a b)
(print (arg a b))
)
(first-class-arg-function + 2 3)
; ==> 5
(first-class-arg-function - 2 3)
; ==> -1
;;; Using a function in statement context
(let ((function (lambda (x) (* x x))))
(print (function 4))
; ==> 16
;(print (function 4))
; ==> What is 'function'?
;;; Obtaining the return value of a function
(define (return-value-function)
(print "ok.")
123)
(let ((result (return-value-function)))
(print result))
; ==> ok.
; ==> 123
;;; Obtaining the return value of a function while breaking the function execution (for example infinite loop)
(print
(call/cc (lambda (return)
(let loop ((n 0))
(if (eq? n 100)
(return (* n n)))
(loop (+ n 1))))))) ; this is infinite loop
; ==> 10000
;;; Is partial application possible and how
(define (make-partial-function n)
(lambda (x y)
(print (n x y)))
)
(define plus (make-partial-function +))
(define minus (make-partial-function -))
(plus 2 3)
; ==> 5
(minus 2 3)
; ==> -1
;;; Distinguishing built-in functions and user-defined functions
; ol has no builtin functions but only eight builtin forms: quote, values, lambda, setq, letq, ifeq, either, values-apply.
; all other functions is "user-defined", and some of them defined in base library, for example (scheme core) defines if, or, and, zero?, length, append...
;;; Distinguishing subroutines and functions
; Both subroutines and functions is a functions in Ol.
; Btw, the "subroutine" has a different meaning in Ol - the special function that executes simultaneously in own context. The intersubroutine messaging mechanism is provided, sure.
;;; Stating whether arguments are passed by value or by reference
; The values in Ol always passed as values and objects always passed as references. If you want to pass an object copy - make a copy by yourself.
ooRexx
This is to show how a built-in function is invoked when an internal function on the dame name in present.
say 'DATE'()
Say date()
Exit
daTe: Return 'my date'
- Output:
H:\>rexx fdate 31 Mar 2022 my date
PARI/GP
Calling a function is done in GP by writing the name of the function and the arguments, if any, in parentheses. As of version 2.5.0, function calls must use parentheses; some earlier versions allowed functions with an arity of 0 to be called without parentheses. However built-in constants (which are implicit functions of the current precision) can still be called without parentheses.
Optional arguments can be skipped, leaving commas in place. Trailing commas can be dropped.
Functions can be used when statements would be expected without change.
f(); \\ zero arguments
sin(Pi/2); \\ fixed number of arguments
vecsort([5,6]) != vecsort([5,6],,4) \\ optional arguments
Str("gg", 1, "hh") \\ variable number of arguments
call(Str, ["gg", 1, "hh"]) \\ variable number of arguments in a vector
(x->x^2)(3); \\ first-class
x = sin(0); \\ get function value
Built-in functions are like user-defined functions in current versions. In older versions built-in functions cannot be passed as closures.
Most arguments are passed by reference. Some built-in functions accept arguments (e.g., flags) that are not GEN
s; these are passed by value or reference depending on their C type. See the User's Guide to the PARI Library section 5.7.3, "Parser Codes".
Pascal
see also: Delphi and Free Pascal
Calling a nullary function and obtaining its return value:
foo
Calling an n-ary function (n ≥ 1) and obtaining its return value:
foo(1, 'abc', true)
Following are not possible in Pascal as defined by the ISO standards (ISO 7185 and ISO 10206).
- optional arguments
- variable number of arguments
- named arguments
- using a function call as a statement
- distinguishing built-in functions and user-defined functions
- distinguishing subroutines and functions
- stating at the call site whether arguments are passed by value or by reference
- partial application
Perl
The most common syntax; simply calls the function foo on the argument(s) provided.
foo(); # Call foo on the null list
&foo(); # Ditto
foo($arg1, $arg2); # Call foo on $arg1 and $arg2
&foo($arg1, $arg2); # Ditto; ignores prototypes
Call foo() as a bareword. Only works after the function has been declared, which can be done normally or with the use subs pragma.
foo;
Call foo() with the current values of @_
&foo;
Call foo() with the current values of @_, discarding the previous stack frame. Not your grandfather's (harmful) goto, although the keyword can do both.
goto &foo;
For subroutines stored in references (anonymous subroutines).
&$fooref('foo', 'bar');
&{$fooref}('foo', 'bar');
$fooref->('foo', 'bar');
Phix
Phix has three kinds of routines: procedure, function, and type. A procedure does not return a value, whereas a function does. A type is a specialised kind of function that permits declarations of instances which are automatically validated whenever they are changed, further a type routine always returns either true or false.
- Phix does not allow implicit discard of function results. The explicit discard statement takes the form
{} = myfunction()
- This is in fact a simple contraction of standard multiple assigment (which can be nested as deeply as you like):
{cities,populations} = columnize(muncipalities)
{{},populations} = columnize(muncipalities) -- discard result[1]
{cities,{}} = columnize(muncipalities) -- discard result[2]
{cities} = columnize(muncipalities) -- ""
- Calling a function with no parameters still requires the "()" empty argument list.
- Optional arguments are denoted simply by the presence of a default, and must be grouped on the right:
function myfunction(integer a, string b="default") return {a,b} end function --? myfunction() -- illegal, compile-time error ?myfunction(1) -- displays {1,"default"} ?myfunction(2,"that") -- displays {2,"that"}
- Sequence parameters can be of any length, which is another way to implement optional/variable number of arguments.
- Named arguments can be specified in any order, with an error if any non-optional parameters are missing:
?myfunction(b:="then",a:=3) -- displays {3,"then"}
--?myfunction(b:="though") -- compile-time error
- The programmer is free to use either positional parameters or named parameters, or a mixture of both (with positional parameters first).
- Phix support first-class functions directly, as integers, along with an older routine_id mechanism:
constant integer r_myfunction = routine_id("myfunction"), first_class = myfunction ?call_func(r_myfunction,{1}) -- displays {1,"default"} ?call_func(myfunction,{1}) -- "" ?call_func(first_class,{1}) -- "" ?first_class(1) -- ""
The value of r_my_func can be passed as an argument to any routine, or stored in a table, and invoked in a similar fashion.
Note however that for performance reasons some builtins do not have a proper routine_id; if you need one you must write a trivial one-line wrapper.
(For a full list, see psym.e/syminit() calls to AutoAsm(), whereas calls to initialAutoEntry() therein indicate builtins that can have routine_ids.)
(Routines that do not have a proper routine_id do not support named parameters either.)
(One day the compiler may be enhanced to automatically create one-line wrappers as needed, but that is quite near the end of a fairly long to-do list.)
- Partial application is usually achieved through a single variable-length "user_data" parameter within a call_func() expression.
- All arguments are passed by reference with copy-on-write semantics: to modify the value of a parameter you must both return and assign it, as in:
s = append(s,item)
- Implicit forward calls are supported, as are optional explicit forward declarations, which can occasionally cure compilation error messages.
Phixmonti
/# Phixmonti does not distinguish between subroutines and functions.
Each word (as they are called), takes its arguments (if any) from the data stack. #/
def saludo
"Hola mundo" print nl
enddef
saludo /# 'saludo' is a user-defined word. #/
2 3 + print /# The '+' sign and 'print' are intrinsic words. The return value is deposited on the data stack #/
PicoLisp
When calling a funcion in PicoLisp directly (does this mean "in a statement context"?), it is always surrounded by parentheses, with or without arguments, and for any kind of arguments (evaluated or not):
(foo)
(bar 1 'arg 2 'mumble)
When a function is used in a "first class context" (e.g. passed to another function), then it is not yet called. It is simply used. Technically, a function can be either a number (a built-in function) or a list (a Lisp-level function) in PicoLisp):
(mapc println Lst) # The value of 'printlin' is a number
(apply '((A B C) (foo (+ A (* B C)))) (3 5 7)) # A list is passed
Any argument to a function may be evaluated or not, depending on the function. For example, 'setq' evaluates every second argument
(setq A (+ 3 4) B (* 3 4))
i.e. the first argument 'A' is not evaluated, the second evaluates to 7, 'B' is not evaluated, then the fourth evaluates to 12.
PureBasic
Procedure Saludo()
PrintN("Hola mundo!")
EndProcedure
Procedure.s Copialo(txt.s, siNo.b, final.s = "")
Define nuevaCadena.s, resul.s
For cont.b = 1 To siNo
nuevaCadena + txt
Next
Resul = Trim(nuevaCadena) + final
ProcedureReturn resul
EndProcedure
Procedure testNumeros(a.i, b.i, c.i = 0)
PrintN(Str(a) + #TAB$ + Str(b) + #TAB$ + Str(c))
EndProcedure
Procedure testCadenas(txt.s)
For cont.b = 1 To Len(txt)
Print(Mid(txt,cont,1))
Next cont
EndProcedure
OpenConsole()
Saludo()
PrintN(Copialo("Saludos ", 6))
PrintN(Copialo("Saludos ", 3, "!!"))
PrintN("")
testNumeros(1, 2, 3)
testNumeros(1, 2)
PrintN("")
testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")
Input()
CloseConsole()
- Output:
Same as FreeBASIC entry.
Python
Under the hood all Python function/method parameters are named. All arguments can be passed as name=value pairs or as a dictionary containing such pairs using the myfunc(**key_args) (apply over dictionary) syntax). One can also "apply" a function over a sequence of arguments using the syntax: myfunc(*args) as noted in comments below. Parameters can be mixed so long parameters with default values (optional arguments) follow any "positional" (required) parameters, and catchall parameter (*args) follow those, and any "keyword arguments' parameter" is last. (Any function can only have up to one "catchall" or *args' parameter and up to one "keyword args" **kwargs parameter).
def no_args():
pass
# call
no_args()
def fixed_args(x, y):
print('x=%r, y=%r' % (x, y))
# call
fixed_args(1, 2) # x=1, y=2
## Can also called them using the parameter names, in either order:
fixed_args(y=2, x=1)
## Can also "apply" fixed_args() to a sequence:
myargs=(1,2) # tuple
fixed_args(*myargs)
def opt_args(x=1):
print(x)
# calls
opt_args() # 1
opt_args(3.141) # 3.141
def var_args(*v):
print(v)
# calls
var_args(1, 2, 3) # (1, 2, 3)
var_args(1, (2,3)) # (1, (2, 3))
var_args() # ()
## Named arguments
fixed_args(y=2, x=1) # x=1, y=2
## As a statement
if 1:
no_args()
## First-class within an expression
assert no_args() is None
def return_something():
return 1
x = return_something()
def is_builtin(x):
print(x.__name__ in dir(__builtins__))
# calls
is_builtin(pow) # True
is_builtin(is_builtin) # False
# Very liberal function definition
def takes_anything(*args, **kwargs):
for each in args:
print(each)
for key, value in sorted(kwargs.items()):
print("%s:%s" % (key, value))
# Passing those to another, wrapped, function:
wrapped_fn(*args, **kwargs)
# (Function being wrapped can have any parameter list
# ... that doesn't have to match this prototype)
## A subroutine is merely a function that has no explicit
## return statement and will return None.
## Python uses "Call by Object Reference".
## See, for example, http://www.python-course.eu/passing_arguments.php
## For partial function application see:
## http://rosettacode.org/wiki/Partial_function_application#Python
QBasic
FUNCTION Copialo$ (txt$, siNo, final$)
DIM nuevaCadena$
FOR cont = 1 TO siNo
nuevaCadena$ = nuevaCadena$ + txt$
NEXT cont
Copialo$ = LTRIM$(RTRIM$(nuevaCadena$)) + final$
END FUNCTION
SUB Saludo
PRINT "Hola mundo!"
END SUB
SUB testCadenas (txt$)
FOR cont = 1 TO LEN(txt$)
PRINT MID$(txt$, cont, 1); "";
NEXT cont
END SUB
SUB testNumeros (a, b, c)
PRINT a, b, c
END SUB
CALL Saludo
PRINT Copialo$("Saludos ", 6, "")
PRINT Copialo$("Saludos ", 3, "!!")
PRINT
CALL testNumeros(1, 2, 3)
CALL testNumeros(1, 2, 0)
PRINT
CALL testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")
- Output:
Igual que la entrada de FreeBASIC.
Quackery
Words in Quackery take zero or more arguments from the (programmer accessible) data stack, and return zero or more results to the data stack.
In this dialogue in the Quackery shell, /mod
takes two arguments and returns two results, pack
takes three arguments (the topmost argument on the stack (2
) specifies how many more arguments it is to take from the stack), echo
takes one argument and returns no results, and cr
takes no arguments and returns no results.
/O> 123 7 /mod ... Stack: 17 4 /O> 2 pack ... Stack: [ 17 4 ] /O> echo cr ... [ 17 4 ] Stack empty.
Words can also take one or more items (nests, words or numbers) and arbitrary strings of text following the word as arguments. For example, times
performs the item following it a specified number of times, and say
echoes the string following it to the terminal.
/O> 4 times [ 3 times [ say "badger" sp ] cr ] ... 2 times [ say "mushroom" sp ] cr ... badger badger badger badger badger badger badger badger badger badger badger badger mushroom mushroom Stack empty.
R
Translated from Python, when possible.
### Calling a function that requires no arguments
no_args <- function() NULL
no_args()
### Calling a function with a fixed number of arguments
fixed_args <- function(x, y) print(paste("x=", x, ", y=", y, sep=""))
fixed_args(1, 2) # x=1, y=2
fixed_args(y=2, x=1) # y=1, x=2
### Calling a function with optional arguments
opt_args <- function(x=1) x
opt_args() # x=1
opt_args(3.141) # x=3.141
### Calling a function with a variable number of arguments
var_args <- function(...) print(list(...))
var_args(1, 2, 3)
var_args(1, c(2,3))
var_args()
### Calling a function with named arguments
fixed_args(y=2, x=1) # x=1, y=2
### Using a function in statement context
if (TRUE) no_args()
### Using a function in first-class context within an expression
print(no_args)
### Obtaining the return value of a function
return_something <- function() 1
x <- return_something()
x
### Distinguishing built-in functions and user-defined functions
# Not easily possible. See
# http://cran.r-project.org/doc/manuals/R-ints.html#g_t_002eInternal-vs-_002ePrimitive
# for details.
### Distinguishing subroutines and functions
# No such distinction.
### Stating whether arguments are passed by value or by reference
# Pass by value.
### Is partial application possible and how
# Yes, see http://rosettacode.org/wiki/Partial_function_application#R
Racket
#lang racket
;; Calling a function that requires no arguments
(foo)
;; Calling a function with a fixed number of arguments
(foo 1 2 3)
;; Calling a function with optional arguments
;; Calling a function with a variable number of arguments
(foo 1 2 3) ; same in both cases
;; Calling a function with named arguments
(foo 1 2 #:x 3) ; using #:keywords for the names
;; Using a function in statement context
;; Using a function in first-class context within an expression
;; Obtaining the return value of a function
;; -> Makes no sense for Racket, as well as most other functional PLs
;; Distinguishing built-in functions and user-defined functions
(primitive? foo)
;; but this is mostly useless, since most of Racket is implemented in
;; itself
;; Distinguishing subroutines and functions
;; -> No difference, though `!' is an idiomatic suffix for names of
;; side-effect functions, and they usually return (void)
;; Stating whether arguments are passed by value or by reference
;; -> Always by value, but it's possible to implement languages with
;; other argument passing styles, including passing arguments by
;; reference (eg, there is "#lang algol60")
;; Is partial application possible and how
(curry foo 1 2) ; later apply this on 3
(λ(x) (foo 1 2 x)) ; a direct way of doing the same
Raku
(formerly Perl 6)
Theory
Fundamentally, nearly everything you do in Raku is a function call if you look hard enough. At the lowest level, a function call merely requires a reference to any kind of invokable object, and a call to its postcircumfix:<( )> method. However, there are various forms of sugar and indirection that you can use to express these function calls differently. In particular, operators are all just sugar for function calls.
Calling a function that requires no arguments:
foo # as list operator
foo() # as function
foo.() # as function, explicit postfix form
$ref() # as object invocation
$ref.() # as object invocation, explicit postfix
&foo() # as object invocation
&foo.() # as object invocation, explicit postfix
::($name)() # as symbolic ref
Calling a function with exactly one argument:
foo 1 # as list operator
foo(1) # as named function
foo.(1) # as named function, explicit postfix
$ref(1) # as object invocation (must be hard ref)
$ref.(1) # as object invocation, explicit postfix
1.$foo # as pseudo-method meaning $foo(1) (hard ref only)
1.$foo() # as pseudo-method meaning $foo(1) (hard ref only)
1.&foo # as pseudo-method meaning &foo(1) (is hard foo)
1.&foo() # as pseudo-method meaning &foo(1) (is hard foo)
1.foo # as method via dispatcher
1.foo() # as method via dispatcher
1."$name"() # as method via dispatcher, symbolic
+1 # as operator to prefix:<+> function
Method calls are included here because they do eventually dispatch to a true function via a dispatcher. However, the dispatcher in question is not going to dispatch to the same set of functions that a function call of that name would invoke. That's why there's a dispatcher, after all. Methods are declared with a different keyword, method, in Raku, but all that does is install the actual function into a metaclass. Once it's there, it's merely a function that expects its first argument to be the invocant object. Hence we feel justified in including method call syntax as a form of indirect function call.
Operators like + also go through a dispatcher, but in this case it is multiply dispatched to all lexically scoped candidates for the function. Hence the candidate list is bound early, and the function itself can be bound early if the type is known. Raku maintains a clear distinction between early-bound linguistic constructs that force Perlish semantics, and late-bound OO dispatch that puts the objects and/or classes in charge of semantics. (In any case, &foo, though being a hard ref to the function named "foo", may actually be a ref to a dispatcher to a list of candidates that, when called, makes all the candidates behave as a single unit.)
Calling a function with exactly two arguments:
foo 1,2 # as list operator
foo(1,2) # as named function
foo.(1,2) # as named function, explicit postfix
$ref(1,2) # as object invocation (must be hard ref)
$ref.(1,2) # as object invocation, explicit postfix
1.$foo: 2 # as pseudo-method meaning $foo(1,2) (hard ref only)
1.$foo(2) # as pseudo-method meaning $foo(1,2) (hard ref only)
1.&foo: 2 # as pseudo-method meaning &foo(1,2) (is hard foo)
1.&foo(2) # as pseudo-method meaning &foo(1,2) (is hard foo)
1.foo: 2 # as method via dispatcher
1.foo(2) # as method via dispatcher
1."$name"(2) # as method via dispatcher, symbolic
1 + 2 # as operator to infix:<+> function
Optional arguments don't look any different from normal arguments. The optionality is all on the binding end.
Calling a function with a variable number of arguments (varargs):
foo @args # as list operator
foo(@args) # as named function
foo.(@args) # as named function, explicit postfix
$ref(@args) # as object invocation (must be hard ref)
$ref.(@args) # as object invocation, explicit postfix
1.$foo: @args # as pseudo-method meaning $foo(1,@args) (hard ref)
1.$foo(@args) # as pseudo-method meaning $foo(1,@args) (hard ref)
1.&foo: @args # as pseudo-method meaning &foo(1,@args)
1.&foo(@args) # as pseudo-method meaning &foo(1,@args)
1.foo: @args # as method via dispatcher
1.foo(@args) # as method via dispatcher
1."$name"(@args) # as method via dispatcher, symbolic
@args X @blargs # as list infix operator to infix:<X>
Note: whether a function may actually be called with a variable number of arguments depends entirely on whether a signature accepts a list at that position in the argument list, but describing that is not the purpose of this task. Suffice to say that we assume here that the foo function is declared with a signature of the form (*@params). The calls above might be interpreted as having a single array argument if the signature indicates a normal parameter instead of a variadic one. What you cannot do in Raku (unlike Perl 5) is pass an array as several fixed arguments. By default it must either represent a single argument, or be part of a variadic list. You can force the extra level of argument list interpolation using a prefix | however:
my @args = 1,2,3;
foo(|@args); # equivalent to foo(1,2,3)
Calling a function with named arguments:
foo :a, :b(4), :!c, d => "stuff"
foo(:a, :b(4), :!c, d => "stuff")
...and so on. Operators may also be called with named arguments, but only colon adverbials are allowed:
1 + 1 :a :b(4) :!c :d("stuff") # calls infix:<+>(1,1,:a, :b(4), :!c, d => "stuff")
Using a function in statement context:
foo(); bar(); baz(); # evaluate for side effects
Using a function in first class context within an expression:
1 / find-a-func(1,2,3)(4,5,6) ** 2;
Obtaining the return value of a function:
my $result = somefunc(1,2,3) + 2;
There is no difference between calling builtins and user-defined functions and operators (or even control stuctures). This was a major design goal of Raku, and apart from a very few low-level primitives, all of Raku can be written in Raku.
There is no difference between calling subroutines and functions in Raku, other than that calling a function in void context that has no side effects is likely to get you a "Useless use of..." warning. And, of course, the fact that pure functions can participate in more optimizations such as constant folding.
By default, arguments are passed readonly, which allows the implementation to decide whether pass-by-reference or pass-by-value is more efficient on a case-by-case basis. Explicit lvalue, reference, or copy semantics may be requested on a parameter-by-parameter basis, and the entire argument list may be processed raw if that level of control is needed.
Practice
Demonstrating each of the above-mentioned function calls with actual running code, along with the various extra definitions required to make them work (in certain cases). Arguments are checked, and function name / run-sequence number are displayed upon success.
{
state $n;
multi f () { print ' f' ~ ++$n }
multi f ($a) { die if 1 != $a; print ' f' ~ ++$n }
multi f ($a,$b) { die if 3 != $a+$b; print ' f' ~ ++$n }
multi f (@a) { die if @a != [2,3,4]; print ' f' ~ ++$n }
multi f ($a,$b,$c) { die if 2 != $a || 4 != $c; print ' f' ~ ++$n }
sub g ($a,*@b) { die if @b != [2,3,4] || 1 != $a; print ' g' ~ ++$n }
my \i = -> { print ' i' ~ ++$n }
my \l = -> $a { die if 1 != $a; print ' l' ~ ++$n }
my \m = -> $a,$b { die if 1 != $a || 2 != $b; print ' m' ~ ++$n }
my \n = -> @a { die if @a != [2,3,4]; print ' n' ~ ++$n }
Int.^add_method( 'j', method ()
{ die if 1 != self; print ' j' ~ ++$n } );
Int.^add_method( 'k', method ($a)
{ die if 1 != self || 2 != $a; print ' k' ~ ++$n } );
Int.^add_method( 'h', method (@a)
{ die if @a != [2,3,4] || 1 != self; print ' h' ~ ++$n } );
my $ref = &f; # soft ref
my $f := &f; # hard ref
my $g := &g; # hard ref
my $f-sym = '&f'; # symbolic ref
my $g-sym = '&g'; # symbolic ref
my $j-sym = 'j'; # symbolic ref
my $k-sym = 'k'; # symbolic ref
my $h-sym = 'h'; # symbolic ref
# Calling a function with no arguments:
f; # 1 as list operator
f(); # 2 as function
i.(); # 3 as function, explicit postfix form # defined via pointy-block
$ref(); # 4 as object invocation
$ref.(); # 5 as object invocation, explicit postfix
&f(); # 6 as object invocation
&f.(); # 7 as object invocation, explicit postfix
::($f-sym)(); # 8 as symbolic ref
# Calling a function with exactly one argument:
f 1; # 9 as list operator
f(1); # 10 as named function
l.(1); # 11 as named function, explicit postfix # defined via pointy-block
$f(1); # 12 as object invocation (must be hard ref)
$ref.(1); # 13 as object invocation, explicit postfix
1.$f; # 14 as pseudo-method meaning $f(1) (hard ref only)
1.$f(); # 15 as pseudo-method meaning $f(1) (hard ref only)
1.&f; # 16 as pseudo-method meaning &f(1) (is hard f)
1.&f(); # 17 as pseudo-method meaning &f(1) (is hard f)
1.j; # 18 as method via dispatcher # requires custom method, via 'Int.^add_method'
1.j(); # 19 as method via dispatcher
1."$j-sym"(); # 20 as method via dispatcher, symbolic
# Calling a function with exactly two arguments:
f 1,2; # 21 as list operator
f(1,2); # 22 as named function
m.(1,2); # 23 as named function, explicit postfix # defined via pointy-block
$ref(1,2); # 24 as object invocation (must be hard ref)
$ref.(1,2); # 25 as object invocation, explicit postfix
1.$f: 2; # 26 as pseudo-method meaning $f(1,2) (hard ref only)
1.$f(2); # 27 as pseudo-method meaning $f(1,2) (hard ref only)
1.&f: 2; # 28 as pseudo-method meaning &f(1,2) (is hard f)
1.&f(2); # 29 as pseudo-method meaning &f(1,2) (is hard f)
1.k: 2; # 30 as method via dispatcher # requires custom method, via 'Int.^add_method'
1.k(2); # 31 as method via dispatcher
1."$k-sym"(2); # 32 as method via dispatcher, symbolic
# Calling a function with a variable number of arguments (varargs):
my @args = 2,3,4;
f @args; # 33 as list operator
f(@args); # 34 as named function
n.(@args); # 35 as named function, explicit postfix # defined via pointy-block
$ref(@args); # 36 as object invocation (must be hard ref)
$ref.(@args); # 37 as object invocation, explicit postfix
1.$g: @args; # 38 as pseudo-method meaning $f(1,@args) (hard ref)
1.$g(@args); # 39 as pseudo-method meaning $f(1,@args) (hard ref)
1.&g: @args; # 40 as pseudo-method meaning &f(1,@args)
1.&g(@args); # 41 as pseudo-method meaning &f(1,@args)
1.h: @args; # 42 as method via dispatcher # requires custom method, via 'Int.^add_method'
1.h(@args); # 43 as method via dispatcher
1."$h-sym"(@args); # 44 as method via dispatcher, symbolic
f(|@args); # 45 equivalent to f(1,2,3)
}
- Output:
f1 f2 i3 f4 f5 f6 f7 f8 f9 f10 l11 f12 f13 f14 f15 f16 f17 j18 j19 j20 f21 f22 m23 f24 f25 f26 f27 f28 f29 k30 k31 k32 f33 f34 n35 f36 f37 g38 g39 g40 g41 h42 h43 h44 f45
REXX
version 1
/*REXX pgms demonstrates various methods/approaches of invoking/calling a REXX function.*/
/*╔════════════════════════════════════════════════════════════════════╗
║ Calling a function that REQUIRES no arguments. ║
║ ║
║ In the REXX language, there is no way to require the caller to not ║
║ pass arguments, but the programmer can check if any arguments were ║
║ (or weren't) passed. ║
╚════════════════════════════════════════════════════════════════════╝*/
yr= yearFunc() /*the function name is caseless if it isn't */
/*enclosed in quotes (') or apostrophes (").*/
say 'year=' yr
exit /*stick a fork in it, we're all done. */
yearFunc: procedure /*function ARG returns the # of args.*/
errmsg= '***error***' /*an error message eyecatcher string. */
if arg() \== 0 then say errmsg "the YEARFUNC function won't accept arguments."
return left( date('Sorted'), 3)
/*╔════════════════════════════════════════════════════════════════════╗
║ Calling a function with a fixed number of arguments. ║
║ ║
║ I take this to mean that the function requires a fixed number of ║
║ arguments. As above, REXX doesn't enforce calling (or invoking) ║
║ a (any) function with a certain number of arguments, but the ║
║ programmer can check if the correct number of arguments have been ║
║ specified (or not). ║
║ In some languages, these are known as "generic" functions. ║
╚════════════════════════════════════════════════════════════════════╝*/
ggg= FourFunc(12, abc, 6+q, zz%2, 'da 5th disagreement')
say 'ggg squared=' ggg**2
exit /*stick a fork in it, we're all done. */
FourFunc: procedure; parse arg a1,a2,a3 /*obtain the first three arguments. */
a4= arg(4) /*another way to obtain the 4th arg. */
errmsg= '***error***' /*an error message eyecatcher string. */
if arg() \== 4 then do
say err "FourFunc function requires 4 arguments,"
say err "but instead it found" arg() 'arguments.'
exit 13 /*exit function with a RC of 13*/
end
return a1 + a2 + a3 + a4
/*╔════════════════════════════════════════════════════════════════════╗
║ Calling a function with optional arguments. ║
║ ║
║ Note that not passing an argument isn't the same as passing a null ║
║ argument (a REXX variable whose value is length zero). ║
╚════════════════════════════════════════════════════════════════════╝*/
x= 12; w= x/2; y= x**2; z= x//7 /* z is x modulo seven. */
say 'sum of w, x, y, & z=' SumIt(w,x,y,,z) /*pass five args, the 4th arg is "null"*/
exit /*stick a fork in it, we're all done. */
SumIt: procedure
$= 0 /*initialize the sum to zero. */
do j=1 for arg() /*obtain the sum of a number of args. */
if arg(j,'E') then $= $ + arg(j) /*the Jth arg may have been omitted. */
end /*j*/
return $
/*╔════════════════════════════════════════════════════════════════════╗
║ Calling a function with a variable number of arguments. ║
║ ║
║ This situation isn't any different then the previous example. ║
║ It's up to the programmer to code how to utilize the arguments. ║
╚════════════════════════════════════════════════════════════════════╝*/
/*╔════════════════════════════════════════════════════════════════════╗
║ Calling a function with named arguments. ║
║ ║
║ REXX allows almost anything to be passed, so the following is one ║
║ way this can be accomplished. ║
╚════════════════════════════════════════════════════════════════════╝*/
what= parserFunc('name=Luna', "gravity=.1654", 'moon=yes')
say 'name=' common.name
gr= common.gr
say 'gravity=' gr
exit /*stick a fork in it, we're all done. */
parseFunc: procedure expose common.
do j=1 for arg()
parse var arg(j) name '=' val
upper name /*uppercase it.*/
call value 'COMMON.'name,val
end
return arg()
/*╔════════════════════════════════════════════════════════════════════╗
║ Calling a function in statement context. ║
║ ║
║ REXX allows functions to be called (invoked) two ways, the first ║
║ example (above) is calling a function in statement context. ║
╚════════════════════════════════════════════════════════════════════╝*/
/*╔════════════════════════════════════════════════════════════════════╗
║ Calling a function in within an expression. ║
║ ║
║ This is a variant of the first example. ║
╚════════════════════════════════════════════════════════════════════╝*/
yr= yearFunc() + 20
say 'two decades from now, the year will be:' yr
exit /*stick a fork in it, we're all done. */
/*╔════════════════════════════════════════════════════════════════════╗
║ Obtaining the return value of a function. ║
║ ║
║ There are 2 ways to get the (return) value (RESULT) of a function. ║
╚════════════════════════════════════════════════════════════════════╝*/
currYear= yearFunc()
say 'the current year is' currYear
call yearFunc
say 'the current year is' result /*result can be RESULT, it is caseless.*/
/*╔════════════════════════════════════════════════════════════════════╗
║ Distinguishing built-in functions and user-defined functions. ║
║ ║
║ One objective of the REXX language is to allow the user to use any ║
║ function (or subroutine) name whether or not there is a built-in ║
║ function with the same name (there isn't a penality for this). ║
╚════════════════════════════════════════════════════════════════════╝*/
/*date: as in going out with someone. */
qqq= date() /*number of real dates that Bob was on.*/
/*hopefully, it accurately counts dates*/
say "Bob's been out" qqq 'times.'
www= 'DATE'("USA") /*returns date in format mm/dd/yyyy */
/*any function in quotes is external. */
exit /*stick a fork in it, we're all done. */
date: return 4 /*Bob only "went out" 4 times, no need */
/* to actually count, he quit after 4. */
/*╔════════════════════════════════════════════════════════════════════╗
║ Distinguishing subroutines and functions. ║
║ ║
║ There is no programmatic difference between subroutines and ║
║ functions if the subroutine returns a value (which effectively ║
║ makes it a function). REXX allows you to call a function as if ║
║ it were a subroutine. ║
╚════════════════════════════════════════════════════════════════════╝*/
/*╔════════════════════════════════════════════════════════════════════╗
║ In REXX, all arguments are passed by value, never by name, but it ║
║ is possible to accomplish this if the variable's name is passed ║
║ and the subroutine/function could use the built-in-function VALUE ║
║ to retrieve the variable's value. ║
╚════════════════════════════════════════════════════════════════════╝*/
/*╔════════════════════════════════════════════════════════════════════╗
║ In the REXX language, partial application is possible, depending ║
║ how partial application is defined; I prefer the 1st definition ║
║ (as per the "discussion" for "Partial Function Application" task: ║
║ 1. The "syntactic sugar" that allows one to write some examples ║
║ are: map (f 1 9) [1..9] ║
║ or: map (f(1,_,9)) [1, ..., 9] ║
╚════════════════════════════════════════════════════════════════════╝*/
version 2
/* REXX ***************************************************************
* 29.07.2013 Walter Pachl trying to address the task concisely
***********************************************************************
* f1 Calling a function that requires no arguments
* f2 Calling a function with a fixed number of arguments
* f3 Calling a function with optional arguments
* f4 Calling a function with a variable number of arguments
* f5 Calling a function with named arguments
* f6 Using a function in statement context
* f7 Using a function within an expression
* f8 Obtaining the return value of a function
* f8(...) is replaced by the returned value
* call f8 ... returned value is in special vatiable RESULT
* f9 Distinguishing built-in functions and user-defined functions
* bif is enforced by using its name quoted in uppercase
* fa,fb Distinguishing subroutines and functions
* Stating whether arguments are passed by value or by reference
* Arguments are passed by value
* ooRexx supports passing by reference (Use Arg instruction)
* Is partial application possible and how
* no ideas
**********************************************************************/
say f1()
Say f2(1,2,3)
say f2(1,2,3,4)
say f3(1,,,4)
Say f4(1,2)
Say f4(1,2,3)
a=4700; b=11;
Say f5('A','B')
f6() /* returned value is used as command */
x=f7()**2
call f8 1,2; Say result '=' f8(1,2)
f9: Say 'DATE'('S') date()
call fa 11,22; Say result '=' fa(1,,
2) /* the second comma above is for line continuation */
Signal On Syntax
Call fb 1,2
x=fb(1,2)
Exit
f1: Return 'f1 doesn''t need an argument'
f2: If arg()=3 Then
Return 'f2: Sum of 3 arguments:' arg(1)+arg(2)+arg(3)
Else
Return 'f2: Invalid invocation:' arg() 'arguments. Needed: 3'
f3: sum=0
do i=1 To arg()
If arg(i,'E')=0 Then Say 'f3: Argument' i 'omitted'
Else sum=sum+arg(i)
End
Return 'f3 sum=' sum
f4: sum=0; Do i=1 To arg(); sum=sum+arg(i); End
Return 'f4: Sum of' arg() 'arguments is' sum
f5: Parse Arg p1,p2
Say 'f5: Argument 1 ('p1') contains' value(p1)
Say 'f5: Argument 2 ('p2') contains' value(p2)
Return 'f5: sum='value(p1)+value(p2)
f6: Say 'f6: dir ft.rex'
Return 'dir ft.rex'
f7: Say 'f7 returns 7'
Return 7
f8: Say 'f8 returns arg(1)+arg(2)'
Return arg(1)+arg(2)
date: Say 'date is my date function'
Return translate('ef/gh/abcd','DATE'('S'),'abcdefgh')
fa: Say 'fa returns arg(1)+arg(2)'
Return arg(1)+arg(2)
fb: Say 'fb:' arg(1)','arg(2)
Return
Syntax:
Say 'Syntax raised in line' sigl
Say sourceline(sigl)
Say 'rc='rc '('errortext(rc)')'
If sigl=39 Then
Say 'fb cannot be invoked as function (it does not return a value'
Exit
- Output:
f1 doesn't need an argument f2: Sum of 3 arguments: 6 f2: Invalid invocation: 4 arguments. Needed: 3 f3: Argument 2 omitted f3: Argument 3 omitted f3 sum= 5 f4: Sum of 2 arguments is 3 f4: Sum of 3 arguments is 6 f5: Argument 1 (A) contains 4700 f5: Argument 2 (B) contains 11 f5: sum=4711 f6: dir ft.rex Datenträger in Laufwerk D: ist DATA Volumeseriennummer: B0F8-F2C3 Verzeichnis von D:\ 29.07.2013 00:33 2.661 ft.rex 1 Datei(en), 2.661 Bytes 0 Verzeichnis(se), 251.050.979.328 Bytes frei f7 returns 7 f8 returns arg(1)+arg(2) f8 returns arg(1)+arg(2) 3 = 3 date is my date function 20130729 07/29/2013 fa returns arg(1)+arg(2) fa returns arg(1)+arg(2) 33 = 3 fb: 1,2 fb: 1,2 Syntax raised in line 39 x=fb(1,2) rc=44 (Function or message did not return data) fb cannot be invoked as function (it does not return a value)
Ring
hello()
func hello
see "Hello from function" + nl
first() second()
func first see "message from the first function" + nl
func second see "message from the second function" + nl
sum(3,5) sum(1000,2000)
func sum x,y see x+y+nl
# this program will print the hello world message first then execute the main function
See "Hello World!" + nl
func main
see "Message from the main function" + nl
Ruby
Ruby does not have functions, but Ruby classes have "methods" which are equivalent. The parentheses around the arguments are optional (definition and call). A method returns the last expression that was evaluated in the body of the method. The return keyword can be used to make it explicit that a method returns a value.
- Calling a function that requires no arguments
def foo() p "foo" end foo #=> "foo" foo() #=> "foo"
- Calling a function with a fixed number of arguments
def foo arg; p arg end # one argument foo(1) #=> 1 foo "1" #=> "1" foo [0,1,2] #=> [0, 1, 2] (one Array)
- Calling a function with optional arguments
def foo(x=0, y=x, flag=true) p [x,y,flag] end foo #=> [0, 0, true] foo(1) #=> [1, 1, true] foo(1,2) #=> [1, 2, true] foo 1,2,false #=> [1, 2, false]
- Calling a function with a variable number of arguments
def foo(*args) p args end foo #=> [] foo(1,2,3,4,5) #=> [1, 2, 3, 4, 5]
- Calling a function with named arguments
def foo(id:0, name:"", age:0) p [id, name, age] end foo(age:22, name:"Tom") #=> [0, "Tom", 22]
- Using a function in statement context
- ?
- Using a function in first-class context within an expression
- The method is not a first-class function. However, there is Proc object.
- Obtaining the return value of a function
def foo(a,b) a + b end bar = foo 10,20 p bar #=> 30 p foo("abc","def") #=> "abcdef" # return multiple values def sum_and_product(a,b) return a+b,a*b end x,y = sum_and_product(3,5) p x #=> 8 p y #=> 15
- Distinguishing built-in functions and user-defined functions
- There is no distinction.
- Distinguishing subroutines and functions
- Subroutine and function don't exist at ruby. It is only a method that there is.
- The Kernel module is included by class Object, so its methods are available in every Ruby object.
- These methods are called without a receiver and thus can be called in functional form.
puts "OK!" # Kernel#puts raise "Error input" # Kernel#raise Integer("123") # Kernel#Integer rand(6) # Kernel#rand throw(:exit) # Kernel#throw # method which can be seen like a reserved word. attr_accessor # Module#attr_accessor include # Module#include private # Module#private require # Kernel#require loop { } # Kernel#loop
- Stating whether arguments are passed by value or by reference
- passed by value of object reference.
- Is partial application possible and how
- However something similar can be done, see Partial function application#Ruby
- Others
- Block Argument:
- The block argument sends a closure from the calling scope to the method.
- The block argument is always last when sending a message to a method. A block is sent to a method using
do ... end
or{ ... }
. class Array def sum(init=0, &blk) if blk inject(init){|s, n| s + blk.call(n)} else inject(init){|s, n| s + n} end end end ary = [1,2,3,4,5] p ary.sum #=> 15 p ary.sum(''){|n| (-n).to_s} #=> "-1-2-3-4-5" p (ary.sum do |n| n * n end) #=> 55
- Splat operator:
- You can turn an Array into an argument list with * (or splat) operator.
def foo(a,b,c) p [a,b,c] end args = [1,2,3] foo *args #=> [1, 2, 3] args = [1,2] foo(0,*args) #=> [0, 1, 2]
- Syntax sugar:
- In Ruby, many operators are actually method calls.
# return value substance i = 3 p 1 + i #=> 4 1.+(i) p i < 5 #=> true i.<(5) p 2 ** i #=> 8 2.**(i) p -i #=> -3 i.-@() a = [1,2,3] p a[0] #=> 1 a.[](0) a[2] = "0" # a.[]=(2,"0") p a << 5 #=> [1, 2, "0", 5] a.<<(5) p a & [4,2] #=> [2] a.&([4,2]) p "abcde"[1..3] #=> "bcd" "abcde".[](1..3) p "%2d %4s" % [1,"xyz"] #=> " 1 xyz" "%2d %4s".%([1,"xyz"])
- Method call which was displayed in the comment is usable actually.
Rust
fn main() {
// Rust has a lot of neat things you can do with functions: let's go over the basics first
fn no_args() {}
// Run function with no arguments
no_args();
// Calling a function with fixed number of arguments.
// adds_one takes a 32-bit signed integer and returns a 32-bit signed integer
fn adds_one(num: i32) -> i32 {
// the final expression is used as the return value, though `return` may be used for early returns
num + 1
}
adds_one(1);
// Optional arguments
// The language itself does not support optional arguments, however, you can take advantage of
// Rust's algebraic types for this purpose
fn prints_argument(maybe: Option<i32>) {
match maybe {
Some(num) => println!("{}", num),
None => println!("No value given"),
};
}
prints_argument(Some(3));
prints_argument(None);
// You could make this a bit more ergonomic by using Rust's Into trait
fn prints_argument_into<I>(maybe: I)
where I: Into<Option<i32>>
{
match maybe.into() {
Some(num) => println!("{}", num),
None => println!("No value given"),
};
}
prints_argument_into(3);
prints_argument_into(None);
// Rust does not support functions with variable numbers of arguments. Macros fill this niche
// (println! as used above is a macro for example)
// Rust does not support named arguments
// We used the no_args function above in a no-statement context
// Using a function in an expression context
adds_one(1) + adds_one(5); // evaluates to eight
// Obtain the return value of a function.
let two = adds_one(1);
// In Rust there are no real built-in functions (save compiler intrinsics but these must be
// manually imported)
// In rust there are no such thing as subroutines
// In Rust, there are three ways to pass an object to a function each of which have very important
// distinctions when it comes to Rust's ownership model and move semantics. We may pass by
// value, by immutable reference, or mutable reference.
let mut v = vec![1, 2, 3, 4, 5, 6];
// By mutable reference
fn add_one_to_first_element(vector: &mut Vec<i32>) {
vector[0] += 1;
}
add_one_to_first_element(&mut v);
// By immutable reference
fn print_first_element(vector: &Vec<i32>) {
println!("{}", vector[0]);
}
print_first_element(&v);
// By value
fn consume_vector(vector: Vec<i32>) {
// We can do whatever we want to vector here
}
consume_vector(v);
// Due to Rust's move semantics, v is now inaccessible because it was moved into consume_vector
// and was then dropped when it went out of scope
// Partial application is not possible in rust without wrapping the function in another
// function/closure e.g.:
fn average(x: f64, y: f64) -> f64 {
(x + y) / 2.0
}
let average_with_four = |y| average(4.0, y);
average_with_four(2.0);
}
Scala
def ??? = throw new NotImplementedError // placeholder for implementation of hypothetical methods
def myFunction0() = ???
myFunction0() // function invoked with empty parameter list
myFunction0 // function invoked with empty parameter list omitted
def myFunction = ???
myFunction // function invoked with no arguments or empty arg list
/* myFunction() */ // error: does not take parameters
def myFunction1(x: String) = ???
myFunction1("foobar") // function invoked with single argument
myFunction1 { "foobar" } // function invoked with single argument provided by a block
// (a block of code within {}'s' evaluates to the result of its last expression)
def myFunction2(first: Int, second: String) = ???
val b = "foobar"
myFunction2(6, b) // function with two arguments
def multipleArgLists(first: Int)(second: Int, third: String) = ???
multipleArgLists(42)(17, "foobar") // function with three arguments in two argument lists
def myOptionalParam(required: Int, optional: Int = 42) = ???
myOptionalParam(1) // function with optional param
myOptionalParam(1, 2) // function with optional param provided
def allParamsOptional(firstOpt: Int = 42, secondOpt: String = "foobar") = ???
allParamsOptional() // function with all optional args
/* allParamsOptional */ // error: missing arguments for method allParamsOptional;
// follow with `_' if you want to treat it as a partially applied function
def sum[Int](values: Int*) = values.foldLeft(0)((a, b) => a + b)
sum(1, 2, 3) // function accepting variable arguments as literal
val values = List(1, 2, 3)
sum(values: _*) // function acception variable arguments from collection
sum() // function accepting empty variable arguments
def mult(firstValue: Int, otherValues: Int*) = otherValues.foldLeft(firstValue)((a, b) => a * b)
mult(1, 2, 3) // function with non-empty variable arguments
myOptionalParam(required = 1) // function called with named arguments (all functions have named arguments)
myFunction2(second = "foo", first = 1) // function with re-ordered named arguments
mult(firstValue = 1, otherValues = 2, 3) // function with named variable argument as literal
val otherValues = Seq(2, 3)
mult(1, otherValues = otherValues: _*) // function with named variable argument from collection
val result = myFunction0() // function called in an expression context
myFunction0() // function called in statement context
/* myOptionalParam(optional = 1, 2) */ // error: positional after named argument.
def transform[In, Out](initial: In)(transformation: In => Out) = transformation(initial)
val result = transform(42)(x => x * x) // function in first-class context within an expression
def divide(top: Double, bottom: Double) = top / bottom
val div = (divide _) // partial application -- defer application of entire arg list
val halve = divide(_: Double, 2) // partial application -- defer application of some arguments
class Foo(var value: Int)
def incFoo(foo: Foo) = foo.value += 1 // function showing AnyRef's are passed by reference
/* def incInt(i: Int) = i += 1 */ // error: += is not a member of Int
// (All arguments are passed by reference, but reassignment
// or setter must be defined on a type or a field
// (respectively) in order to modify its value.)
// No distinction between built-in functions and user-defined functions
// No distinction between subroutines and functions
Seed7
- Seed7 provides two kinds of subroutines: proc, which has no return value, and func, which has a return value. The return value of a func must be used by the caller (e.g. assigned to a variable). If you don't want do deal with the return value, use a proc instead.
- Seed7 supports call-by-value, call-by-reference, and call-by-name parameters. Programmers are free to specify the desired parameter passing mechanism. The most used parameter passing mechanism is 'in'. Depending on the type 'in' specifies call-by-value (for integer, float, ...) or call-by-reference (for string, array, ...). It is prohibited to write something to an 'in' parameter.
- All parameters are positional.
- There are no differences between between calling built-in vs. user defined functions.
env := environment; # Call a function that requires no arguments. env := environment(); # Alternative possibility to call of a function with no arguments. cmp := compare(i, j); # Call a function with a fixed number of arguments.
- There are no optional arguments, but a similar effect can be achieved with overloading.
write(aFile, "asdf"); # Variant of write with a parameter to specify a file. write("asdf"); # Variant of write which writes to the file OUT.
- Seed7 does not support functions with a variable number of arguments. But a function argument can be an array with as many values as you want:
const func integer: sum (in array integer: intElems) is func result var integer: sum is 0; local var integer: element is 0; begin for element range intElems do sum +:= element; end for; end func; s := sum([] (1, 2, 3)); # Use an aggregate to generate an array. t := sum([] (2, 3, 5, 7));
- Concatenation operators can be used to concatenate arguments. This solution is used to provide the write function:
write("Nr: " <& num); # Use operators to concatenate arguments.
- The procedure ignore can be used to ignore a return value.
ignore(getln(IN)); # Using a function in statement context (ignore the result).
- Call-by-name parameters use a function in first-class context. The function doMap from the examples section of the Seed7 homepage uses a given expression to modify the elements of an array:
seq := doMap([](1, 2, 4, 6, 10, 12, 16), x, succ(x));
SenseTalk
- If no variable is specified, `put` prints the variable to stdout
put zeroArgsFn()
// Function calls can also be made using the following syntax:
put the zeroArgsFn
function zeroArgsFn
put "This function was run with zero arguments."
return "Return value from zero argument function"
end zeroArgsFn
- Running a function requires a keyword such as `put; if no variable is return, put into e.g. _
put TwoArgFn("variable", (3, 4)) into _
// Alternatively, the function can be called like so:
put the TwoArgFn of "variable", (3, 4)
// The parameter list is flexible, allowing any amount of variable to be passed in.
// These can be accessed with the keyword `the parameterList`
// The specified parameters only limits to named parameters
get TwoArgFn("variable", (3, 4), "hello")
get the TwoArgFn of "variable", (3, 4), "hello"
function TwoArgFn arg1, arg2
put "2 argument function: arg1 = " & arg1 & "; arg2 = " & arg2
put "Parameters = " & the parameterList
end TwoArgFn
- A parameter is set to "" if nothing is specified
get ThreeArgFn("variable", (3, 4))
function ThreeArgFn arg1, arg2, arg3
put "3 argument function: arg1 = " & arg1 & "; arg2 = " & arg2 & "; arg3 = " & arg3
end ThreeArgFn
- Using this, default parameter values can be set up if a check if done at the start of the function
get OneArgFn() -- arg1 is 5
get OneArgFn(10) -- arg1 is now 10
function OneArgFn arg1
if arg1 is ""
set arg1 to 5
end if
put "One argument function; arg1 = " & arg1
end OneArgFn
- All variables are, by default, passed by value
- If the argument prefixed by 'container', the variable is passed by reference
put 3 into a
get AddOne(a)
put "Value of a = " & a
// Value of a = 3
put 5 into b
get AddOne(container b)
put "Value of b = " & b
// Value of b = 6
function AddOne n
add 1 to n
end AddOne
SenseTalk also distinguishes between functions and subroutines, which it calls handlers:
CustomHandler 1, 2, 3
// Prints: 1 - 2 - 3
to handle CustomHandler arg1, arg2, arg3
put arg1 && "-" && arg2 && "-" && arg3
end CustomHandler
Subroutines can be called as a command, without storing the output
MyCommand 1, "variable", (4, 5, 6)
to MyCommand args
...
end MyCommand
Functions/subroutines can also be defined with the to, on or function keywords:
to MyFn args
...
end MyFn
function MyFn args
...
end args
on MyFn args
...
end args
Sidef
All functions in Sidef are first-class closures
foo(); # without arguments
foo(1, 2); # with two arguments
foo(args...); # with a variable number of arguments
foo(name: 'Bar', age: 42); # with named arguments
var f = foo; # store the function foo inside 'f'
var result = f(); # obtain the return value of a function
var arr = [1,2,3];
foo(arr); # the arguments are passed by object-reference
Partial application is possible by using a curry function:
func curry(f, *args1) {
func (*args2) {
f(args1..., args2...);
}
}
func add(a, b) {
a + b
}
var adder = curry(add, 1);
say adder(3); #=>4
Slope
Define and call a procedure:
(define hello-world (lambda () (display "Hello, world!\n"))
(hello-world)
Call an anonymous procedure/lambda:
((lambda () (display "Hello, world!\n")))
Define and call a procedure with arguments:
(define hello (lambda (name) (display "Hello, " name "!\n")))
(hello "Rosetta Code")
Define and call an anonymous procedure with arguments:
((lambda (name) (display "Hello, " name "!\n")) "Rosetta Code")
Defining a procedure that takes option arguments and defining one that takes a variable number of arguments works the same. `...` as a paramater represents a list of all arguments passed in from that paramater forward. Here is an example usage for variable arguments:
((lambda (op ...)
(if (null? ...)
(! "At least one argument is required")
(apply op ...)))
* 1 2 3 4)
Here is an example with an optional value:
((lambda (first ...)
(define last (if (null? ...) "" (append " " (car ...))))
(display "Hello " first last "\n")) "John" "Kimball")
Partial application varies by procedure. Some built-ins use partial application (such as `or`). Macros created with `macro` do not evaluate any arguments and the macro definition is responsible for evaluating what it needs to. But macros likely fall into a different category than the scope of this task.
SmallBASIC
func F1()
return 1
end
func F2(a)
return a + 1
end
func F3(a, b)
return a + b
end
func F4(byref a)
a = 5
return a + 1
end
sub S1(a, b)
print a, b
end
sub S2(byref a)
a = 5
end
var1 = 1
var2 = 2
' Functions return a result and return-value must be assigned to a variable
result = F1()
result = F2(var1)
result = F3(var1, var2)
' Parameters are passed by reference if byref is used in function definition
result = F4(var1) ' result = 6 and var1 = 5
' Subroutines can't return a result
S1(var1, var2)
' Parameters are passed by reference if byref is used in sub definition.
' This can be used to return a result indirectly
S2(var1) ' var1 = 5
' Functions and subroutines can take expressions as parameter
result = F2(1 + 2)
Smalltalk
Where f is a closure and arguments is an array of values for f to operate on.
f valueWithArguments: arguments.
SSEM
Assuming the subroutine has been set up in accordance with the Wheeler jump technique as described in the SSEM Function definition entry, calling it requires simply loading the return address into the accumulator and jumping out to the subroutine. Parameters must be passed using "global variables", i.e. storage locations; results may be passed the same way, although it is also possible to pass a return value in the accumulator.
This code fragment, beginning (for the sake of argument) at address 10, performs a Wheeler jump to a subroutine beginning at address 20. The return address is coded in negative (two's complement) form because the SSEM negates values in the process of loading them into the accumulator. As always on the SSEM, jump targets are one less than the actual intended target: this is because the CI ("Current Instruction") register is incremented after an instruction has been executed rather than before.
00110000000000100000000000000000 10. -12 to c
10110000000000000000000000000000 11. 13 to CI
11001111111111111111111111111111 12. -13
11001000000000000000000000000000 13. 19
Swift
// call a function with no args
noArgs()
// call a function with one arg with no external name
oneArgUnnamed(1)
// call a function with one arg with external name
oneArgNamed(arg: 1)
// call a function with two args with no external names
twoArgsUnnamed(1, 2)
// call a function with two args and external names
twoArgsNamed(arg1: 1, arg2: 2)
// call a function with an optional arg
// with arg
optionalArguments(arg: 1)
// without
optionalArguments() // defaults to 0
// function that takes another function as arg
funcArg(noArgs)
// variadic function
variadic(opts: "foo", "bar")
// getting a return value
let foo = returnString()
// getting a bunch of return values
let (foo, bar, baz) = returnSomeValues()
// getting a bunch of return values, discarding second returned value
let (foo, _, baz) = returnSomeValues()
Tcl
aCallToACommandWithNoArguments
aCallToACommandWithOne argument
aCallToACommandWith arbitrarily many arguments
aCallToACommandWith {*}$manyArgumentsComingFromAListInAVariable
aCallToACommandWith -oneNamed argument -andAnother namedArgument
aCallToACommandWith theNameOfAnotherCommand
aCallToOneCommand [withTheResultOfAnother]
Tcl does differentiate between functions and other types of commands in expressions:
expr {func() + [cmd]}
expr {func(1,2,3} + [cmd a b c]}
However, there are no deep differences between the two: functions are translated into commands that are called in a particular namespace (thus foo() becomes tcl::mathfunc::foo). There are no differences in usage between built-in commands and user-defined ones, and parameters are passed to commands by value conceptually (and read-only reference in the implementation).
True BASIC
FUNCTION Copialo$ (txt$, siNo, final$)
FOR cont = 1 TO ROUND(siNo)
LET nuevaCadena$ = nuevaCadena$ & txt$
NEXT cont
LET Copialo$ = LTRIM$(RTRIM$(nuevaCadena$)) & final$
END FUNCTION
SUB Saludo
PRINT "Hola mundo!"
END SUB
SUB testCadenas (txt$)
FOR cont = 1 TO ROUND(LEN(txt$))
PRINT (txt$)[cont:cont+1-1]; "";
NEXT cont
END SUB
SUB testNumeros (a, b, c)
PRINT a, b, c
END SUB
CALL Saludo
PRINT Copialo$("Saludos ", 6, "")
PRINT Copialo$("Saludos ", 3, "! !")
PRINT
CALL testNumeros(1, 2, 3)
CALL testNumeros(1, 2, 0)
PRINT
CALL testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")
END
- Output:
Igual que la entrada de FreeBASIC.
UNIX Shell
In the shell, there are no argument specifications for functions. Functions obtain their arguments using the positional parameter facilities and functions are simply called by name followed by any arguments that are to be passed:
sayhello # Call a function in statement context with no arguments
multiply 3 4 # Call a function in statement context with two arguments
The shell does not support the use of named parameters. There is no lookahead in the shell, so functions cannot be called until their definition has been run.
VBA
'definitions/declarations
'Calling a function that requires no arguments
Function no_arguments() As String
no_arguments = "ok"
End Function
'Calling a function with a fixed number of arguments
Function fixed_number(argument1 As Integer, argument2 As Integer)
fixed_number = argument1 + argument2
End Function
'Calling a function with optional arguments
Function optional_parameter(Optional argument1 = 1) As Integer
'Optional parameters come at the end of the parameter list
optional_parameter = argument1
End Function
'Calling a function with a variable number of arguments
Function variable_number(arguments As Variant) As Integer
variable_number = UBound(arguments)
End Function
'Calling a function with named arguments
Function named_arguments(argument1 As Integer, argument2 As Integer) As Integer
named_arguments = argument1 + argument2
End Function
'Using a function in statement context
Function statement() As String
Debug.Print "function called as statement"
statement = "ok"
End Function
'Using a function in first-class context within an expression
'see call the functions
'Obtaining the return value of a function
Function return_value() As String
return_value = "ok"
End Function
'Distinguishing built-in functions and user-defined functions
'There is no way to distinguish built-in function and user-defined functions
'Distinguishing subroutines And functions
'subroutines are declared with the reserved word "sub" and have no return value
Sub foo()
Debug.Print "subroutine",
End Sub
'functions are declared with the reserved word "function" and can have a return value
Function bar() As String
bar = "function"
End Function
'Stating whether arguments are passed by value or by reference
Function passed_by_value(ByVal s As String) As String
s = "written over"
passed_by_value = "passed by value"
End Function
'By default, parameters in VBA are by reference
Function passed_by_reference(ByRef s As String) As String
s = "written over"
passed_by_reference = "passed by reference"
End Function
'Is partial application possible and how
'I don't know
'calling a subroutine with arguments does not require parentheses
Sub no_parentheses(myargument As String)
Debug.Print myargument,
End Sub
'call the functions
Public Sub calling_a_function()
'Calling a function that requires no arguments
Debug.Print "no arguments", , no_arguments
Debug.Print "no arguments", , no_arguments()
'Parentheses are not required
'Calling a function with a fixed number of arguments
Debug.Print "fixed_number", , fixed_number(1, 1)
'Calling a function with optional arguments
Debug.Print "optional parameter", optional_parameter
Debug.Print "optional parameter", optional_parameter(2)
'Calling a function with a variable number of arguments
Debug.Print "variable number", variable_number([{"hello", "there"}])
'The variable number of arguments have to be passed as an array
'Calling a function with named arguments
Debug.Print "named arguments", named_arguments(argument2:=1, argument1:=1)
'Using a function in statement context
statement
'Using a function in first-class context within an expression
s = "no_arguments"
Debug.Print "first-class context", Application.Run(s)
'A function name can be passed as argument in a string
'Obtaining the return value of a function
returnvalue = return_value
Debug.Print "obtained return value", returnvalue
'Distinguishing built-in functions and user-defined functions
'Distinguishing subroutines And functions
foo
Debug.Print , bar
'Stating whether arguments are passed by value or by reference
Dim t As String
t = "unaltered"
Debug.Print passed_by_value(t), t
Debug.Print passed_by_reference(t), t
'Is partial application possible and how
'I don 't know
'calling a subroutine with arguments does not require parentheses
no_parentheses "calling a subroutine"
Debug.Print "does not require parentheses"
Call no_parentheses("deprecated use")
Debug.Print "of parentheses"
End Sub
- Output:
no arguments ok no arguments ok fixed_number 2 optional parameter 1 optional parameter 2 variable number 2 named arguments 2 function called as statement first-class context ok obtained return value ok subroutine function passed by value unaltered passed by reference written over calling a subroutine does not require parentheses deprecated use of parentheses
WDTE
let noargs => + 2 5;
noargs -- print;
let fixedargs a b => + a b;
fixedargs 3 5 -- print;
let m => import 'math';
m.cos 3 -- print;
# WDTE only has expressions, not statements, so statement vs.
# first-class context doesn't make sense.
# Arguments in WDTE are technically passed by reference, in a way, but
# because it's a functional language and everything's immutable
# there's no real usability difference from that.
# Partial application is possible. For example, the following
# evaluates `+ 3` and then passes 7 to the resulting partially applied
# function.
(+ 3) 7 -- print;
WebAssembly
(func $main (export "_start")
(local $result i32)
;;Call a function with no arguments
call $noargfunc
;;Multiply two numbers and store the result, flat syntax
i32.const 12
i32.const 3
call $multipy
set_local $result
;;Multiply two numbers and store the result, indented syntax
(set_local $result
(call $multipy
(i32.const 12)
(i32.const 3)
)
)
;;Add two numbers in linear memory (similar to using pointers)
(i32.store (i32.const 0) (i32.const 5))
(i32.store (i32.const 4) (i32.const 7))
(call $addinmemory
(i32.const 0)
(i32.const 4)
(i32.const 8)
)
)
Wren
Wren distinguishes between functions and methods.
The former are first-class standalone objects which cannot be overloaded whereas the latter are always members of a class and can be overloaded by arity (i.e. the number of arguments they require). As Wren is dynamically typed and doesn't support type annotations, methods cannot be overloaded by parameter type. Methods can either be instance or static members of their class.
As well as 'ordinary' methods which always have a (possibly empty) parameter list, Wren also has the following types of methods:
1. 'constructors' which always have a parameter list and are really a pair of methods - a static method which creates a new instance of the class and then invokes an initializer on that instance.
2. 'getters' which leave off the parameter list.
3. 'setters' which have '=' after the name followed by a parameter list with just a single parameter.
4. 'operators' which, if they're infix operators, always have a parameter list with a single parameter. However, if they're prefix operators, they have no parameter list.
Wren does not support optional arguments, a variable number of arguments or named arguments though these can be respectively simulated by overloading, passing lists or passing maps.
Arguments are always passed by value though, if they're mutable reference types, it's the reference which gets copied so the function or method can mutate the object itself.
There are no built-in functions but all built-in classes have methods. Unless you know what they are, there is no way to distinguish between them and methods of user-defined classes.
The only way to distinguish between sub-routines and functions it to check whether they return a concrete value. The former always return null by default.
Partial function application is not supported per se but can be simulated as in the task of that name.
Here are some examples:
var f1 = Fn.new { System.print("Function 'f1' with no arguments called.") }
var f2 = Fn.new { |a, b|
System.print("Function 'f2' with 2 arguments called and passed %(a) & %(b).")
}
var f3 = Fn.new { 42 } // function which returns a concrete value
f1.call() // statement context
f2.call(2, 3) // ditto
var v1 = 8 + f3.call() // calling function within an expression
var v2 = f3.call() // obtaining return value
System.print([v1, v2]) // print last two results as a list
class MyClass {
static m() { System.print("Static method 'm' called.") }
construct new(x) { _x = x } // stores 'x' in a field
x { _x } // gets the field
x=(y) { _x = y } // sets the field to 'y'
- { MyClass.new(-_x) } // prefix operator
+(o) { MyClass.new(_x + o.x) } // infix operator
toString { _x.toString } // instance method
}
MyClass.m() // call static method 'm'
var mc1 = MyClass.new(40) // construct 'mc1'
var mc2 = MyClass.new(8) // construct 'mc2'
System.print(mc1.x) // print mc1's field using getter
mc1.x = 42 // change mc1's field using setter
System.print(-mc1.x) // invoke prefix operator -
System.print(mc1 + mc2) // invoke infix operator +
- Output:
Function 'f1' with no arguments called. Function 'f2' with 2 arguments called and passed 2 & 3. [50, 42] Static method 'm' called. 40 -42 50
XLISP
; call a function (procedure) with no arguments:
(foo)
; call a function (procedure) with arguments:
(foo bar baz)
; the first symbol after "(" is the name of the function
; the other symbols are the arguments
; call a function on a list of arguments formed at run time:
(apply foo bar)
; In a REPL, the return value will be printed.
; In other contexts, it can be fed as argument into a further function:
(foo (bar baz))
; this calls bar on the argument baz and then calls foo on the return value
; or it can simply be discarded
(foo bar)
; nothing is done with the return value
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<demo>
<!--
XSLT 1.0 actually defines two function-like constructs that
are used variously depending on the context.
-->
<xsl:call-template name="xpath-function-demos"/>
<xsl:call-template name="xslt-template-demos"/>
</demo>
</xsl:template>
<xsl:template name="xpath-function-demos">
<!--
A 'function' in XSLT 1.0 is a function that can be called from
an XPath 1.0 expression (such as from "select" or "test"
attribute of several XSLT elements). The following demos apply
to these functions.
-->
<!-- Calling function that requires no arguments -->
<!-- false() always returns a boolean false value -->
<line>This test is <xsl:if test="false()">NOT</xsl:if> OK.</line>
<!-- Calling a function with a fixed number of arguments -->
<!-- not() takes exactly 1 argument. starts-with() takes exactly 2 arguments. -->
<line>'haystack' does <xsl:if test="not(starts-with('haystack', 'hay'))">NOT</xsl:if> start with 'hay'.</line>
<!-- Calling a function with optional arguments -->
<!-- If the third argument of substring() is omitted, the length of the string is assumed. -->
<line>'<xsl:value-of select="substring('haystack', 1, 3)"/>' = 'hay'</line>
<line>'<xsl:value-of select="substring('haystack', 4)"/>' = 'stack'</line>
<!-- Calling a function with a variable number of arguments -->
<!-- concat() accepts two or more arguments. -->
<line>'<xsl:value-of select="concat('abcd', 'efgh')"/>' = 'abcdefgh'</line>
<line>'<xsl:value-of select="concat('ij', 'kl', 'mn', 'op')"/>' = 'ijklmnop'</line>
<!--
Aggregate functions such as sum() and count() accept nodesets.
This isn't quite the same as varargs but are probably worth
mentioning.
-->
<line>The number of root elements in the input document is <xsl:value-of select="count(/*)"/> (should be 1).</line>
<!-- Calling a function with named arguments -->
<!-- XPath 1.0 uses only positional parameters. -->
<!-- Using a function in statement context -->
<!--
In general, XPath 1.0 functions have no side effects, so calling
them as statements is useless. While implementations often allow
writing extensions in imperative languages, the semantics of
calling a function with side effects are, at the very least,
implementation-dependent.
-->
<!-- Using a function in first-class context within an expression -->
<!-- Functions are not natively first-class values in XPath 1.0. -->
<!-- Obtaining the return value of a function -->
<!--
The return value of the function is handled as specified by the
various contexts in which an XPath expression is used. The
return value can be stored in a "variable" (no destructive
assignment is allowed), passed as a parameter to a function or a
template, used as a conditional in an <xsl:if/> or <xsl:when/>,
interpolated into text using <xsl:value-of/> or into an
attribute value using brace syntax, and so forth.
-->
<!-- Here, concat() is interpolated into an attribute value using braces ({}). -->
<line foo="{concat('Hello, ', 'Hello, ', 'Hello')}!">See attribute.</line>
<!-- Distinguishing built-in functions and user-defined functions -->
<!--
Given that functions aren't first-class here, the origin of any
given function is known before run time. Incidentally, functions
defined by the standard are generally unprefixed while
implementation-specific extensions (and user extensions, if
available) must be defined within a separate namespace and
prefixed.
-->
<!-- Distinguishing subroutines and functions -->
<!--
There are no "subroutines" in this sense—everything that looks
like a subroutine has some sort of return or result value.
-->
<!-- Stating whether arguments are passed by value or by reference -->
<!-- There is no meaningful distinction since there is no mechanism by which to mutate values. -->
<!-- Is partial application possible and how -->
<!-- Not natively. -->
</xsl:template>
<xsl:template name="xslt-template-demos">
<!--
A 'template' in XSLT 1.0 is a subroutine-like construct. When
given a name (and, optionally, parameters), it can be called
from within another template using the <xsl:call-template/>
element. (An unnamed template is instead called according to its
match and mode attributes.) The following demos apply to named
templates.
-->
<!--
Unlike with functions, there are no built-in named templates to
speak of. The ones used here are defined later in this
transform.
-->
<!--
Answers for these prompts are the same as with XPath functions (above):
Using a function in statement context
Distinguishing subroutines and functions
Stating whether arguments are passed by value or by reference
Is partial application possible and how
-->
<!-- Calling function that requires no arguments -->
<xsl:call-template name="nullary-demo"/>
<!--
Note that even if a template has no parameters, it has access to
the current node (.) as of the time of the call. This
<xsl:apply-templates/> runs a matching template above that calls
the template "nullary-context-demo" with no parameters. Another
way to manipulate a template's idea of which node is current is
by calling from inside a <xsl:for-each/> loop.
-->
<xsl:apply-templates select="/*" mode="nullary-context-demo-mode"/>
<!--
A template parameter is made optional in the definition of the
template by supplying an expression as its select attribute,
which is evaluated and used as its value if the parameter is
omitted. Note, though, that all template parameters have an
implicit default value, the empty string, if the select
attribute is not specified. Therefore, all template parameters
are always optional, even when semantically they should not be.
-->
<!-- Calling a function with a fixed number of arguments -->
<working note="When all parameters are supplied">
<xsl:call-template name="ternary-demo">
<xsl:with-param name="a" select="4"/>
<xsl:with-param name="b">3</xsl:with-param>
<xsl:with-param name="c" select="2 + 3"/>
</xsl:call-template>
</working>
<broken note="When the third parameter 'c' is omitted">
<xsl:call-template name="ternary-demo">
<xsl:with-param name="a" select="4"/>
<xsl:with-param name="b">3</xsl:with-param>
</xsl:call-template>
</broken>
<!-- Calling a function with optional arguments -->
<!-- With the optional third parameter -->
<working name="When all parameters are supplied">
<xsl:call-template name="binary-or-ternary-demo">
<xsl:with-param name="a" select="4"/>
<xsl:with-param name="b" select="3"/>
<xsl:with-param name="c" select="5"/>
</xsl:call-template>
</working>
<!-- Without the optional third parameter (which defaults to 0) -->
<working name="When 'a' and 'b' are supplied but 'c' is defaulted to 0">
<xsl:call-template name="binary-or-ternary-demo">
<xsl:with-param name="a" select="4"/>
<xsl:with-param name="b" select="3"/>
</xsl:call-template>
</working>
<!-- Calling a function with a variable number of arguments -->
<!--
Templates are not varargs-capable. Variable numbers of arguments
usually appear in the form of a nodeset which is then bound to a
single parameter name.
-->
<!-- Calling a function with named arguments -->
<!--
Other than what comes with the current context, template
arguments are always named and can be supplied in any order.
Templates do not support positional arguments. Additionally,
even arguments not specified by the template may be passed; they
are silently ignored.
-->
<!-- Using a function in first-class context within an expression -->
<!-- Templates are not first-class values in XSLT 1.0. -->
<!-- Obtaining the return value of a function -->
<!--
The output of a template is interpolated into the place of the
call. Often, this is directly into the output of the transform,
as with most of the above examples. However, it is also possible
to bind the output as a variable or parameter. This is useful
for using templates to compute parameters for other templates or
for XPath functions.
-->
<!-- Which is the least of 34, 78, 12, 56? -->
<xsl:variable name="lesser-demo-result">
<!-- The variable is bound to the output of this call -->
<xsl:call-template name="lesser-value">
<xsl:with-param name="a">
<!-- A call as a parameter to another call -->
<xsl:call-template name="lesser-value">
<xsl:with-param name="a" select="34"/>
<xsl:with-param name="b" select="78"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="b">
<!-- and again -->
<xsl:call-template name="lesser-value">
<xsl:with-param name="a" select="12"/>
<xsl:with-param name="b" select="56"/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<!-- The variable is used here in an XPath expression -->
<line>
<xsl:value-of select="concat('And the answer, which should be 12, is ', $lesser-demo-result, ', of course.')"/>
</line>
<!-- Distinguishing built-in functions and user-defined functions -->
<!-- Virtually all templates are user-defined. -->
</xsl:template>
<!-- Templates supporting template demos above -->
<xsl:template match="/*" mode="nullary-context-demo-mode">
<xsl:call-template name="nullary-context-demo"/>
</xsl:template>
<xsl:template name="nullary-demo">
<line>No parameters needed here!</line>
</xsl:template>
<xsl:template name="nullary-context-demo">
<!-- When a template is called it has access to the current node of the caller -->
<xsl:for-each select="self::*">
<line>The context element here is named "<xsl:value-of select="local-name()"/>"</line>
</xsl:for-each>
</xsl:template>
<xsl:template name="ternary-demo">
<!-- This demo requires, at least semantically, all three parameters. -->
<xsl:param name="a"/>
<xsl:param name="b"/>
<xsl:param name="c"/>
<line>(<xsl:value-of select="$a"/> * <xsl:value-of select="$b"/>) + <xsl:value-of select="$c"/> = <xsl:value-of select="($a * $b) + $c"/></line>
</xsl:template>
<xsl:template name="binary-or-ternary-demo">
<!-- This demo requires the first two parameters, but defaults the third to 0 if it is not supplied. -->
<xsl:param name="a"/>
<xsl:param name="b"/>
<xsl:param name="c" select="0"/>
<line>(<xsl:value-of select="$a"/> * <xsl:value-of select="$b"/>) + <xsl:value-of select="$c"/> = <xsl:value-of select="($a * $b) + $c"/></line>
</xsl:template>
<xsl:template name="lesser-value">
<xsl:param name="a"/>
<xsl:param name="b"/>
<xsl:choose>
<xsl:when test="number($a) < number($b)">
<xsl:value-of select="$a"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$b"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Yabasic
sub test(a, b, c) : print a, b, c : end sub
test(1, 2, 3) // show 1 2 3
test(1, 2) // show 1 2 0
execute("test", 1, 2, 3) // show 1 2 3
sub test$(a$) // show all members of a "list"
local n, i, t$(1)
n = token(a$, t$(), ", ")
for i = 1 to n
print t$(i), " ";
next
end sub
test$("1, 2, 3, 4, text, 6, 7, 8, \"include text\"")
print
Z80 Assembly
Like most assembly languages, the concept of functions are too "high-level" for most of the task to apply. However, subroutines do exist and they are used like a function in a high-level language would be.
- Functions that require no arguments are the simplest. They are simply
CALL
ed without any special input.
- Functions that take a fixed number of arguments usually require the programmer to load the arguments into registers or push them to the stack prior to calling the function.
PackNibbles:
;input: B = top nibble, C = bottom nibble. Outputs to accumulator.
;usage: B = &0X, C = &0Y, => A = &XY
LD A,B
AND %00001111
RLCA
RLCA
RLCA
RLCA
OR C
RET
- Assembly language in general has difficulty with optional and variable numbers of arguments (unless it is written by a compiler, of course). Prior to the function call, an optional argument would most likely be set to zero if intended to be unused in a particular instance of a function.
- Z80 Assembly does not support named arguments directly, but this can be achieved with assembly macros and labels.
- Getting a function's return value depends on how it was programmed. The concept of "return values" is a high-level construct that isn't enforced by assembly languages in general, and Z80 is no exception. The programmer is free to choose which register or section of memory the return value of a function is stored, if one even exists. Generally speaking the accumulator is usually used for this purpose but it depends on the data type as well as the needs of the program.
AddTwoNumbers
;input registers: A,B. Outputs to A.
ADD a,b
RET
- Some implementations of Z80 Assembly have built-in functions. These are essentially just subroutines located in ROM at a specific memory address. Functions stored in low memory can be called with the
RST #
instruction. Anything in high memory will need to beCALL
ed like any other user-created subroutine. On the Amstrad CPC,CALL &BB5A
will print the accumulator to the screen as an ASCII character.
- Whether an argument is passed by value or by reference is again up to the programmer. By default, Z80 Assembly is pass-by-value, since it's much easier to operate on registers than directly on memory. The function would have to explicitly store the updated values back into memory for them to be altered. However, some Z80 instructions do directly alter memory, such as
RLD
,RRD
,LDIR
,etc.
zkl
The syntax and semantics of function calls is the always the same: name/object(parameters). All calls are varargs, it is up to the callee to do default/optional parameter handling (but that is hidden from the programmer). No named parameters. Pass by reference or value, depending.
Using f has a function, method or object:
f(); f(1,2,3,4);
fcn f(a=1){}() // define and call f, which gets a set to 1
fcn{vm.arglist}(1,2,3,4) // arglist is L(1,2,3,4)
fcn{a1:=vm.nthArg(1)}(1,2,3) // a1 == 2
(f() == True); (f() and 1 or 2)
if (f()) println()
f(f) // pass f to itself
s:=f()
fcn{}.isType(self.fcn) //True
fcn{}.len.isType(self.fcn) //False, len is a Method
Partial application is done with the .fp* methods or the 'wrap keyword
fcn(a,b,c).fp(1)() // call function with a always set to 1
fcn(a,b,c).fp1(2,3)() // call function with b & c always set to 2 & 3
fcn(a,b,c,d).fpN(3,5)() // call function with d always set to 5
fcn{vm.arglist}.fpN(3,66)(1,2,3,4,5) //-->L(1,2,3,66,4,5)
fcn{}.fpM("01-",5) // use a mask to select parameters
// 1 is supplied, 0 is get upon call, - is chop arglist
fcn{vm.arglist}.fpM("01-",66)(1,2,3,4) //-->L(1,66)
a:=5; f('wrap(b){a+b}) // 'wrap is syntactic sugar for .fpN
// to create a lexical closure --> f(fcn(b,a){a+b}.fpN(1,a))
zonnon
module CallingProcs;
type
{public} Vector = array {math} * of integer;
var
nums: array {math} 4 of integer;
ints: Vector;
total: integer;
procedure Init(): boolean; (* private by default *)
begin
nums := [1,2,3,4];
ints := new Vector(5);
ints := [2,4,6,8,10];
return true;
end Init;
(* function *)
procedure Sum(v: Vector): integer;
var
i,s: integer;
begin
s := 0;
for i := 0 to len(v) - 1 do
(* inc is a predefined subroutine *)
inc(s,v[i])
end;
return s
end Sum;
(* subroutine
* @param v: by value
* @param t: by reference
*)
procedure Sum2(v: array {math} * of integer; var t: integer);
var
i: integer;
begin
t := 0;
for i := 0 to len(v) - 1 do
inc(t,v[i])
end
end Sum2;
begin
Init; (* calling a function without parameters *)
total := Sum(nums);
writeln(total);
(* optional arguments not supported *)
(* variable arguments through open arrays *)
writeln(Sum(ints));
(* named arguments not supported *)
ints := [1,3,5,7,9];
Sum2(ints,total);
writeln(total);
end CallingProcs.
ZX Spectrum Basic
On the ZX Spectrum, functions and subroutines are separate entities. A function is limited to being a single expression that generates a return value. Statements are not allowed within a function. A subroutine can perform input and output and can contain statements.
10 REM functions cannot be called in statement context
20 PRINT FN a(5): REM The function is used in first class context. Arguments are not named
30 PRINT FN b(): REM Here we call a function that has no arguments
40 REM subroutines cannot be passed parameters, however variables are global
50 LET n=1: REM This variable will be visible to the called subroutine
60 GO SUB 1000: REM subroutines are called by line number and do not have names
70 REM subroutines do not return a value, but we can see any variables it defined
80 REM subroutines cannot be used in first class context
90 REM builtin functions are used in first class context, and do not need the FN keyword prefix
100 PRINT SIN(50): REM here we pass a parameter to a builtin function
110 PRINT RND(): REM here we use a builtin function without parameters
120 RANDOMIZE: REM statements are not functions and cannot be used in first class context.
- Functions and subroutines
- Simple
- Programming Tasks
- Solutions by Programming Task
- 11l
- 360 Assembly
- 6502 Assembly
- 8086 Assembly
- 68000 Assembly
- AArch64 Assembly
- ActionScript
- Ada
- ALGOL 68
- ALGOL W
- AntLang
- ARM Assembly
- Arturo
- AutoHotkey
- AWK
- Axe
- BASIC
- BASIC256
- Batch File
- BBC BASIC
- Binary Lambda Calculus
- BQN
- Bracmat
- C
- C sharp
- C++
- Clojure
- COBOL
- CoffeeScript
- Common Lisp
- Cubescript
- D
- Dart
- Delphi
- Dragon
- Dyalect
- Déjà Vu
- EasyLang
- Ecstasy
- Elena
- Elixir
- EMal
- Erlang
- F Sharp
- Factor
- Forth
- Fortran
- Fortress
- Free Pascal
- FreeBASIC
- FutureBasic
- Gambas
- Go
- Groovy
- Haskell
- I
- Icon
- Unicon
- J
- Java
- JavaScript
- Jq
- Julia
- Kotlin
- Lambdatalk
- Lang
- Langur
- Latitude
- LFE
- Liberty BASIC
- Lingo
- Little
- Lua
- Luck
- M2000 Interpreter
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- Octave
- Nanoquery
- Nemerle
- Nim
- OCaml
- Oforth
- Ol
- OoRexx
- PARI/GP
- Pascal
- Perl
- Phix
- Phix/basics
- Phixmonti
- PicoLisp
- PureBasic
- Python
- QBasic
- Quackery
- R
- Racket
- Raku
- REXX
- Ring
- Ruby
- Rust
- Scala
- Seed7
- SenseTalk
- Sidef
- Slope
- SmallBASIC
- Smalltalk
- SSEM
- Swift
- Tcl
- True BASIC
- UNIX Shell
- VBA
- WDTE
- WebAssembly
- Wren
- XLISP
- XSLT
- Yabasic
- Z80 Assembly
- Zkl
- Zonnon
- ZX Spectrum Basic
- GUISS/Omit
- Pages with too many expensive parser function calls