ModelicaSpecification
ModelicaSpecification copied to clipboard
MCP-0011: Custom Reductions
Modified by dietmarw on 28 Apr 2016 09:22 UTC This is a discussion regarding MCP-0011_CustomReductions:
- https://svn.modelica.org/projects/MCP/public/MCP-0011_CustomReductions/
It concerns calling user-defined functions in reduction expressions. Something like:
myProduct(2*c for c in complexArray)
Please comment on the proposal in this trac ticket.
Modified by dietmarw on 28 Apr 2016 09:21 UTC This is a discussion regarding MCPI-0011_CustomReductions:
- https://svn.modelica.org/projects/MCP/public/MCP-0011_CustomReductions/
It concerns calling user-defined functions in reduction expressions. Something like:
myProduct(2*c for c in complexArray)
Please comment on the proposal in this trac ticket.
Modified by dietmarw on 28 Apr 2016 09:20 UTC This is a discussion regarding MCPI-0011_CustomReductions:
- https://svn.modelica.org/projects/MCP/public/MCP-0010_ReductionFilter/
It concerns calling user-defined functions in reduction expressions. Something like:
myProduct(2*c for c in complexArray)
Please comment on the proposal in this trac ticket.
Reported by sjoelund.se on 23 May 2014 11:03 UTC This is a discussion regarding MCPI-0011_CustomReductions: https://svn.modelica.org/projects/MCP-Ideas/MAinternal/MCPI-0011_CustomReductions/MCPI-0011_CustomReduction.pdf
It concerns calling user-defined functions in reduction expressions. Something like:
myProduct(2*c for c in complexArray)
Please comment on the proposal in this trac ticket.
Migrated-From: https://trac.modelica.org/Modelica/ticket/1500
Comment by jmattsson on 23 May 2014 11:22 UTC As far as I can tell the only benefit is that you only need:
function myProduct
input Complex a;
input Complex b;
output Complex c;
algorithm
c := a * b;
end myProduct;
myProduct(2*c for c in complexArray);
instead of:
function myProduct
input Complex a[:];
output Complex c;
algorithm
c := Complex(0);
for b in a loop
c := c * b;
end for;
end myProduct;
myProduct({2*c for c in complexArray});
Or am I missing something?
Comment by jmattsson on 23 May 2014 11:33 UTC Of course, if you already happen to have myProduct:
function myProduct
input Complex a;
input Complex b;
output Complex c;
algorithm
// Calculate c
end myProduct;
Then the example becomes:
myProduct(2*c for c in complexArray);
instead of:
function myProductArr
input Complex a[:];
output Complex c;
algorithm
c := Complex(0);
for b in a loop
c := myProduct(c, b);
end for;
end myProductArr;
myProductArr({2*c for c in complexArray});
I still think that it is more complication than it is worth, given that we already have array comprehensions. Also, when writing it as a function that takes an array the user can decide on folding order and default values.
Note that requiring that there are default values for the inputs to the function precludes using Complex.'+' like you did in the example, since binary operator functions aren't allowed to have default values on the first two inputs.
Comment by sjoelund.se on 23 May 2014 11:48 UTC Replying to [comment:2 jmattsson]:
Note that requiring that there are default values for the inputs to the function precludes using
Complex.'+'like you did in the example, since binary operator functions aren't allowed to have default values on the first two inputs.
That was sort of the point of it. Anyway, Complex.'+' is allowed to contain a function that takes 1 input without binding and 1 with (just like Complex.'-'). It just won't be matched for binary addition.
Or am I missing something?
You also have multiple iterators to consider. You would need to run some weird cat command to flatten the array if you use those. If we sometime finally add lists to Modelica, one would generalise reductions to work on sequences anyway. Then writing functions that take arrays are not just inefficient: they need to cast a list to array, etc.
But yes, most of what you gain for Modelica is efficiency and no need to write the curly bracers. The implementation is really quite simple as well. If you implemented support for the other reductions, you should already have everything needed for user-defined reductions.
Like for sum(f(i) for i in range), you would probably store something like:
- startValue:
0.0 - expression:
f(i) - reduction:
[$acc =] $lhs + /*Real addition*/ $acc
The difference would be to store mySum(f(i) for i in range):
- startValue:
0.0 - expression:
f(i) - reduction:
[$acc =] mySum($lhs,$acc)
Comment by choeger on 23 May 2014 12:03 UTC I am unhappy with the syntax. We already have automatic lifting of functions to map-application (section 12.4.6), now we get automatic lifting of functions to a fold-application. This kind of type-dependent semantics is confusing (at least for the reader of the code), unnecessary complicated, probably unsound and complicates interpretation/translation.
Please consider to make map/fold an explicit syntax construct (cannot be implemented directly in Modelica due to a missing sound typesystem).
So instead of running something like
f({1,2,3,4}); // ---> {1,2,3,4} if f is e.g. id()
f({1,2,3,4}); // ---> 10 if f is e.g. sum()
consider (syntax totally made up)
f ** {1,2,3,4}; // ---> {1,2,3,4} if f is of Int -> Int, otherwise error
f /* {1,2,3,4}; // ---> 10 if f is of Int[] -> Int -> Int, otherwise error
That would:
- allow for better diagnostics
- simple translation
- enhanced readability (depending on the selected concrete syntax, of course)
Hiding the concrete semantics of an expression from the user just because we are to lazy to define a sane syntax is really bad style IMO.
Comment by sjoelund.se on 23 May 2014 12:22 UTC Replying to [comment:4 choeger]:
Please consider to make map/fold an explicit syntax construct (cannot be implemented directly in Modelica due to a missing sound typesystem).
It is explicit. 12.4.6 does not apply to reduction expressions as they are not function calls.
If it has for iterators, it is totally different from regular function calls. The most confusing part is the array constructor, which has both function and reduction syntax. But as array is special, this proposal changes nothing for those.
f({1,2,3,4}) would never try to fold the function call, vectorizing it as before.
Comment by jmattsson on 23 May 2014 12:42 UTC Replying to [comment:3 sjoelund.se]:
That was sort of the point of it.
The point of the example is that it would be illegal even with your suggestion? Now you are confusing me.
Replying to [comment:3 sjoelund.se]:
Anyway,
Complex.'+'is allowed to contain a function that takes 1 input without binding and 1 with (just likeComplex.'-'). It just won't be matched for binary addition.
No. There is a specific exception in the spec for '-', since it can be used either as a binary or as a unary operator.
You also have multiple iterators to consider. You would need to run some weird cat command to flatten the array if you use those.
And it would be yet another thing we would need to specify more or less arbitrarily.
But yes, most of what you gain for Modelica is efficiency and no need to write the curly bracers.
I'm afraid I can't see the efficiency gain - unless you are talking about the lists that we do not have.
The implementation is really quite simple as well.
Maybe, I haven't considered all the corner cases and weird combinations that users will inevitably use yet. I don't see any mention in your draft of effects of combinations with other language features, so I'm guessing you haven't either.
Like for sum(f(i) for i in range), you would probably store something like:
- startValue:
0.0- expression:
f(i)- reduction:
[$acc =] $lhs + /*Real addition*/ $accThe difference would be to store mySum(f(i) for i in range):
- startValue:
0.0- expression:
f(i)- reduction:
[$acc =] mySum($lhs,$acc)
This example assumes that the compiler is implemented like OMC is, so it doesn't really give anything for me. Sorry.
I'm not saying anything definite about if this should be done of not, just that I think that the motivation that you have presented so far is too weak. Multiple iterators is the strongest point, I think, but there I think it would be simpler and more powerful with an operator that flattens a multi dimensional array into a one dimensional one.
Comment by sjoelund.se on 23 May 2014 13:18 UTC Replying to [comment:6 jmattsson]:
Replying to [comment:3 sjoelund.se]:
That was sort of the point of it. The point of the example is that it would be illegal even with your suggestion? Now you are confusing me.
Just consider that Complex.'+' has a different definition or that the restriction on default arguments has not been introduced yet. For some definitions of folding, it would be valid for all non-empty inputs.
No. There is a specific exception in the spec for
'-', since it can be used either as a binary or as a unary operator.
(Slightly off-topic: + is also a unary operator. Anyway, you are allowed to store functions that cannot be matched as either binary or unary operator. The restriction is that they cannot be used in an overloaded binary operation. Not that the operator must not contain only functions that are allowed to be used in binary operations.)
But yes, most of what you gain for Modelica is efficiency and no need to write the curly bracers. I'm afraid I can't see the efficiency gain - unless you are talking about the lists that we do not have.
Take a function mySum(1:65536). You now need to create the entire array in order to call mySum. With folding, you do not need this array. Inlining the call would likely not work as it involves a loop, making a fold expression more efficient. By analysing an inlined call to the scalar mySum it is also possible to sometimes fold away parts of the input to the reduction. Just like you would remove the 1 in max{2*i for i in {1,time,x,3}}.
The implementation is really quite simple as well. Maybe, I haven't considered all the corner cases and weird combinations that users will inevitably use yet. I don't see any mention in your draft of effects of combinations with other language features, so I'm guessing you haven't either.
Reductions are really quite limited. There are no new implicit names or anything introduced from iterators that we did not have before. If you disallow operators and perhaps some builtin operators it is really quite simple. I did not read through all the builtins to see if anything would cause problems.
If one wants to be really thorough it would be possible to define scalar min(myReal) to have one default argument Constants.inf and not have any special rules for min/max/sum/product, making all reductions the same. That really would make me have to think things through though, as it would affect a lot of things.
Multiple iterators is the strongest point, I think, but there I think it would be simpler and more powerful with an operator that flattens a multi dimensional array into a one dimensional one.
I think it was a mistake to define {i+j for i in 1:3, j in 1:3} as being the same as {{i+j for i in 1:3} for j in 1:3} instead of being {2,4,6}. Because it makes it very hard to iterate over two arrays of the same size without introducing auxiliary variables.
If we want the other array constructor we again need new syntax for that.
Comment by jmattsson on 23 May 2014 13:43 UTC Replying to [comment:7 sjoelund.se]:
Just consider that Complex.'+' has a different definition or that the restriction on default arguments has not been introduced yet.
What? So your example assumes that there has been additional changes to the spec that just isn't mentioned in the the proposal? Why not just use a different example?
Slightly off-topic:
+is also a unary operator.
Not for operator records - the list in the beginning of ch 14 only lists it as a binary operator.
Anyway, you are allowed to store functions that cannot be matched as either binary or unary operator. The restriction is that they cannot be used in an overloaded binary operation. Not that the operator must not contain only functions that are allowed to be used in binary operations.
Then you interpret "A function is allowed for a binary operator if and only if" differently than I do. It seem weird to write "allowed" if you mean "considered when matching".
Take a function
mySum(1:65536). You now need to create the entire array in order to callmySum. With folding, you do not need this array. Inlining the call would likely not work as it involves a loop, making a fold expression more efficient.
OK. On the other hand you would get 65536 function calls instead of one. It depends on if you can inline functions with loops, but yes, in some cases it might be more efficient.
Comment by otter on 23 May 2014 16:26 UTC Let me quickly motivate the MCPI for reduction expressions:
In the MODRIO ITEA project there is a workpackage about requirements/properties modeling (defining requirements formally and checking them automatically for every simulation). There is a proposal from EDF how to describe requirements formally in a way that is close to what an engineer understands. Hilding has shown recently that some parts of the EDF proposal could be very nicely represented in Modelica with a few minor extensions (as the one that Martin S. proposes). Here are some examples from Hilding:
// Current Modelica
Integer a[:]= {0,0,1,0,0};
algorithm
all :=forall({x == 0 for x in a});
any :=exists({x == 0 for x in a});
n :=card({x == 0 for x in a});
// Simplified syntax
all :=forall(x == 0 for x in a);
any :=exists(x == 0 for x in a);
n :=card(x == 0 for x in a);
For a simple expression as above, this removal of the {} does not change so much. However, in the real applications the calls above are usually nested and combined with records:
record Pump
Boolean IsActive;
end Pump;
record Subsystem
Pump P[:];
end Subsystem;
function Test2
output Boolean b1, b2;
protected
Subsystem S[:] = {Subsystem(P={Pump(IsActive=false)}),
Subsystem(P={Pump(IsActive=true), Pump(IsActive=true)})};
algorithm
// Current Modelica
b1 := forall({exists({S[i].P[j].IsActive for j in 1:size(S[i].P, 1)})
for i in 1:size(S, 1)});
// Desired Modelica
b2 := forall(exists(p.IsActive for p in s.P) for s in S);
now, the code is much more readable with this small extension.
Martin S. pointed out that in principal such an extension is already available in OpenModelica and then it seemed natural to discuss whether the OpenModelica solution could be standardized.
Comment by jmattsson on 26 May 2014 09:23 UTC Replying to [comment:9 otter]:
now, the code is much more readable with this small extension.
This is kind of misleading, since the largest improvement is from allowing array expressions to refer to arrays of models. The difference from just this MCPI is:
// Without arrays of models as expressions:
b1 := forall({exists({S[i].P[j].IsActive for j in 1:size(S[i].P, 1)})
for i in 1:size(S, 1)});
// Becomes
b2 := forall(exists(S[i].P[j].IsActive for j in 1:size(S[i].P, 1))
for i in 1:size(S, 1)));
// Without arrays of models as expressions:
b1 := forall({exists({p.IsActive for p in s.P}) for s in S});
// Becomes
b2 := forall(exists(p.IsActive for p in s.P) for s in S);
So you see, the readability gain from this MCPI in this case is rather small. The large gain comes from the other changes.
(Edited due to missing the issue with arrays of models in my original answer.)
Comment by jmattsson on 26 May 2014 09:52 UTC Actually, after looking in the spec, I think that it might be simply a tool issue that prevents using the code below currently.
b1 := forall({exists({p.IsActive for p in s.P}) for s in S});
At least I didn't find anything that said that it was illegal in a quick search.
Comment by otter on 26 May 2014 10:14 UTC Replying to [comment:11 jmattsson]:
Actually, after looking in the spec, I think that it might be simply a tool issue that prevents using the code below currently.
b1 := forall({exists({p.IsActive for p in s.P}) for s in S});At least I didn't find anything that said that it was illegal in a quick search.
Yes, Hilding pointed out last week that it is not clear for him whether indexing arrays of records in this way might be allowed according to the spec. So, it might be sufficient to just add a clarification.
Furthermore, there are three options:
- Just clarify the indexing of records
- Allow the construct "expr for ..." as argument of every function call (in order to avoid the {..})
- Use the proposal from Martin (S.).
As I understand Martin (S.), his proposal has the advantage that no array needs to be actually build, whereas the {..} approach requires to first construct the array and then pass the array to the function. One might analyze whether a tool would be able to optimize the array construction away, if it is an inline function with a simple expression.
Comment by sjoelund.se on 26 May 2014 10:25 UTC Replying to [comment:12 otter]:
Just clarify the indexing of records
Sure. There is nothing in the spec disallowing it, so we allow it (although we do not handle the dot in the expression; that's just a bug though).
Allow the construct "expr for ..." as argument of every function call (in order to avoid the {..})
I would say not to add this as it would prevent my proposal at a later date. If you do add it, you will run into the concerns choeger had. for iterators currently are for reduction expressions, and a function that just takes an array input is not really a reduction (though it could be). Anyway, the {...} is a quite small thing.
Comment by jmattsson on 26 May 2014 12:44 UTC Replying to [comment:12 otter]:
Yes, Hilding pointed out last week that it is not clear for him whether indexing arrays of records in this way might be allowed according to the spec. So, it might be sufficient to just add a clarification.
Ah, yes. I read your example wrong and thought Subsystem was a model, not a record. If it is a record, then I'd definitely say that it is allowed to write {exists({p.IsActive for p in s.P}) for s in S} with current Modelica. If it was a model, then it would be less clear.
Comment by sjoelund.se on 18 Jun 2014 12:49 UTC There was some discussion today during the meeting, suggesting to instead introduce a new operator for folding, like:
fold(fn, arrayExp, startValue);
or:
fold(function fn(x=y), arrayExp, startValue)
This does not resolve Martin O.'s problems with defining a nice-looking text for properies modellers (although the extra { would not have to be displayed in Dymola equation view anyway). So maybe it would be okay to define e.g. exists as a function taking an array just like you can today...
I do not really like the idea of introducing yet another special operator in Modelica just for folding. The syntax is very much like functional programming, so maybe we should go all the way and add another MCPI for polymorphic functions? We would then get folding for free, and it does not need to be a special operator.
In MetaModelica we have a short-hand syntax for polymorphism (similar syntax to templates in C++):
function fold<T1,T2>
input FoldFunc func;
input T1 values[:];
input T2 startValue;
output T2 out := startValue;
protected
partial function FoldFunc
input T1 t1;
input T2 t2;
output T2 out;
end FoldFunc;
algorithm
for value in values loop
out := func(value,out);
end for;
end fold;
In MetaModelica <T1,T2> is just short for:
replaceable type T1 subtypeof Any;
replaceable type T2 subtypeof Any;
I would prefer to only have the short-hand. Or maybe some new keyword for a polymorphic type.
It is a more complicated feature to add than just fold. But we also have prototype implementations for this that have been running for a long time.
The difference is that we have tagged value in the runtime, so we can pass anything in the same space. An alternative would be to do the same things we do for partial function application: We create a new, temporary function. So for example.
function intAdd
input Integer x,y;
output Integer z := x+y;
end intAdd;
Integer i = fold(intAdd, integerArrayExp, 0);
would become:
Integer i = fold_intAdd(integerArrayExp, 0);
function fold_intAdd
input Integer values[:];
input Integer startValue;
output Integer out := startValue;
algorithm
for value in values loop
out := intAdd(value,out);
end for;
end fold_intAdd;
Does anyone think it would be interesting to pursue allowing polymorphic functions in Modelica instead of a special fold/reduce operator?
Comment by choeger on 18 Jun 2014 13:21 UTC Allowing for general-purpose polymorphic functions would be very interesting, indeed.
Unfortunately:
- Roughly 1ns after its introduction the aspect of inference will come up
- We already have overloading and subtyping in the language. Take a look at http://en.wikipedia.org/wiki/Lambda_cube to get an idea, where this leads in terms of sound type-systems
- Instead of an unsound type-system, we could as well have no type system
My conclusion: Unless other features get removed from the language, or someone does the work and design a sound Modelica type system (good luck ;)), adding random useful features will only complicate the language for no further benefit.
Hence, defining custom operators (heck, one could even embedd a well-defined and sound polymorphic array monad language) is the only viable way to go.
p.s.: No, I do not believe that MetaModelica is both a superset of Modelica and has sound polymorphism, so I do not consider it a "working prototype" ;).
Comment by sjoelund.se on 19 Jun 2014 10:37 UTC Replying to [comment:16 choeger]:
- We already have overloading and subtyping in the language
True. But overloading is irrelevant for the type inference I have in mind. Just because you have type inference and polymorphism, you do not have to introduce all the problems those features can cause in languages. C++ template functions have polymorphism, does type inference, has operator overloading and subtyping. Yet the following works fine:
#include <iostream>
template<typename T>
T plus(T t1, T t2)
{
return t1 + t2;
}
int main()
{
std::cout << plus(1,2) << "\n";
return 0;
}
In fact, C++ templates are more powerful than MetaModelica since it allows using operators like +, which are not defined for all possible types T. MetaModelica gives you a guarantee that all possible types T are allowed (and also that you only need to instantiate the function once; the cost is of course that you are not allowed to use any operations you like inside the function).
So... Should I write a new MCPI for polymorphic functions as an alternative to this proposal and discuss this there?
Comment by sjoelund.se on 19 Jun 2014 10:39 UTC Also, regarding overloading: keep in mind that we do not support function overloading in Modelica; only operator overloading.
Comment by choeger on 19 Jun 2014 10:55 UTC Replying to [comment:17 sjoelund.se]:
True. But overloading is irrelevant for the type inference I have in mind. Just because you have type inference and polymorphism, you do not have to introduce all the problems those features can cause in languages.
That is a rather bold statement and basically conflicts with many publications and established research. I don't say you are wrong with that, but if you aren't you should probably not write a MCP about it, but a handful of research papers ;). For instance, if you could implement proper polymorphic type inference, overloading and subtyping, you could merge Haskell and OCaml (and even get rid of row-polymorphism along the way).
C++ template functions have polymorphism
Nope. C++ templates are a (Turing-Complete!) Meta-Programming language. No polymorphism involved. Granted, you can implement some similar functionality, but you cannot assign a principle type to a C++ template function.
So... Should I write a new MCPI for polymorphic functions as an alternative to this proposal and discuss this there?
Assuming you want to formulate a type-system and proof its soundness I am all for it. Otherwise, I would just call it a waste of effort. Such things need to be done right.
Also, regarding overloading: keep in mind that we do not support function overloading in Modelica; only operator overloading.
There is no principle difference (except for fewer possibilities for the users).
Anyway, if you want to introduce polymorphism, you could start by writing the type of the following function:
function foo<T1,T2,T3>
input T1.SomeClass arg1;
input T2 arg2;
output T3 result = arg1.bar + arg2;
end foo;
Comment by sjoelund.se on 19 Jun 2014 11:19 UTC Replying to [comment:19 choeger]:
Anyway, if you want to introduce polymorphism, you could start by writing the type of the following function:
#!mo function foo<T1,T2,T3> input T1.SomeClass arg1; input T2 arg2; output T3 result = arg1.bar + arg2; end foo;
It is about writing the type of an instantiated function (which depends on the actual input arguments you give it). That is, you are interested in the result type of the function call (and by the time you know that, you know the instantiated type of the function).
T3 is not bound by the input for parameters, so I would personally have disallowed it. It seems C++ does as well:
#include <iostream>
template<typename T, typename T2>
T2 plus(T t1, T t2)
{
return t1+t2;
}
int main()
{
std::cout << plus(1,2) << "\n";
return 0;
}
a.cpp:11:16: error: no matching function for call to 'plus'
std::cout << plus(1,2) << "\n";
^~~~
a.cpp:4:4: note: candidate template ignored: couldn't infer template argument
'T2'
T2 plus(T t1, T t2)
^
1 error generated.
Comment by choeger on 19 Jun 2014 11:46 UTC Replying to [comment:20 sjoelund.se]:
It is about writing the type of an instantiated function (which depends on the actual input arguments you give it). That is, you are interested in the result type of the function call (and by the time you know that, you know the instantiated type of the function).
No. Polymorphism in a type system is about assigning a type to an expression (e.g. a function). You seem to insist on talking about Metaprogramming, which is a completely different story. What is an "instantiated" function anyway and how is it different from any other function?
T3 is not bound by the input for parameters, so I would personally have disallowed it. It seems C++ does as well:
In fact it is. Informally, it is "T5 when the operator '+' is overloaded with T4 -> T2 -> T5, for some type T4 when T1 is some type-record containing the type "SomeClass" which is a subtype of the record { bar : T4 }
And, again, C++ templates are a Metaprogramming facility. You can check this by compiling:
//fefes C++ example
template<class T> struct Loop { Loop<T*> operator->(); };
Loop<int> i = i->hooray;
When you run an interpreter anyway, you don't need a type system in the first place.
Comment by sjoelund.se on 19 Jun 2014 12:17 UTC Replying to [comment:21 choeger]:
No. Polymorphism in a type system is about assigning a type to an expression (e.g. a function). You seem to insist on talking about Metaprogramming, which is a completely different story. What is an "instantiated" function anyway and how is it different from any other function?
It is the difference between sum (what is its type signature in Modelica?), and sum(realArray) (has type signature Real[:]->Real).
In fact it is. Informally, it is "T5 when the operator '+' is overloaded with T4 -> T2 -> T5, for some type T4 when T1 is some type-record containing the type "SomeClass" which is a subtype of the record { bar : T4 }
No, T3 is not given by the inputs. You would evaluate the type parameters like C++ does:
function foo<T1,T2,T3>
input T1.SomeClass arg1;
input T2 arg2;
end foo;
T3 is nowhere to be found -> report an error. Only after the template typenames are inferred do you generate the entire type of the function (and can elaborate expressions in the function body, protected variables, etc).
On closer look, I think even if T3 was not part of the template arguments, T1.SomeClass would be allowed anyway. T1 would not be a type, but a package.
Class templates I will ignore. Only typename arguments to template functions.
Comment by choeger on 19 Jun 2014 14:06 UTC Replying to [comment:22 sjoelund.se]:
No, T3 is not given by the inputs. You would evaluate the type parameters like C++ does:
I can only repeat myself: C++ has no polymorphism. And the fact that you do not see how T1 and T2 determine T3 shows that you do not want to think about the difference.
Apparently, we will not reach any consensus here. Feel free to propose whatever metaprogramming interpreter you want to implement. But don't expect anything even remotely comparable to a polymorphic type system.
Comment by otter on 20 Jun 2014 08:39 UTC Replying to [comment:17 sjoelund.se]:
So... Should I write a new MCPI for polymorphic functions as an alternative to this proposal and discuss this there?
Yes, please do (separate MCPI). Please, take also into account that there was a long time ago a proposal by Hilding based on type inference and it would be helpful to take this into account in the discussion. There are two important use cases:
-
Implementing Modelica blocks where the type is not relevant. For example, Modelica.Blocks.Routing contains many blocks to combine and extract signals and these operations are always the same for any type. Currently, these blocks are only defined for Real signals, but it is tedious to just copy these blocks for all different types. As I recall, Hildings proposal is basically to use "Any" as a new type name and use type inference to infer the actual type. I assume function polymorphism would not help here.
-
Implementing built-in functions of Modelica Currently, there are several built-in functions of Modelica, like max, min, that are only built-in functions because a user cannot implement Modelica functions where different types of the input arguments are possible. If polymorphic functions could be implemented by a user, one would need less built-in functions.
Comment by sjoelund.se on 1 Jul 2014 14:10 UTC #1533 was created for polymorphic functions
Comment by dietmarw on 19 Dec 2014 07:01 UTC Ticket retargeted after milestone closed
Modified by otter on 18 Sep 2015 10:13 UTC
Modified by otter on 18 Sep 2015 10:22 UTC
Modified by otter on 18 Sep 2015 10:23 UTC
Comment by hansolsson on 25 Apr 2016 10:02 UTC Replying to [comment:9 otter]:
Let me quickly motivate the MCPI for reduction expressions:
In the MODRIO ITEA project there is a workpackage about requirements/properties modeling (defining requirements formally and checking them automatically for every simulation). There is a proposal from EDF how to describe requirements formally in a way that is close to what an engineer understands. Hilding has shown recently that some parts of the EDF proposal could be very nicely represented in Modelica with a few minor extensions (as the one that Martin S. proposes). Here are some examples from Hilding:
// Current Modelica Integer a[:]= {0,0,1,0,0}; algorithm all :=forall({x == 0 for x in a}); any :=exists({x == 0 for x in a}); n :=card({x == 0 for x in a}); // Simplified syntax all :=forall(x == 0 for x in a); any :=exists(x == 0 for x in a); n :=card(x == 0 for x in a);
As previously noted this simplification is different from this MCPI.
If we want to allow this simplification I believe we should consider that it is natural to generalize variants to functions with multiple inputs, so we would consider that another natural extension is:foo(i, i+1 for i in V) -> {foo(i,i+1) for i in V)} whereas this MODRIO-part assumes that foo(i for i in V) -> foo({i for i in V}). And the MCPI proposes mapping { foo(i for i in V) -> foo(V[end], ... foo(V[2], foo(V[1])))