0
$\begingroup$

I need a simple function that can be called without any arguments, myFunction[ ], that will create an element of a data structure. However, each element in the data structure has a "label" associated with it. You can assume the data structure to be of the form <| |> and the first element has the Key "label" and a symbolic value, say myLabel. So, the data structure is essentially <| "label"->"myLabel", Key2->value2, etc... |> .
I can certainly build the function that will take myFunction[myLabel] and use the incoming myLabel as the value of the Key "label". However, What I also want to be able to do is either one of the two things below:

  1. when I call my function myLabel = myForce[] without an argument, it should create the data <| "label"->"myLabel", Key2->value2, etc... |>. This will require somehow the ability to use the incoming Stack and parse the incoming myLabel from the right hand side of the equal sign and use it. I could never competely figure out the use of Wolfram Stack

So I also tried Cache'ing

  1. Create the data structure "Metaaata approach" with a place holder "label" value, say NoLB, when the function is called without an argument. It will create the first entry in the Cache as <| "label"-> "NoLB", Key2->value2, ..etc |> so when I use myLabel = myFunction[] it will assign the data structure to myLabel, which will be what I just typed above. If I can call myFunction again with myFunction[myLabel] (note here myLabel is not a symbol but data structure at this point), I can have another definition of my myFunction defined with a pattern matching myFunciton[x_"Head of the data structure] := and take x go to the Cache and if there is an entry with $NoLB in there, replace it with the data structure with one that has the "label" of x.

Simpler way of solving this dilemma appears to be avoid calling the myFunction without an argument, and force/train the user to only call it as something = myFunction[myLabel], which I may finally accept. However, thinking about it I suspect Wolfram developers already have a way to solve this problem very easily, but that information is not documented anywhere, and ChatGPT plugin keeps refusing to address the issue taking me around loops and hoops. Yes, I have been working on it for a week, and finally last three days with ChatGPT plug in. I have learned tremendous amount of information about programming fancy constructions, but was never able to solve it completely.

Can somebody comment on my question, and hopefully provide a simple solution. Sory for the lengthy question, but I thought I need to try explaining it well.

$\endgroup$
15
  • $\begingroup$ myFunction[ ], that will create an element of a data structure... Does that mean literally just create a small structure that you will then insert into a larger structure? Or does it mean that it will not just create the small structure but also add it to the large structure? Or does it mean that it will just update the small structure based on a pre-existing key in the large structure? $\endgroup$
    – lericr
    Commented May 13 at 17:29
  • $\begingroup$ It would be a lot easier if you walked us through a concrete example. $\endgroup$
    – lericr
    Commented May 13 at 17:29
  • $\begingroup$ I think Stack is a red herring here. I can't quite figure out what you're trying to do, but I doubt that Stack will be at all helpful. $\endgroup$
    – lericr
    Commented May 13 at 17:34
  • $\begingroup$ Wait, are you just trying to update global variables? $\endgroup$
    – lericr
    Commented May 13 at 17:35
  • $\begingroup$ Ideally, it is simple. I want the function that I write say my, myFunction[ ] := Module[{ ], "some operations to create a resulting data"]. The data will be in the form of an Associations. Say, <|"label"-> "Name", ..., "and some additional Keys and Associated Values" |> ]. $\endgroup$
    – ZGurdal
    Commented May 13 at 19:16

3 Answers 3

0
$\begingroup$

I hesitate to provide an answer, because this sounds like a supremely dangerous and confusing thing to do. First off, Set is a built in function, and it's such a fundamental one that you really don't want to override it. So, I suggest you just mimic it by using a similar symbol.

Let's start by defining the actual functionality you want in the normal way (assuming I understand the situation, which I actually am not sure I do).

$theData = <||>;

MyFunctionSetOnce[symbol_Symbol, value_] :=
  ($theData[SymbolName[symbol]] = value;
   symbol = $theData)

Then we can use a "pretty" symbol in place of Set.

TildeTilde = MyFunctionSetOnce

Now we can use it this way:

x ≈ y;

$theData // InputForm
(* <|"x" -> y|> *)

x // InputForm
(* <|"x" -> y|> *)

In practice, the ≈ (which is actually \[TildeTilde]) can be entered as ESC ~~ ESC.

I've named the function MyFunctionSetOnce because you can't use it twice on the same symbol.

