Exercises in Programming Style–Introspective

NOTE : read the rest of the series, or check out the source code.

If you enjoy read­ing these exer­cises then please buy Crista’s book to sup­port her work.

exercises-prog-styles-cover

Fol­low­ing on from the last post, we will look at the Intro­spec­tive style today.

 

Style 16 – Introspective

This marks the start of a cou­ple meta-pro­gram­ming relat­ed styles which also includes Reflec­tive, Aspects and Plu­g­ins.

If you have come from a .Net or Java back­ground then the sub­tle dif­fer­ence between intro­spec­tion and reflec­tion might not be obvi­ous. This wikipedia arti­cle gives a pret­ty good expla­na­tion:

type intro­spec­tion is the abil­i­ty of a pro­gram to exam­ine the type or prop­er­ties of an object at run­time

Intro­spec­tion should not be con­fused with reflec­tion, which goes a step fur­ther and is the abil­i­ty for a pro­gram to manip­u­late the val­ues, meta-data, prop­er­ties and/or func­tions of an object at run­time.

Constraints

  • The prob­lem is decom­posed using some form of abstrac­tion (pro­ce­dures, func­tions, objects, etc.)
  • The abstrac­tions have access to infor­ma­tion about them­selves and oth­ers, although they can­not mod­i­fy that infor­ma­tion

 

In her exam­ple, Crista used two of Python’s intro­spec­tive capa­bil­i­ties:

  1. inspect­ing the stack to see who the caller is and only allow the func­tion to be called from ‘extract_words’
  2. fetch­ing the val­ue of the argu­ment passed into the func­tion

both feel a bit con­trived, espe­cial­ly 2.

I don’t know of any ways to do 1. in F#, you can walk the stack­frame but it gives you file­name, line num­ber, method name, etc. but I didn’t find a way to get the call­ing func­tion name in any usable form. Since I’m doing this exer­cise in a F# script might have com­pli­cat­ed mat­ters fur­ther, as I kept see­ing things such as ‘FSI_0004’ as type names.

After giv­ing this some thought, I think a more real­is­tic exam­ple in our con­text here is to use objects to hold data as prop­er­ties and use intro­spec­tion to fetch their val­ue.

 

So first, let’s define the two types which we’ll use intro­spec­tion on:

Style16_02

Style16_03

We’ll use intro­spec­tion to get at the DataStorage.Words and StopWordsFilter.StopWords prop­er­ties. But, let’s do that with style and define the dynam­ic oper­a­tor to do the heavy lift­ing for us:

Style16_01

and now we can have a fil­ter­Words func­tion that:

  • takes two argu­ments  — dataS­tor­age and fil­ter
  • dataS­tor­age can be of any type with a string[] prop­er­ty called Words
  • fil­ter can be of any type with a Set<string> prop­er­ty called Stop­Words

Style16_04

this func­tion has the sig­na­ture of

a -> ‘b -> seq<string>

Per­haps here lies the strength and weak­ness of this approach:

  • that it’s much more gener­ic than if we had depend­ed upon the con­crete types, and would even work with types that I don’t con­trol (and there­fore can’t enforce any inter­faces upon them)
  • but the con­straints on dataS­tor­age and fil­ter are now implic­it and you’ll have to inspect my code to fig­ure them out

a much bet­ter solu­tion in F# would be to use sta­t­i­cal­ly resolved type para­me­ters, but that’ll be out-of-style I think.


Next, we’ll add anoth­er func­tion to count the fre­quen­cy of the fil­tered words, noth­ing spe­cial here:

Style16_05

Final­ly, to string every­thing togeth­er:

Style16_06

 

You can find the source code for this exer­cise here.