@mdconn_uk has joined the channel
Does Racket support annotation mechanism (like Java or C# annotation)? Programmers can tag some annotation in program and read them via reflection.
No, there is not a built-in annotation mechanism. You can use some things to do similar stuff (like chaperone properties) but that would require manual work.
Thanks. I am thinking about how to implement DI container in Racket. For example, in Java or C#, annotation mechanism be used to implement DI container.
Is DI container useful in Racket?
People do not do a lot of DI in Racket.
Maybe that’s just preference, or what kinds of programs people build.
If you did do DI, I think the most likely ways would be 1. macros for defining code that took dependencies as arguments 2. using units 3. just using plain old functions
Using Scribble I got this: WARNING: no declared exporting libraries for definition in: function-name
What does that means?
How can I fix that?
@hectometrocuadrado probably you need a @defmodule
for the library you’re documenting
Something like @defmodule["file.rkt"]
?
One advantage of the DI container is that it can construct an object graph automatically instead of manually. This is very convenient to construct deeply nested components which depend on shared components. The unit system in Racket is a bit like Poorman injection.
Of course, I’m just thinking. At present I have not encountered such a complicated use case in Racket.
@defmodule[mixfix]
where mixfix
is your module
Btw, you might want to use raco pkg new
when you start a new project.
Has the module to be a path?
It will generate a Scribble file for you automatically
I created the scribble file in a different directory
I’m not sure what you mean by that. In my mixfix
package, users would write (require mixfix)
, so mixfix
is the path to my module.
It doesn’t matter where your Scribble file is.
I think I’m missing something
xd
Are you creating a package?
Nope. Just a bunch of rkt files for my own use.
I wanted to make a scribble manual to have a site where I could see how the functoons are.
Also, I wanted to practice with scribble
I guess a short answer is that, it’s kinda tricky to write a Scribble without installing the code that you are documenting as a package. It might be possible to do so, but I tried it before and failed.
So if you can install it as a package, that would simplify things
So, the easy way is documenting a package
Note that you don’t need to upload the package to the package server. You can just have a local package
I see. Thanks!
Although I might be misunderstanding, I think another way is:
- Parameters. As in
make-parameter
to define them, andparameterize
to set values for some dynamic extent.
By convention these are often named current-x
. current-output-port
, current-eval
, current-pretty-print-width
, etc.
In some sense this is like 1, but without the explicit extra function parameters.
@greg Dynamic scoping as dependency injection is a good idea. What surprised me is that there is very few people mention this idiom in programming community.
That might be because hardly anyone using Racket is doing so-called “enterprise” development? (That’s just my own impression/guess. Both about the Racket community. And also that DI is mainly used in “enterprise” development teams.)
Can one of you explain what people actually use DI for?
Not really. :slightly_smiling_face:
Probably @chansey97 can. I’ve only seen e.g. “Spring” used in a Java app. In my personal opinion it made the app deeply difficult to understand, from looking at the source code. (to be fair, you could say the same about “excessively macro-ized” code.)
But what problem were they trying to solve?
Even if spring/DI wasn’t a good solution
I have a little more mileage with so-called “12 Factor Apps” stuff in the web dev community. That mainly says, use env vars for config.
In the specific case I saw, the honest answer? The person was trying to use enterprise dev best practices, and everyone uses Spring (they felt), so they ought to, also.
I had similar questions as you and never got a satisfying answer.
But that’s just my one data point. I’m not trying to pee all over DI and say it’s never useful. I just don’t have a compelling example motivation to offer. Consider that a limitation of me, not DI.
In my own data point: The company was delivering a Java app that customers would install on their JVM app servers. They wanted the app to work with whatever the company used for database, messaging queues, and stuff like that. So it was an end-user configuration problem — that was the motivation.
I just don’t have a great pitch for why DI needed to be the solution.
To be fair, “that’s what enterprise customers expect” could be a 100% valid answer from a business POV.
So lots of things needed to be parameterized over some choices (like the database) and DI was the parameterization mechanism chosen.
Yes. Although in the case I saw, it wasn’t that many choices or that many things that needed to be parameterized. So it felt like overkill. Sort of “for the future”, “wishful planning ahead”.
In Java presumably the fact that you can’t just wrap your class in a lambda makes a difference
Yes. And even if you could do it that way, I don’t know if people would do it that way. I think there’s a “culture” difference. (You can chicken-and-egg which caused which, I suppose.)
A fair chunk of enterprise dev teams are kind of like visiting a Plimoth Plantation for 90s programming ideas. :slightly_smiling_face:
I think we should distinguish between DI and DI container. IMO, DI is a very commonly used design pattern, such as SML functor, Scala Cake pattern, or Racket unit, etc. In the DI scenario, we usually have a composition root, where we assemble the entire program.
The DI container just makes the assembly process easier.
Look this example: public class Service {
@Inject private Logger logger;
@Inject private Processor processor;
public void execute(String command) {
logger.log("executing " + command);
processor.process(command);
logger.log("executed " + command);
}
}
public class ProcessorImpl implements Processor {
@Inject private Logger logger;
public void process(Object o) {
logger.log("processing");
System.out.println("processing " + o + "...");
}
}
public class StandardModule extends AbstractModule {
@Override
protected void configure() {
bind(Processor.class).to(ProcessorImpl.class);
}
}
Injector injector = Guice.createInjector(new StandardModule());
Service service = injector.getInstance(Service.class);
Here Service
depends on Logger
and Processor
, a ProcessorImpl
depends on Logger
. Note that in this example in fact we created two loggers, but you can make logger
sharing as well.
Another complicated example is xText. I once used xText to create DSL in Java. They used DI container very frequently.
xText provides a compiler framework: You just fill code in the framework without knowing the entire architecture (which deep integrates with Eclipse IDE). So you need DI container to embed your own components.
I think I’d use parameters for that example in Racket
I agree.
DI container is just one application of annotation. The annotation mechanism seems powerful.
@popa.bogdanp has a package that let’s you do a kind of DI. I’ve not used it myself. https://docs.racket-lang.org/component/index.html
How can I make a Cartesian plane in scheme?
Could you please elaborate on what you’re trying to do? Do you want to plot a plane, do simple operations on points…?
I need to make a Cartesian plane and locate three points on this
{ (0,0), (1,0), (0, 1) }
I suppose to Racket-ify it: (define plane '((0 . 0) (0 . 1) (1 . 0)))
but I have to create the plane using canvas and then locate the points in this
What Racket uses parameters for is 100% the exact kind of thing that Java uses DI for
(for context: a lot of my day job involves DI-heavy Java)
There’s some differences in the approach but by and large they’re tackling the same problem: how to make certain parts of code dynamically configurable without making more work for callers (as adding function parameters or wrapping things in lambdas or units would do, those all affect callers heavily)
This is pure perception: it seems that Java objects via DI are a bit more complicated than the objects that get used through parameters. Not that more complicated things cannot be used with parameters.
There’s more that’s possible. But it’s not much more complex than what people sometimes do with parameters, where they set up multiple parameters whose current values are dependent on other parameters.