4
$\begingroup$

I would like to be able to call a function an unspecified number of times. That is, I would like the generalization of something like:

   Sample[yi_, yf_, yinc_, zi_, zf_, zinc_]:=
          Table[{y, z}, {y, yi, yf, yinc}, {z, zi, zf, zinc}]

to $n$ variables, all with their own respective initial, finial and incremental values, and so I'd be calling on Table $n$ times. Is something like this even possible?

$\endgroup$

2 Answers 2

5
$\begingroup$

Something like :

sample[ranges_] := Table[Evaluate[ranges[[All, 1]]], Evaluate[Sequence @@ ranges]]

used like :

sample[{{x, 0, 3, 1}, {y, -2, 2, 1}}]
$\endgroup$
11
  • 2
    $\begingroup$ Or you can use ranges__ and avoid Sequence and Evaluate. $\endgroup$ Commented Mar 22, 2012 at 14:20
  • $\begingroup$ I would use ranges:{{_Symbol, _?NumericQ, _?NumericQ, _?NumericQ} ..} or ranges:{_Symbol, _?NumericQ, _?NumericQ, _?NumericQ} .. which forces the user to give the correct form for the iterators. Personally, I'd use the second form of ranges as it is called like Table: sample[{x,0,3,1},{y,-2,2,1}]. Also, you'd remove the Sequence @@ shortening the code. $\endgroup$ Commented Mar 22, 2012 at 14:25
  • $\begingroup$ @Szabolcs Your solution is better, please feel free to edit my answer. $\endgroup$ Commented Mar 22, 2012 at 14:31
  • $\begingroup$ Protecting the user by specifying the argument types is good. Note, however, that it precludes constructs in which the endpoints of some ranges depend on the values in the current range, such as {x, 0, 3, 1}, {y, 0, x, 1}. $\endgroup$ Commented Mar 22, 2012 at 15:00
  • $\begingroup$ @whuber that's true. Then remove the ?NumericQ from them which will allow the additional constructs. $\endgroup$ Commented Mar 22, 2012 at 15:17
2
$\begingroup$

Going by the suggested syntax in your question you might find use in this:

sample[params__] := Range @@@ Partition[{params}, 3]

This does no type checking and assumes that your params list is in threes.
I kept it simple for ease of reading.

Example:

tbl = sample[3, 12, 2, 5, 1, -1]
{{3, 5, 7, 9, 11}, {5, 4, 3, 2, 1}}

On this output could use Outer:

Outer[ff, ##] & @@ tbl
{{ff[3, 5], ff[3, 4], ff[3, 3], ff[3, 2], ff[3, 1]},
 {ff[5, 5], ff[5, 4], ff[5, 3], ff[5, 2], ff[5, 1]},
 {ff[7, 5], ff[7, 4], ff[7, 3], ff[7, 2], ff[7, 1]},
 {ff[9, 5], ff[9, 4], ff[9, 3], ff[9, 2], ff[9, 1]},
 {ff[11, 5], ff[11, 4], ff[11, 3], ff[11, 2], ff[11, 1]}}

If you allow for more flexible syntax, you might use:

Outer[ff, ##] & @@ Range @@@ {{3, 12, 2}, {5, 1, -1}, {3}}
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.