1

I'm trying to define a function f which takes a list of reals. My purpose is to build a function which I can give a list of reals, integers or strings and have it build an appropriate probability distribution for.

So I'd like to do something like

f[{samples_Real}]:=makeRealDist[samples];
f[{samples_Integer}]:=makeInteger[samples];
f[{samples_String}]:=makeCategoricalDist[samples];

I can easily match on Real/Integer/Strings. The part I can't figure out is how to match on a list of Real/Integer/String.

Artes
  • 57,212
  • 12
  • 157
  • 245
Steven
  • 11
  • 1
  • 1
    Almost there! f[{samples__Real}] or f[samples:{__Real}] – mfvonh Jun 24 '14 at 04:02
  • That seems about right for what I want, thank you! I was close. However, samples is then treated as a "Squence[samples]", I was expecting just a list of reals/integers/strings like {1.0, 2.0, 3.0}. I'm obviously missing something in my understanding, any pointers to what that might be? I'm hoping to pass this list on to my makeRealDist function... – Steven Jun 24 '14 at 04:13
  • The second option will give you a list. – mfvonh Jun 24 '14 at 04:15
  • You can also use Repeated (..), but here BlankSequence (__) is simpler. – mfvonh Jun 24 '14 at 04:20
  • f[samples:{__Real}] Seems to be exactly what I was looking for. But what is the difference between {Samples__Real} and samples:{_Real} ? – Steven Jun 24 '14 at 04:24
  • 2
    Are you sure you want Real? This way 3 will be rejected, but 3. will be accepted. Why not check for NumericQ? but may be you really want Real. – Nasser Jun 24 '14 at 04:26
  • Basically everything on the LHS of := is a pattern (not technically a Pattern but no matter), so it's just a question of what parts of that pattern you want to attach a definition to for use on the RHS. So samples__Real means you are capturing the sequence itself, whereas samples:{__Real} means you are capturing the list (which is just the head List wrapped around a sequence). – mfvonh Jun 24 '14 at 04:28
  • @Nasser's suggestion is a good one unless you have a specific need for Reals. You'd implement it like this: f[samples:{__?NumericQ}] – mfvonh Jun 24 '14 at 04:33
  • @Nasser I'm actually overloading the function for lists of different types. So I can take data of different types and have a single code path dealing with it: f[samples:{__Real}]:=somethingReal[samples]; f[samples:{__Integer}]:=somethingUnreal[samples]; f[samples:{__String}]:=secondReality[samples]; Imagine pulling data out of a database, I can map each column full of data. Map[f, DBQueryResults] – Steven Jun 24 '14 at 04:34

1 Answers1

6

I feel that the basics of this topic are well covered in my answer to:

Once you have read that and understand BlankSequence, Repeated, and Pattern you will understand that you could use either of these:

f1[samples : {__Real}]   := makeRealDist[samples]
f2[samples : {_Real ..}] := makeRealDist[samples]

If you wish to permit integers, fractions, etc, you can use NumberQ or perhaps even NumericQ.
Viable semantics include:

f3[samples_List] /; VectorQ[samples, NumberQ] := makeRealDist[samples]
f4[samples : {__?NumberQ}] := makeRealDist[samples]

Timings will show that the first forms (f1 and f3) are to be preferred:

SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]

packed = Range[1, 1000, 0.0001];
timeAvg @ #[packed] & /@ {f1, f2, f3, f4}
{3.67616*10^-7, 0.1404, 5.59104*10^-7, 1.201}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Blacksequence? That sure soundeth sinister, nay, eldritch even. Goes well with your username, too :D – Yves Klett Jun 24 '14 at 07:45
  • @Yves You mean you don't mutter dark incantations as you code? :o) – Mr.Wizard Jun 24 '14 at 15:41
  • 1
    Well, more like PEGI 18 obscenities, at times. But they most assuredly do not help with the code as such. Hmm, worth a try. Now where did I put my Necronomicon again? Ah... right next to my NKS special edition and the Laundry files :D – Yves Klett Jun 24 '14 at 16:03
  • f1[samples : {__Real}] := makeRealDist[samples] Reads cleanest to me, and has a benefit of being quite fast. Thank you all who helped. – Steven Jun 25 '14 at 18:57
  • @user159805 You are welcome for my part. If you find this answer fully satisfactory please consider Accepting it. Also please consider choosing a more "human" username. – Mr.Wizard Jun 25 '14 at 22:25