Non-Static Imports? #855
-
I'm trying to use pkl to solve a problem where I need to render similar data in different formats. The basic idea is that I have a common template and I need to emit it as xml or json depending on the context. This is how I've been thinking about it so far: class myObj {
local self = this
name: String
value: Int
jsonField: String?
xmlField: String?
function asJSON() = new {
name = self.name
value = self.value
specificField = self.jsonField ?? default
}
function asXML() = (xml.Element(self.name)) {
value = self.value
specificField = self.xmlField ?? default
}
} Then I have a few files that actually define the data import "objdef.pkl"
objects = Listing<myObj> {
new myObj {
name = "foo"
value = 10
jsonField = "foo-json"
xmlField = "foo-xml"
}
...
} bar.pkl import "objdef.pkl"
objects = Listing<myObj> {
new myObj {
name = "bar"
value = 20
jsonField = "bar-json"
xmlField = "bar-xml"
}
...
} I then have a common render module for each type data = import("foo,pkl") <- Want to be able to change this based on what file I'm rendering
output = {
for (_obj i objects) {
_obj.asJSON()
}
} I tried passing in the filepath as a prop and reading it in, but putting anything other than a string literal into an import expression seems to throw an error. Is there any way around this? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 10 replies
-
One way to work around this is to use a glob import, and then select the actual import from the resulting mapping. local allModules = import*("**.pkl")
local myModule = read("prop:my-module")
data = allModules[myModule] By the way, sidenote: zero-argument functions are kind of a smell in Pkl, because their result is un-cached (calling the same function multiple times will execute the function body multiple times; Pkl does not memoize function calls). Instead, use a - function asJSON() = new {
+ hidden fixed asJSON = new {
name = self.name
value = self.value
specificField = self.jsonField ?? default
} |
Beta Was this translation helpful? Give feedback.
-
So I think I might be able to accomplish this with a renderer converter. The one thing I would like to clarify is if I can define the renderer at a template level. For example, if I could do something like objects = Listing<myObj>
output {
files {
["out.json"] {
renderer = CustomJsonRenderer{}
}
["out.xml"] {
renderer = CustomXmlRenderere{}
}
}
} And then have amends "template.pkl"
import "objdef.pkl"
objects = Listing<myObj> {
new myObj {
name = "bar"
value = 20
jsonField = "bar-json"
xmlField = "bar-xml"
}
...
} Would evaluating foo.pkl produce an out.json and out.xml? Could I configure it to only produce one of those? |
Beta Was this translation helpful? Give feedback.
I've run into this before as well. You have some "aggregation" logic in a module that you want to ship as part of your package, but you don't want to copy it around into each repo that needs it. Here's how I've addressed that:
aggregate.pkl (in package)
aggregate.pkl (usage site)