This commit is contained in:
Ingy döt Net 2013-04-10 16:57:12 -07:00
parent 518da4a923
commit 764da6cbbb
6144 changed files with 83610 additions and 11 deletions

View file

@ -0,0 +1,15 @@
The task is to 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
This task is ''not'' about [[Function definition|defining functions]].

View file

@ -0,0 +1,3 @@
---
category:
- Functions and subroutines

View file

@ -0,0 +1,4 @@
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
}

View file

@ -0,0 +1,3 @@
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

View file

@ -0,0 +1 @@
S: String := Ada.Text_IO.Get_Line;

View file

@ -0,0 +1,5 @@
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

View file

@ -0,0 +1,12 @@
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

View file

@ -0,0 +1,9 @@
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.

View file

@ -0,0 +1,3 @@
Positional := H(A, F'Access);
Named := H(Int => A, Fun => F'Access);
Mixed := H(A, Fun=>F'Access);

View file

@ -0,0 +1,39 @@
; 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.

View file

@ -0,0 +1,48 @@
/* 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: no such thing */
/* statement context: is that a real phrase? */
/* 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. */

View file

@ -0,0 +1,3 @@
var foo = function() { return arguments.length };
foo() // 0
foo(1, 2, 3) // 3

View file

@ -0,0 +1 @@
var squares = [1, 2, 3].map(function (n) { return n * n }); // [1, 4, 9]

View file

@ -0,0 +1,5 @@
var make_adder = function(m) {
return function(n) { return m + n }
};
var add42 = make_adder(42);
add42(10) // 52

View file

@ -0,0 +1,4 @@
foo.toString()
"function () { return arguments.length }"
alert.toString()
"function alert() { [native code] }"

View file

@ -0,0 +1,6 @@
var mutate = function(victim) {
victim[0] = null;
victim = 42;
};
var foo = [1, 2, 3];
mutate(foo) // foo is now [null, 2, 3], not 42

View file

@ -0,0 +1,49 @@
% 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.

View file

@ -0,0 +1,2 @@
(foo)
(bar 1 'arg 2 'mumble)

View file

@ -0,0 +1,2 @@
(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

View file

@ -0,0 +1 @@
(setq A (+ 3 4) B (* 3 4))

View file

@ -0,0 +1,51 @@
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
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
## 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

View file

@ -0,0 +1,137 @@
/*REXX program to demonstrate various methods of 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()
say 'year=' yr
exit
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*/
if arg()\==4 then do
call sayErr "FourFunc function requires 4 arguments,"
call sayErr "but instead it found" arg() 'arguments.'
exit 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 5 args, 4th is null*/
exit
SumIt: procedure; sum=0
do j=1 for arg()
if arg(j,'E') then sum=sum+arg(j) /*the Jth arg may have been omitted*/
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
exit
parseFunc: procedure expose common.
do j=1 for arg()
parse var arg(j) name '=' val
upper name
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
/*┌────────────────────────────────────────────────────────────────────┐
Obtaining the return value of a function.
There are two ways to get the (return) value of a function.
*/
currYear=yearFunc()
say 'the current year is' currYear
call yearFunc
say 'the current year is' result
/*┌────────────────────────────────────────────────────────────────────┐
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).
*/
qqq=date() /*number of real dates that Bob was on. */
say "Bob's been out" qqq 'times.'
www='DATE'('USA') /*returns date in format mm/dd/yyy */
exit /*any function in quotes is external. */
date: return 4
/*┌────────────────────────────────────────────────────────────────────┐
Distinguishing subroutines and functions.
There is no programatic 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
(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})
*/

View file

@ -0,0 +1 @@
f valueWithArguments: arguments.

View file

@ -0,0 +1,7 @@
aCallToACommandWithNoArguments
aCallToACommandWithOne argument
aCallToACommandWith arbitrarily many arguments
aCallToACommandWith {*}$manyArgumentsComingFromAListInAVariable
aCallToACommandWith -oneNamed argument -andAnother namedArgument
aCallToACommandWith theNameOfAnotherCommand
aCallToOneCommand [withTheResultOfAnother]

View file

@ -0,0 +1,2 @@
expr {func() + [cmd]}
expr {func(1,2,3} + [cmd a b c]}