Open lukaszkadlubowski opened 11 months ago
Currently forbidden, but unlike in older STACK versions, we do not have impossible technical constraints for allowing this. The constraints are more related to author-side debugging messages and how those should represent things. One reason why these might still have some issues in our world is this:
a: mystruct("foo","bar");
defstruct (mystruct (fieldA, fieldB);
b: new(mystruct);
b@fieldA: "foo";
b@fieldB: "bar";
print(tex1(a));
print(tex1(b));
Basically, from the outside, it is difficult to distinguish between structs and function calls.
The approach I think is most used is the so-called inert function, like stackunits(num,unit)
, where things are tied together with a function call that will never be evaluated because the function has no definition. Naturally, this has the problem of dealing with accessing individual fields; fields are not named but instead positional, and it is often simpler to unpack all fields. As an example, lately, I have been playing with representing graphs and in my case, this is a typical access method, i.e. unpack and repack, which is obviously less convenient than that @
operator or updating a list element by index:
ta: directed_graph( [[-0.5,5.5],[-2.5,-2],[4,-2],[-7,1]], [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2],[4,2]] );
[nodes, edges]: args(ta);
/* Naturally, if there were more "arguments", one can access by position to pick singular things. */
edges: args(ta)[2];
/* Then one could simply return that same thing back */
retval: directed_graph(nodes, edges);
In general, lists have proved to be very useful, especially if one knows how to unpack them using that multi-assign operator like on the second line of the example. However, every now and then people need to have maps/dictionaries, and as not everyone is aware of the way the handy assoc
-function works there are some utility functions in STACK for creating so-called "STACK-maps". STACK-maps are a bit silly construct, but as we needed a way to distinguish dictionaries and lists in an unambiguous way in our own JSON parser, those were created to fill in that blank.
As to functions returning many things, I think that returning a list is the STACK way of doing things, even our answer tests follow that pattern:
[Errors, Result, FeedBack, Note]: AnswerTest(StudentAnswer, TeacherAnswer, [Opt], [Raw]);
Naturally, if it returns a massive number of things you cannot unpack them selectively in that assignment. Either unpack all or take the result as a list and pick some from that.
The path for them to become a thing in STACK is as follows, and I don't really see how it would fit our current development plans as it does not really connect to any of the things in movement currently. But I will keep my eyes open to avoid them becoming impossible again.
defstruct
-calls are identified and present in all execution contexts using those structs.defstruct
-calls and ensure that no conflicting definitions are in play.@
.@
as an operator to the parser (well the next-gen parser does have it), and allow it in the pre-parsing char filter.Of those number 3 is probably the one that would require the most work.
Thank you very much for the detailed answer. Actually, I have been using list unpacking already, but as some of my functions would return lists with dozens of elements, relying on the order of items in the list quickly becomes tiresome and the code is difficult to read. Also, assuming I get it right, each variable name used in unpacking needs to be listed in the block([...],)
if I want local variable scoping, etc. The whole thing becomes very verbose and error-prone.
I will look at the alternatives you mentioned. It would be nice to have the possibility of using structs sometime in the future.
Thank you for your help and your work on this great tool!
Hello,
What I want to achieve
I have several functions that should return structured data that I want to access in a key-value manner. I tested Maxima structures (https://maxima.sourceforge.io/docs/manual/maxima_singlepage.html#Structures) to achieve that and they work fine in my local Maxima setup.
Problem
The problem is that Maxima structures use a
@
field access operator, which seems not to be allowed in question variables field. This is the error I get: The characters @, $ and \ are not allowed in CAS input.Question
So I would like to ask if there is any way to make Maxima structures work in STACK, or is there any recommended workaround, supported datatype and/or syntax for the scenario where I have more than 10 values to be returned by a function?
Example
Minimum working (in my local Maxima setup) and non-working (in question variables of a Moodle STACK question) example is: