0
$\begingroup$

I'd like to make a function that has many parts. Doing this in something such as Java, which I am familiar with, would be simple. In Mathematica I have these "pieces", which I want to put into a single function:

(* These are just example values for testing. *)
m = 2;
portionOfPT = "friday";
portionOfCT = "pqcfku";

(* I want all of this to happen within the function. *)
ptBlocks = Partition[stringToNumbers[portionOfPT], m]
ctBlocks = Partition[stringToNumbers[portionOfCT], m]
ctMatrix = {ctBlocks[[1]], ctBlocks[[2]]}
ptMatrix = {ptBlocks[[1]], ptBlocks[[2]]}
inversePTMatrix = Inverse[ptMatrix, Modulus -> 26]

(* This is what I want to return.*)
key = Mod[inversePTMatrix.ctMatrix, 26]

The function would be something like this with two parameters:

autoPTAtkHill[portionOfPT_, portionOfCT_, m_] := 

How do I go about making a function containing multiple parts like this that depend on what is returned from the previous.

EDIT:

Does this look correct, and by correct I mean proper. It gives the correct results.

autoPTAtkHill[portionOfPT_, portionOfCT_, m_] := 
  Module[{key},
   ptBlocks = Partition[stringToNumbers[portionOfPT], m];
   ctBlocks = Partition[stringToNumbers[portionOfCT], m];
   ctMatrix = {ctBlocks[[1]], ctBlocks[[2]]};
   ptMatrix = {ptBlocks[[1]], ptBlocks[[2]]};
   inversePTMatrix = Inverse[ptMatrix, Modulus -> 26];
   key = Mod[inversePTMatrix.ctMatrix, 26]
  ];
$\endgroup$
7
  • 1
    $\begingroup$ Remember that a comment in Mathematica is (*...*) ,not // reference.wolfram.com/language/guide/Syntax.html $\endgroup$ Feb 22, 2015 at 18:12
  • 1
    $\begingroup$ Check the documentation on Module. $\endgroup$
    – Szabolcs
    Feb 22, 2015 at 18:15
  • $\begingroup$ My mistake, thank you for pointing this out. $\endgroup$
    – connor
    Feb 22, 2015 at 18:15
  • $\begingroup$ Thanks for pointing me into the correct direction with Module. Could you check my edit and tell me if it is the way others would expect the function to look. $\endgroup$
    – connor
    Feb 22, 2015 at 18:49
  • 2
    $\begingroup$ minor point, but there is no purpose here to assigning the symbol key. Your Mod expression will be returned by the function without it. also ptBlocks,ctBlocks etc probably ought to be put in the Module scope unless of course you want them available later as a side effect. $\endgroup$
    – george2079
    Feb 22, 2015 at 20:56

1 Answer 1

4
$\begingroup$

I would do something like this:

autoPTAtkHill[portionOfPT_, portionOfCT_, m_] := 
  Module[{ptBlocks, ctBlocks, ctMatrix, ptMatrix, inversePTMatrix},
   ptBlocks = Partition[stringToNumbers[portionOfPT], m];
   ctBlocks = Partition[stringToNumbers[portionOfCT], m];

   ctMatrix = {ctBlocks[[1]], ctBlocks[[2]]};
   ptMatrix = {ptBlocks[[1]], ptBlocks[[2]]};

   inversePTMatrix = Inverse[ptMatrix, Modulus -> 26];
   Mod[inversePTMatrix.ctMatrix, 26]];

As @george2079 says, the last statement in the Module is implicitly returned, so you don't need to assign it. I recommend reading my answer here to clarify what exactly is going on here (it's very important).


By the way, instead of {ctBlocks[[1]], ctBlocks[[2]]} you can do Take[ctBlocks,2] or ctBlocks[[1;;2]].


One thing to recognize is that there isn't any limit to what you can put inside Module. You can make functions scoped within the Module, for example:

f[a_] := Module[{innerF},
  innerF[n_] := n + 2;

  innerF[a + 2]];

For this matter, Module is its own thing:

Module[{innerF},
  innerF[n_] := n + 2;

  innerF[10]]

And not necessary to create a function:

f[a_] := (
  var1 = 1;
  var2 = 2;
  a + var1 + var2
);

Module is used to limit the scope of variables.


An idiom I sometimes use is something like this:

autoPTAtkHill[portionOfPT_, portionOfCT_, m_] := 
  Module[{partition, firstTwo, inverse, process, ctMatrix, inversePTMatrix},

   partition = Partition[#, m] &;
   firstTwo = Take[#, 2] &;
   inverse = Inverse[#, Modulus -> 26] &;

   process = RightComposition[{stringToNumbers, partition, firstTwo}];

   ctMatrix = process[portionOfCT];
   inversePTMatrix = inverse[process[portionOfPT]];

   Mod[inversePTMatrix.ctMatrix, 26]];

Which is useful if your algorithm has more complicated steps. There are quite a few functions like RightComposition. This however is not a very common idiom and might actually be harder to read for some people, the fools.


Finally, you can do things like this:

Module[{expensiveToCompute},
 expensiveToCompute = expensiveComputation[blah, blah, blah];

 myFunction[a_, b_] := Module[{},
   expensiveToCompute * etc
   ]]

Where expensiveToCompute is computed only once yet its value is hidden and only available to myFunction (within reason). Because myFunction is not shadowed by the outer Module, it's available in the global scope.

$\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.