1
$\begingroup$

General problem

I am looking for a possibility to store information in parallel for a function and change the information when a function is called.

Idea

It seems possible to solve this problem by using DownValues of a function. Imagine I use

makeFileCache[stream_, cacheSize_] := fileCache[OpenRead[stream], cacheSize];
fileCache[stream_, cacheSize_]["Size"] := cacheSize;
fileCache[stream_, cacheSize_][newCacheSize_]:= ???;
f = makeFileCache[STREAM, 12]; (* use arbitrary STREAM here. *)

This way I could for example

f["Size"] 

in order to get the DownValue of the cache size. But is there a possibility to set it directly when calling? I know it is possible to manipulate it directly, this is not what I ask for. I look for a possibility to replace the question marks and directly work on the function f and change its underlying parameters.

As I didn't know what exactly to look for it might be possible (and probable) that this question is a duplicate. Hints are appreciated.

$\endgroup$
  • $\begingroup$ I'm not sure exactly what you mean. Do you mean you want to call f[n_] and have that reset the cache size? Also have you seen Associations? They were introduced in 10.0 and will probably make your life easier. $\endgroup$ – b3m2a1 Mar 14 '17 at 20:00
3
$\begingroup$

So if I understand you correctly, you want f to work in an oop like manner. There are a few things you could do here. One if go full OOP:

$cacheStore =
  <||>;

makeFileCache[stream_, cacheSize_] :=

  With[{fcUUID = CreateUUID["FileCache-"]},
   $cacheStore[fcUUID] = <|
     "Size" -> cacheSize,
     "Stream" -> OpenRead[stream]
     |>;
   fileCache[fcUUID]
   ];

fileCache[uuid_]["Size"] :=
  $cacheStore[uuid, "Size"];
fileCache[uuid_]["Stream"] :=
  $cacheStore[uuid, "Stream"];
fileCache[uuid_][
   newCacheSize_Integer] :=
  ($cacheStore[uuid, "Stream"] = 
    newCacheSize);

But this is overkill and you'll have to clear that $cacheStore yourself.

Cleanest is probably a setCacheSize function:

setCacheSize[fileCache[stream_, size_], newsize_] :=

  fileCache[stream, newsize];
setCacheSize[s_Symbol?(MatchQ[_fileCache]), size_] :=

  s = fileCache[First@s, size];
setCacheSize~SetAttributes~HoldFirst;

These are the two most reasonable routes, I think, but obviously I could be wrong. There's a universe of stuff discussing object-oriented programming in Mathematica. See for instance the first two results I got by searching for "OOP" How can I implement object oriented programming in Mathematica?, Struct equivalent in Mathematica?, and then for completeness there's this: Which Object-oriented paradigm approach to use in Mathematica?

$\endgroup$
  • 1
    $\begingroup$ This is indeed exactly what I was looking for. Sometimes Mathematica's way of thinking drives me crazy coming from other languages. Thanks a lot :-) $\endgroup$ – pbx Mar 14 '17 at 21:40
  • $\begingroup$ It's a lot to get a handle on if you're an oop person, like I am. But the language is powerful and the unified symbolic nature of the language is actually a real pleasure once you get a handle on it. In any case I'm hoping real(ish) OOP framework built on a UUIDs and Associations will make it into the language at some point. I doubt it though. $\endgroup$ – b3m2a1 Mar 14 '17 at 21:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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