More:  Inner[], Outer[], Thread[]...

Inner[Times,{1,2,3,4},{a,b,c,d},Plus]  (* inner product *)

Inner[Plus,{1,2,3,4},{a,b,c,d},Times]

Inner[{#1,#2}& ,{1,2,3,4},{a,b,c,d},Plus]

Select[], Cases[], Position[], Count[]...

?Select

Select[
Table[Random[],{10}],
#>.5&]

Cases[{a, a^b, 3^Pi, Pi^3}, _^_]

Position[{a, a^b, 3^Pi, Pi^3}, _^_]

Functions & Patterns - more

Clear[h]

h[x_]:= x + x

h[x_,y_]:= {y,x}

How to define functions that accept a variable number of arguments?

{
h[3],
h[{{{1}}},"second argument"],
h[1,2,3]
}

?h

h[l__]:=Reverse[{l}]

{h[1,2,3],
h[{1},{2},{3},{4},5,6,7,8],
h[],
h[{1,2,3}]
}//ColumnForm

h[l__]:=Reverse[{l}]

{h[1,2,3],
h[{1},{2},{3},{4},5,6,7,8],
h[],
h[{1,2,3}]
}//ColumnForm

Clear[h]

hh[l__/;Length[{l}]≥2]:={l}[[2]]

hh[1,2,3]

hh[{23,3,1},2,3,{4,5},4,3]

Clear[hh]

hh[first_, second_, rest__]:=second

hh[first_, second_]:=second

hh[1,2]

hh[1,2,3,4,5,6,7]

The triple underscore matches ANY list of arguments, including the empty list

h[l___]:=Length[{l}]

h[]

h[1,2,3,4,5,6,7]

Clear[hh]

hh[l__/;Length[{l}]≥2]:={l}[[2]]

hh[first_, second_, rest___]:=second

penultimate[___,ourguy_,_]:=ourguy

penultimate[1,2,3,4,5,6,7]

function[left_,a_,b_,right_]/;b<a:=
function[left,b,a,right]

function[1,2,3,1,2,3,10,1,2,3,-10]

Clear[function]

function[left___,a_,b_,right___]/;b<a:=
function[left,b,a,right]

function[1,2,3,1,2,3,10,1,2,3,-10]

function[left___,a_,b_,right___]/;b==a:=
function[left,a,right]

function[1,2,3,1,2,3,10,1,2,3,-10]

function[list___]:={list}

function[1,2,3,1,2,3,10,1,2,3,-10]

?function

Clear[function]

list=RandomInteger[10,20]

x + y = k

function[left___,x_,middle___,y_,right___]/;x+y==10:=

Clear[h]

It is possible to assign a name to structures comprising several patterns.

h[x_,{1,2}]:=  {"Yes","No"}[[Random[Integer]+1]]

h[2,{1,2}]

h[off_,pair:{_,_}]:= pair[[Random[Integer]+1]]+off

h[2,{x,y}]

h[off_,{v1_,v2_}]:= {v1,v2}[[Random[Integer]+1]]+off

h[off_,pair_List/;Length[pair]==2]:= pair[[Random[Integer]+1]]+off

h[10,{Pi,E}]

Clear[f]

f[x:_^_]:=p[x]

?f

{
f[2^3],
f[Pi^2],
f[a^b]
}

f[x:_^e_]:=p[x,e]

{
f[2^3],
f[Pi^2],
f[a^b]
}

?f

Clear[h]

f[h[_],h[_]]:=q

{
f[h[4],h[5]], 
f[h[Pi],h[Pi]]
}

f2[h[x_],h[x_]]:=q

Clear[ff]

ff[x_,x:h[_]]:=r[x]

{
ff[Sin,Sin[4]], 
ff[h[4],h[5]],
 ff[h[Pi],h[Pi]]
}//ColumnForm

Clear[f]

f[m:{{a_, 0},{b_, c_}}]:=  m[[2]]

or alternatively

f[m:{{_, 0},{_, _}}]:=  m [[2]]

but also

f[{{_,0},m:{_,_}}]:=m

f[{{a_,b_},{c_,d_}}] :=  a d - b c

f[
{{1,2},
{2,3}}
]

?f

f[
{{1,0},
{a,b}}
]

f[
{{exp1, 1},
{exp1, exp1}}
]

Tests and constraints on a pattern can be specified through ? and /; after the underscore.
f [ x_ ? testFunction ] := ...
x is matched only if testFunction[ x ] returns True.
f [ x_?EvenQ ] only matches even numbers.
f [ {x_, y_} /; condition( x, y ) ] only matches the pairs {x, y} that satisfy the condition.

Factorial
n Integer & Positive :  n!
n Integer & Negative : (-n)!
x Real &Positive: floor(x)!
x Real &Negative: ceiling(x)!

?If

Quit[]

fact[n_]:=
If[n==0, 
1,
If[n>0,
n*fact[n-1],
fact[-n]
]
]

myfact[0]=1;
myfact[n_Integer?Positive]:=n myfact[n-1]

myfact[n_Integer?Negative]:=myfact[-n]

myfact[x_Real/;x>0]:=myfact[Floor[x]]

myfact[x_Real?Negative]:=myfact[Ceiling[x]]

?*Q

myfact[0]

?myfact

h[x_,2x_]:=x^2-3

{h[3,6],h[Pi,2Pi],h[x,2 x],h[Sin[x], 2 Sin[x]]}

Clear[h]

h[x_,y_]/;y==2 x:= x^2-3

{h[3,6],h[{Pi,2Pi}],h[x,2 x],h[Sin[x], 2 Sin[x]],h[0,0]}

Clear[g]

g[ {x_, y_,l___}/; x+y == 4 ]:= {l}

g[{3,1,2,2,4,1}]

g[g[{3,1,2,2,4,1}]]

g[g[g[{3,1,2,2,4,1}]]]

g[x_/;x>2]:= Sin[x]
g[x_Real]:=x^2
g[x_Complex]:=Exp[-x]
g[x_Integer]:=Prime[x]

Plot[g[x],{x,-1,6}]

Clear[f]

pattern -> sorting?

...

what does the following pattern match?

t[f_[a_,b_]]:={f,a,b}

t[g[a,b]]

t[Sin[x,y]]

t[Sin[x+y]]

t[Sin[3+Pi]]

Sin[3+Pi]//HoldForm

ReleaseHold[HoldForm[Sin[3+Pi]]]

FullForm[Sin[3+Pi]]

t[f_[_,b_]_]:=(Print["match!"];{f,b})

k=t[3 myfun[3,exp]]

FullForm[f_[_,b_]_]

Optional arguments

Clear[f,M]

f[a_, b_, c_,mode_:"Lower"]:=
Which[
 mode == "Lower", 
{{a, 0},
{b,c}},
mode=="Upper",
{{a,b},
{0,c}},
True,
Print["mode error in function f"];Abort[]
]

f[M[1],M[2],M[3],"Upper"]//MatrixForm

f[M[1],M[2],M[3],"Lower"]//MatrixForm

f[M[1],M[2],M[3],"Symmetric"]

f[M[1],M[2],M[3]]//MatrixForm

Clear[f]

f[a_^b_]:={a,b}

{f[1^2],f[2^1],f[Pi^(t+y)],f[(t+y)]}

ff[a_^(b_:1)]:={a,b}

{ff[1^2],ff[2^1],ff[Pi^(t+y)],ff[(t+y)]}

Recap

f[x_]:= (* general function definition *)

f[x_List]:= (* restricting the type of the arguments *)

f[x_,y_]:= (* multiple arguments *)

f[x_,"a"]:= (* fixing one of the arguments *)

f[x_?NumberQ]:= (* test on argument x *)

f[x_,y_,z_/;condition[z]]:= (* condition on argument z *)

f[x_,y_,z_]/;condition[x,y,z]:=(* condition on arguments *)

f[a_,b__,l___]:=
(* matching one element, a non-empty list of elements, any list  *)

f[a_,b__,l___]:={l}

f[a_+b_]:=(* specifying the form of the argument *)

f[{{a_,b_},___}]:=(* again, specifying the shape of the argument *)

f[m:{_^b_}]:=Power[m,-b]:=(* assigning names to parts of a pattern *)

f[a_,b_:Pi]:=Sin[a+b]:= (* default arguments *)