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$
    – Szabolcs
    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$
    – rcollyer
    Mar 22, 2012 at 14:25
  • $\begingroup$ @Szabolcs Your solution is better, please feel free to edit my answer. $\endgroup$ 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$
    – whuber
    Mar 22, 2012 at 15:00
  • $\begingroup$ @whuber that's true. Then remove the ?NumericQ from them which will allow the additional constructs. $\endgroup$
    – rcollyer
    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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.