x ≈ z
(* MyFunctionSetOnce[<|"x" -> z|>, z] *)
(* The Association doesn't match _Symbol so nothing happens. *)

If you want to be able to update the same key multiple times, you can try something like this:

SetAttributes[MyFunctionSetOrUpdate, HoldFirst];

MyFunctionSetOrUpdate[symbol_Symbol, value_] :=
  ($theData[SymbolName[Unevaluated[symbol]]] = value;
   symbol = $theData);

TildeTilde = MyFunctionSetOrUpdate;

x ≈ "hello"
(* <|"x" -> "hello"|> *)

x ≈ "goodbye"
(* <|"x" -> "goodbye"|> *)

Now, I still don't know why just using a style like MyFunction[myLabel] is undesirable. It avoids some side effects (which are potentially confusing) and it is probably familiar to most students even if they haven't seen that literal syntax before. And you could even use postfix form:

myLabel // MyFunction

which is structurally similar to

myLabel = MyFunction[]

But I personally wouldn't stop even there. I'd go all the way to "pure" functional style and avoid side effects altogether. You seem sure that this would be confusing, but I honestly don't think it would be. If these are aerospace engineering students, then they really shouldn't have any problem with the side-effect-free approach.

$\endgroup$
3
  • $\begingroup$ Initially I had difficulty understanding why you thought I was trying to overload the Set because that was not my intention. After spending some time reading your note, I now know why, and what you are suggesting is more powerful than what I thought. $\endgroup$
    – ZGurdal
    Commented May 14 at 15:22
  • $\begingroup$ In fact I have a new symbol combinations for the newSet that you are suggesting, but the symbol that I have in mind does not seem to have any definition in Wolfram, and I need to create a keyboard shortcut for it (instead of [TildeTilde] of course ). Would you be interested in helping me to set up a new definition for keyboard shortcut for a new symbol ? Or at least put me on the right track to find more about it so that I can do it myself? $\endgroup$
    – ZGurdal
    Commented May 14 at 15:24
  • $\begingroup$ Look in the documentation for InputAliases and InputAutoReplacements. $\endgroup$
    – lericr
    Commented May 14 at 15:52
0
$\begingroup$

This is not an answer, and the code won't do what you want at all, but I'm just trying to clarify what you want.

(* Initial state. We've presumably created the implementation for myFunction and an initial 
   value for this data object. Let's give the data object a name. *)
$theData = <||>;

(* Now we're going to invoke myFunction[] using Set. *)
myLabel = MyFunction[];

(* That presumably had an effect, but this is where I'm getting confused. *)
(* If we check $theData, what should we now see? *)
$theData

(* It seems like you want something like <|"label"-> ??? |> , but I don't know 
   what the ??? should be. Somehow we inspect the left hand side of the Set, so 
   do you want $theData to literally be <|"label" -> "myLabel"|> ? *)

(* Also, something was done to myLabel, but I'm confused about that too. If we 
   check myLabel, what should we now see? *)
myLabel

(* Should we get myLabel === $theData ? *)
$\endgroup$
4
  • $\begingroup$ Yes and yes. Even though I used myLabel = in reality it will become a data object $theData with a Head Association. Yes, at that point $theData will be <|"label" -> "myLabel"|>. , and myLabel === $theData will produce Yes. $\endgroup$
    – ZGurdal
    Commented May 13 at 20:17
  • $\begingroup$ Sorry, the Dollar makes the text italic, could don't figure out. the reason that I used myLabel on the left hand side of Set was misleading, it was just to indicate that the symbol on the left of Set will become the "label" in the data. $\endgroup$
    – ZGurdal
    Commented May 13 at 20:21
  • $\begingroup$ In the future myFunction will be overloaded with bunch of pattern matching to manipulate the DollarTheData to change some additional elements of the data specified by their own Key's $\endgroup$
    – ZGurdal
    Commented May 13 at 20:23
  • $\begingroup$ Okay, so next question. Why do you want to use Set instead of just myFunction[myLabel]? You can still get the side effect and you don't need to duplicate myLabel as in myLabel = myFunction[myLabel]. $\endgroup$
    – lericr
    Commented May 13 at 21:02
0
$\begingroup$

Good, I am almost convincing you. This is a particular aerospace engineering system, and the name of the function and the name of the label has connotations with the data object being created. once I use my function myFunction[myLabel], I will have to assign it to some variable name that I will be using repeatedly. There is nothing better to assign it to, other than the label of the data. This will be Freshman level students who really do not want to be confused.... :) So, is there any hope for this. (1) is my ideal option, if it can be done, but as you said Stack is very difficult to use, and I repeatedly get warnings about non-existence of good documentation, and other dangers of Stack[] or Stack[_]. I am almost ready to give up, and go to Metadata option, which I do not expect to be easy option either.

$\endgroup$
4
  • $\begingroup$ Okay, so the reason you want to use Set is simply because you like the form of myLabel = myFunction[]. You think that the students will understand the = better than just a function call with side effects. Is that correct? $\endgroup$
    – lericr
    Commented May 13 at 22:27
  • $\begingroup$ Yes, what I am trying to do is not any different than Wolfram List[]. In the field that I will use, myFunction is as fundamental as List. I basically every functionality in List to be in my myFunction. The only side effect that I know is if I call a = List[a] I will get RecursionLimit error. But I know how to eliminate that either changing the error message so that students will not try that, or I can use Block (with or without Module) to fix it. Any more questions. You are asking very good questions. Do you work for Wolfram? $\endgroup$
    – ZGurdal
    Commented May 13 at 22:59
  • $\begingroup$ @lericr Yes, keyboard shortcuts are working as a charm. Now back to original discussion, why just using a style like MyFunction[myLabel] is undesirable. I will have to admit, it is not, but I do not understand it. If I create the data object with it, I will do what I want, but then what do I do with it. I have to assign it to something so that I can use it. The only assignment thing that I can think of is Set. Wait, I may just be realizing what you saw a while ago only now. Your MyFunctionSetOnce would do the trick that I need. $\endgroup$
    – ZGurdal
    Commented May 14 at 21:49
  • $\begingroup$ I am going back and seriously start coding your approach. I was just reading. Will let you know how it is evolving. My brain apparently slowed down quite a bit. $\endgroup$
    – ZGurdal
    Commented May 14 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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