- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
DSLs utilizing meta-class objects
Tue, 2009-01-27, 00:18
I'm interested in a convenient syntax for accessing metaclass information in Scala in a way similar to the way you can access it in the Smalltalk family of languges. Searching Google, I came across this blog:
http://www.codemonkeyism.com/archives/2008/11/27/native-type-support-in-...
I fully appreciate the theoretical reasons the syntax is what it is.
However, there's one really good reason to want this sort of thing in Scala.
I want to do a 100% type-safe version of JRuby's Glimmer internal DSL in Scala. You can understand Glimmer quickly by reading the examples at http://www.eclipse.org/glimmer/. For convenience, here's a Java and a Glimmer version of the same program:
[Java]
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = new Shell(display);
shell.setText("Example");
shell.setLayout(new FillLayout());
Composite composite = new Composite(shell, SWT.NONE);
composite.setLayout(new GridLayout());
Label label = new Label(composite, SWT.NONE);
label.setText("Hello World!");
shell.pack();
shell.open();
while (!display.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
[Glimmer.JRuby]
shell {
text "Example"
composite {
label { text "Hello World!" }
}
}.open
JRuby Glimmer isn't type-safe and can't be. Even aside from being wrtten in Ruby, it works by overriding method_missing in Object.
But you could easily use "pimp my library" to decorate java.lang.Class and get a 100% type-safe version of Glimmer in Scala. Something like:
[Glimmer.Scala]
classof[Shell] {
classof[Text] "Example"
classof[Composite] {
classof[Label] l => { l.setText "Hello World!" }
}
}.open
Unfortunately, the result isn't very intentional, and is not very DRY. But it's 100% type safe and can be compile-time type checked, and theoretically even code completed, etc. by IDEs. (I haven't checked to see if this is implemented yet in the current tooling.)
If I pimp java.lang.String, or scala.Symbol, I get something like:
[Glimmer.Scala2]
"shell" {
"text" "Example"
"composite" {
"label" l => { l.setText "Hello World!" }
}
}.open
or
[Glimmer.Scala3]
'shell {
'text "Example"
'composite {
'label l => { l.setText "Hello World!" }
}
}.open
which both lose compile-time type safety (they are equivalent to the JRuby version) and aren't quite as pretty as the JRuby version. The Symbol version isn't too bad to my eyes, but I really don't want to settle for losing type safety.
Moreover, since Shell, Text, Composite, and Label are SWT classes, not my own, I can't use hacks like the one proposed in the comments to the blog that was referenced at the beginning.
What I'd like is ideally nearly identical to the JRuby syntax, but taking advantage of Scala's compile-time type safety and IDE support. Something like:
[Glimmer.Scala.desired]
#Shell {
#Text "Example"
#Composite {
#Label l => { l.setText "Hello World!" }
}
}.open
where #SomeTypeName is compile-time equivalent to classOf[someTypeName], can be type-checked, etc.
Or some equally convenient syntax.
I'm not sure if I should use Manifest yet, nor if it would give what I need.
Does anyone have any thoughts on this? It seems like an interesting problem.
Regards,
David Orme | IB Architecture OneBench
External +1 (630) 685-4771 | david.x.orme@jpmchase.com
Team email: IBTech
Arch FC OneBench
Support email: IBTech
OneBench Support
Web: OneBench
JPMIM Forum: eclipsercp
This communication is for informational purposes only. It is not intended as an offer or solicitation for the purchase or sale of any financial instrument or as an official confirmation of any transaction. All market prices, data and other information are not warranted as to completeness or accuracy and are subject to change without notice. Any comments or statements made herein do not necessarily reflect those of JPMorgan Chase & Co., its subsidiaries and affiliates. This transmission may contain information that is privileged, confidential, legally privileged, and/or exempt from disclosure under applicable law. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the information contained herein (including any reliance thereon) is STRICTLY PROHIBITED. Although this transmission and any attachments are believed to be free of any virus or other defect that might affect any computer system into which it is received and opened, it is the responsibility of the recipient to ensure that it is virus free and no responsibility is accepted by JPMorgan Chase & Co., its subsidiaries and affiliates, as applicable, for any loss or damage arising in any way from its use. If you received this transmission in error, please immediately contact the sender and destroy the material in its entirety, whether in electronic or hard copy format. Thank you. Please refer to http://www.jpmorgan.com/pages/disclosures for disclosures relating to UK legal entities.
Tue, 2009-01-27, 03:57
#2
Re: DSLs utilizing meta-class objects
On Mon, Jan 26, 2009 at 3:14 PM, <david.x.orme@jpmchase.com> wrote:
I'm interested in a convenient syntax for accessing metaclass information in Scala in a way similar to the way you can access it in the Smalltalk family of languges. Searching Google, I came across this blog:
[Glimmer.Scala.desired]
#Shell {
#Text "Example"
#Composite {
#Label l => { l.setText "Hello World!" }
}
}.open
Can't get you all the way to Ruby, but I can get you close-ish.
import scala.reflect.Manifest
def $[T](implicit manifest : Manifest[T]) : Class[T] = manifest.erasure.asInstanceOf[Class[T]]
scala> $[String]
res3: Class[String] = class java.lang.String
scala> $[String].newInstance
res4: String =
Note that Manifest is experimental, unsupported, and likely to murder kittens.
I think it's possible to have type-safety and get the following DSL in Scala 2.7.3:
shell {
text( "Example")
composite {
label { text ("Hello World!") }
}
}.open
If you start with: You can delay the execution of f. In the shell method, you can set up a ThreadLocal context for executing subsequent commands. So, you'd have something like:
then:
Does this give you enough to start with or do you need the example fleshed out a little more?
Thanks,
David
On Mon, Jan 26, 2009 at 3:14 PM, <david.x.orme@jpmchase.com> wrote:
--
Lift, the simply functional web framework http://liftweb.net
Collaborative Task Management http://much4.us
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp