Content deleted Content added
MarcGarver (talk | contribs) →History: uncited despite having quotations, and appears to be OR or POV |
small clarification |
||
(22 intermediate revisions by 9 users not shown) | |||
Line 1:
{{Short description|Data abstraction problem in programming languages}}
The '''expression problem''' is a challenging problem in [[programming language]]s that concerns the extensibility and modularity of statically typed data abstractions. The goal is to define a data abstraction that is extensible both in its representations and its behaviors, where one can add new representations and new behaviors to the data abstraction, without recompiling existing code, and while retaining static type safety (e.g., no casts).
== History ==
Line 41:
applied Reynold's idea in the context of Objects and Abstract Data Types, which had both grown extensively. Cook identified the matrix of representations and behaviors that are implicit in a Data Abstraction, and discussed how ADTs are based on the behavioral axis, while Objects are based on the representation axis. He provides extensive discussion of work on ADTs and Objects that are relevant to the problem. He also reviewed implementations in both styles, discussed extensibility in both directions, and also identified the importance of static typing.
Most importantly, he discussed situations in which there was more flexibility than
Reynolds considered, including internalization and optimization of methods.
At ECOOP '98, [[Shriram Krishnamurthi]] et al.<ref name="Synth">
Line 47:
| title=Synthesizing Object-Oriented and Functional Design to Promote Re-Use
| url=https://cs.brown.edu/~sk/Publications/Papers/Published/kff-synth-fp-oo/
}}</ref> presented a design pattern solution to the problem of simultaneously extending an expression-oriented programming language and its tool-set. They dubbed it the "expressivity problem" because they thought programming language designers could use the problem to demonstrate the expressive power of their creations. For PLT, the problem had shown up in the construction of DrScheme, now [[
{{cite journal
| title= Modular object-oriented programming with units and mixins
| date=1999 | doi=10.1145/291251.289432 | last1=Findler | first1=Robert Bruce | last2=Flatt | first2=Matthew | journal=ACM
▲| last1=Findler | first1=Robert Bruce | last2=Flatt | first2=Matthew | journal=ACM Sigplan Notices | volume=34 | pages=94–104 }}</ref> via a rediscovery of [[mixin]]s.<ref name="Mixins">{{cite thesis |type= PhD
| last= Cook | first= William | date= 1989
| title= A Denotational Semantics of Inheritance | publisher= Brown University
Line 76 ⟶ 75:
Some follow-up work used the expression problem to showcase the power of programming language designs.<ref name="Scala0">
{{cite
|
| first1=Matthias | last1=Zenger
| first2=Martin | last2=Odersky
| title=Proceedings of the sixth ACM SIGPLAN international conference on Functional programming | pages=241–252
| citeseerx=10.1.1.28.6778
| year=2001
| doi=10.1145/507635.507665
| isbn=1-58113-415-0 }}</ref><ref name="Scala">
{{cite
|
| chapter-url=https://homepages.inf.ed.ac.uk/wadler/fool/program/final/10/10_Paper.pdf
| first1=Matthias | last1=Zenger
| first2=Martin | last2=Odersky
| title=FOOL 2005
| publisher=ACM
| citeseerx=10.1.1.107.4449
| year=2005
Line 99 ⟶ 100:
There are various solutions to the expression problem. Each solution varies in the amount of code a user must write to implement them, and the language features they require.
* [[Multiple dispatch]]<ref name="Chambers & Leavens, Multi-Methods">{{cite journal|last1=Chambers|first1=Craig|last2=Leavens|first2=Gary T.|title=Type Checking and Modules for Multi-Methods|journal= ACM
*
* [[Coproduct]]s of [[functor]]s<ref>{{cite journal
|author = Wouter Swierstra
Line 115 ⟶ 116:
|doi-access = free
}}</ref>
* [[Type class]]es<ref name="Wehr & Thiemann, JavaGI Type Classes">{{cite journal|last1=Wehr|first1=Stefan|last2=Thiemann|first2=Peter|title= JavaGI: The Interaction of Type Classes with Interfaces and Inheritance|journal= ACM
* Tagless-final<ref name="Carette et al.,
Finally tagless, partially evaluated: Tagless staged interpreters for simpler typed languages">{{cite journal|last1=Carette|first1=Jacques|last2=Kiselyov|first2=Oleg|last3=Chung-chieh|first3=Shan|title=Finally Tagless, Partially Evaluated: Tagless Staged Interpreters for Simpler Typed Languages|journal=J. Funct. Program.|date=2009|volume=19 |issue=5 |pages=509–543 |doi=10.1017/S0956796809007205 |s2cid=6054319 |url=http://okmij.org/ftp/tagless-final/JFP.pdf}}</ref> / Object algebras<ref name="Oliveira & Cook, Object Algebras">{{cite journal|last1=Oliveira|first1=Bruno C. d. S.|last2=Cook|first2=William R.|title=Extensibility for the Masses: Practical Extensibility with Object Algebras|journal=Ecoop '12|date=2012|url=http://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf}}</ref>
* Polymorphic Variants<ref name="Code Reuse Through Polymorphic Variants">{{cite
== Example ==
Line 126 ⟶ 127:
<syntaxhighlight lang="c#" line="1">
{
int Eval();
}
{
{
N = n;
}
public int Eval()
Line 146 ⟶ 147:
}
{
{
Left = left;
Line 154 ⟶ 155:
}
public int Eval()
Line 164 ⟶ 165:
}
{
}
</syntaxhighlight>
Line 174 ⟶ 175:
<syntaxhighlight lang="c#" line="1">
{
{
Left = left;
Line 182 ⟶ 183:
}
public int Eval()
Line 193 ⟶ 194:
</syntaxhighlight>
However, if we wish to add a new function over the type (a new method in C# terminology), for example to pretty print an expression, we have to change the {{code|IEvalExp}} interface and then modify all the classes that implement the interface. Another possibility is to create a new interface that extends the {{code|IEvalExp}} interface and then create sub-types for {{code|Lit}}, {{code|Add}} and {{code|Mult}} classes, but the expression returned in {{code|ExampleOne.AddOneAndTwo()}} has already been compiled so we will not be able to use the new function over the old type. The problem is reversed in functional programming languages like [[F Sharp (programming language)|F#]] where it is easy to add a function over a given type, but extending or adding types is difficult.
=== Problem
Let us redesign the original library with extensibility in mind using the ideas from the paper ''Extensibility for the Masses.''<ref name="Oliveira & Cook, Object Algebras" />
<syntaxhighlight lang="c#" line="1">
{
T Lit(int n);
Line 205 ⟶ 206:
}
{
public IEvalExp Lit(int n)
Line 218 ⟶ 219:
}
{
public static T AddOneToTwo(ExpAlgebra<T> ae) => ae.Add(ae.Lit(1), ae.Lit(2));
Line 227 ⟶ 228:
<syntaxhighlight lang="c#" line="1">
{
string Print();
}
{
{
N = n;
}
public string Print()
Line 247 ⟶ 248:
}
{
{
Left = left;
Line 255 ⟶ 256:
}
public string Print()
Line 265 ⟶ 266:
}
{
public IPrintExp Add(IPrintExp left, IPrintExp right)
Line 278 ⟶ 279:
}
{
}
</syntaxhighlight>
|