Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -1,3 +1,4 @@
|
|||
---
|
||||
category:
|
||||
- Functions and subroutines
|
||||
- Simple
|
||||
|
|
|
|||
28
Task/Call-a-function/ALGOL-68/call-a-function.alg
Normal file
28
Task/Call-a-function/ALGOL-68/call-a-function.alg
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# A function without arguments: #
|
||||
f();
|
||||
# or #
|
||||
f;
|
||||
|
||||
# A function with a fixed number of arguments: #
|
||||
f(1, x);
|
||||
|
||||
# ALGOL 68 does not support optional arguments, variable numbers of arguments, or named
|
||||
arguments.
|
||||
However, some functions may take an argument "0" as an instruction to use the default value
|
||||
(sort of a pseudo-optional argument). #
|
||||
|
||||
# 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,
|
||||
both ALGOL examples above are already in a statement context.
|
||||
For full ALGOL compatibility, though, they should be in the form "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. #
|
||||
103
Task/Call-a-function/D/call-a-function.d
Normal file
103
Task/Call-a-function/D/call-a-function.d
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
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);
|
||||
}
|
||||
25
Task/Call-a-function/Forth/call-a-function.fth
Normal file
25
Task/Call-a-function/Forth/call-a-function.fth
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
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 ;
|
||||
70
Task/Call-a-function/Fortran/call-a-function.f
Normal file
70
Task/Call-a-function/Fortran/call-a-function.f
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
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 memorty 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
|
||||
11
Task/Call-a-function/Go/call-a-function-1.go
Normal file
11
Task/Call-a-function/Go/call-a-function-1.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
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) {}
|
||||
9
Task/Call-a-function/Go/call-a-function-2.go
Normal file
9
Task/Call-a-function/Go/call-a-function-2.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
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)
|
||||
8
Task/Call-a-function/Go/call-a-function-3.go
Normal file
8
Task/Call-a-function/Go/call-a-function-3.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
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...)
|
||||
1
Task/Call-a-function/Go/call-a-function-4.go
Normal file
1
Task/Call-a-function/Go/call-a-function-4.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
gif.Encode(ioutil.Discard, image.Black, &gif.Options{NumColors: 16})
|
||||
1
Task/Call-a-function/Go/call-a-function-5.go
Normal file
1
Task/Call-a-function/Go/call-a-function-5.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
if 2*g(1, 3.0)+4 > 0 {}
|
||||
9
Task/Call-a-function/Go/call-a-function-6.go
Normal file
9
Task/Call-a-function/Go/call-a-function-6.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
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")
|
||||
4
Task/Call-a-function/Go/call-a-function-7.go
Normal file
4
Task/Call-a-function/Go/call-a-function-7.go
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
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
|
||||
2
Task/Call-a-function/Go/call-a-function-8.go
Normal file
2
Task/Call-a-function/Go/call-a-function-8.go
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
list = append(list, a, d, e, i)
|
||||
i = len(list)
|
||||
1
Task/Call-a-function/Maple/call-a-function-1.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-1.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
f()
|
||||
1
Task/Call-a-function/Maple/call-a-function-2.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-2.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
f(1,sin(x), g -> int(g(t),t=0..1)
|
||||
1
Task/Call-a-function/Maple/call-a-function-3.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-3.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
f(1, sin(x), g -> int(g(t),t=0..1)
|
||||
1
Task/Call-a-function/Maple/call-a-function-4.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-4.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
f(1, sin(x), g -> int(g(t),t=0..1)
|
||||
1
Task/Call-a-function/Maple/call-a-function-5.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-5.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
f(a,b,method = foo)
|
||||
1
Task/Call-a-function/Maple/call-a-function-6.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-6.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
f(a); f(b);
|
||||
1
Task/Call-a-function/Maple/call-a-function-7.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-7.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
f(a) + g(b)
|
||||
1
Task/Call-a-function/Maple/call-a-function-8.maple
Normal file
1
Task/Call-a-function/Maple/call-a-function-8.maple
Normal file
|
|
@ -0,0 +1 @@
|
|||
x := f(1)
|
||||
2
Task/Call-a-function/Maple/call-a-function-9.maple
Normal file
2
Task/Call-a-function/Maple/call-a-function-9.maple
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
> type( op, 'builtin' );
|
||||
true
|
||||
4
Task/Call-a-function/Perl/call-a-function-1.pl
Normal file
4
Task/Call-a-function/Perl/call-a-function-1.pl
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
foo(); # Call foo on the null list
|
||||
&foo(); # Ditto
|
||||
foo($arg1, $arg2); # Call foo on $arg1 and $arg2
|
||||
&foo($arg1, $arg2); # Ditto; ignores prototypes
|
||||
1
Task/Call-a-function/Perl/call-a-function-2.pl
Normal file
1
Task/Call-a-function/Perl/call-a-function-2.pl
Normal file
|
|
@ -0,0 +1 @@
|
|||
foo;
|
||||
1
Task/Call-a-function/Perl/call-a-function-3.pl
Normal file
1
Task/Call-a-function/Perl/call-a-function-3.pl
Normal file
|
|
@ -0,0 +1 @@
|
|||
&foo;
|
||||
1
Task/Call-a-function/Perl/call-a-function-4.pl
Normal file
1
Task/Call-a-function/Perl/call-a-function-4.pl
Normal file
|
|
@ -0,0 +1 @@
|
|||
goto &foo;
|
||||
3
Task/Call-a-function/Perl/call-a-function-5.pl
Normal file
3
Task/Call-a-function/Perl/call-a-function-5.pl
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
&$fooref('foo', 'bar');
|
||||
&{$fooref}('foo', 'bar');
|
||||
$fooref->('foo', 'bar');
|
||||
|
|
@ -8,6 +8,13 @@ def fixed_args(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
|
||||
|
|
@ -41,6 +48,18 @@ def is_builtin(x):
|
|||
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.
|
||||
|
||||
|
|
|
|||
58
Task/Call-a-function/R/call-a-function.r
Normal file
58
Task/Call-a-function/R/call-a-function.r
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
### 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
|
||||
65
Task/Call-a-function/Scala/call-a-function.scala
Normal file
65
Task/Call-a-function/Scala/call-a-function.scala
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
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
|
||||
277
Task/Call-a-function/XSLT/call-a-function.xslt
Normal file
277
Task/Call-a-function/XSLT/call-a-function.xslt
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
<?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>
|
||||
Loading…
Add table
Add a link
Reference in a new issue