1

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.

pbx
  • 842
  • 4
  • 11
  • 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. – b3m2a1 Mar 14 '17 at 20:00

1 Answers1

3

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?

b3m2a1
  • 46,870
  • 3
  • 92
  • 239
  • 1
    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 :-) – pbx Mar 14 '17 at 21:40
  • 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. – b3m2a1 Mar 14 '17 at 21:43