In JS, inner functions could be quite handy to simplify the code, something like:
function complexStuff() {
function step1() { ... }
function step2() { ... }
step1()
step2()
}
Is it possible to use something similar in Ruby, or are there different approaches?
I don't like private methods because private methods are available to the whole class, and in this case, I want to limit the scope of the inner function even more--to just one method.
A Ruby lambda is similar to an anonymous js function:
step1 = lambda {puts "I am a lambda!"}
step1.call "optional args", ...
Some shorthand:
f = -> {puts "Shorthand lambda"}
f.()
More info (including shorthand notation!!) here
Related
I am learning reactive. In an MVC project I have a service method (and the controller has the same signature) like this:
#Override
public Map<Long, Question> getQuestions() {
List<Question> questions = questionRepo.findAllByType(Type.A);
return questions.stream()
.collect(Collectors.toMap(q -> q.getId(), q -> q));
}
Resulting in something similar to this:
{
1: {id: 1, ...}
2: {id: 2, ...}
...
}
Now, switching to reactive and kotlin coroutines. What is the proper way to implement this in a reactive way?
This is the signature of the repository:
interface QuestionRepository : CoroutineCrudRepository<Question, Long> {
#Query("select * from Question q where type = :type")
fun findAllByType(type: Type): Flow<Question>
}
Approaches
From what I think so far using Mono<Map<Long,Question>> seems to make no sense as it would require to block for building the inner map.
Flow<Map<Long,Question>> Does not make sense either, because we do not populate multiple maps.
So my best approach for now is not using a Map...
override fun getQuestions(): Flow<Question> {
return questionRepo.findAllByType(Type.A)
}
...but this would require to change the frontend code (it now needs to convert the list to a map).
I also think of
override fun getQuestions(): Flow<Pair<Long?,Question>> {
return questionRepo.findAllByType(Type.A).map { it.id to it }
}
but this would require the frontend to change as well, because the output would look like
[{"first":1,"second":{"id":1, ...}]
Are there other, better approaches? How would you implement it?
UPDATE
added repository.
Assuming the Flow emits elements one at a time that you want to put into a single Map in the client code, then you can collect them into a MutableMap like this and return it.
suspend fun getQuestions(): Map<Long, Question> {
val map = mutableMapOf<Long, Question>()
questionRepo.findAllByType(Type.A)
.collect {
map[it.id] = it
}
return map
}
If your downstream client code is not expecting a suspend function, I guess you need to wrap this in runBlocking, and presumably the downstream code is already handling the fact that this is a long-running function call.
override fun getQuestions(): Map<Long, Question> = runBlocking {
val map = mutableMapOf<Long, Question>()
questionRepo.findAllByType(Type.A)
.collect {
map[it.id] = it
}
map
}
I am migrating my prototype from a listener to a visitor pattern. In the prototype, I have a grammar fragment like this:
thingList: thing+ ;
thing
: A aSpec # aRule
| B bSpec # bRule
;
Moving to a visitor pattern, I am not sure how I write visitThingList. Every visitor returns a specializes subclass of "Node", and I would love somehow when to be able to write something like this, say a "thingList" cares about the first thing in the list some how ...
visitThingList(cx: ThingListContext): ast.ThingList {
...
const firstThing = super.visit(cx.thing(0));
The problem with this is in typing. Each visit returns a specialized type which is a subclass of ast.Node. Because I am using super.visit, the return value will be the base class
of my node tree. However, I know because I am looking at the grammar
and because I wrote both vistARule and visitBRule that the result of the visit will be of type ast.Thing.
So we make visitThingList express it's expectation with cast ...
visitThingList(cx: ThingListContext): ast.ThingList {
const firstThing = super.visit(cx.thing(0));
if (!firstThing instanceof ast.Thing) {
throw "no matching visitor for thing";
}
// firstThing is now known to be of type ast.Thing
...
In much of my translator, type problems with ast Nodes are a compile time issue, I fix them in my editor. In this case, I am producing a more fragile walk, which will only reveal the fragility at runtime and then only with certain inputs.
I think I could change my grammar, to make it possible to encode the
type expectations of vistThingList() by creating a vistThing() entry point
thingList: thing+ ;
thing: aRule | bRule;
aRule: A aSpec;
bRule: B bSpec;
With vistThing() typed to match the expectation:
visitThing(cx: ThingContext): ast.Thing { }
visitThingList(cx: ThingListContext) {
const firstThing: ast.Thing = this.visitThing(cx.thing(0));
Now visitThingList can call this.visitThing() and the type enforcement of making sure all rules that a thing matches return ast.Thing belongs to visitThing(). If I do create a new rule for thing, the compiler will force me to change the return type of visitThing() and if I make it return something which is NOT a thing, visitThingList() will show type errors.
This also seems wrong though, because I don't feel like I should have to change my grammar in order to visit it.
I am new to ANTLR and wondering if there is a better pattern or approach to this.
When I was using the listener pattern, I wrote something like:
enterThing(cx: ThingContext) { }
enterARule(cx : ARuleContext) { }
enterBRule(cx : BRuleContext) { }
Not quite: for a labeled rule like thing, the listener will not contain enterThing(...) and exitThing(...) methods. Only the enter... and exit... methods for the labels aSpec and bSpec will be created.
How would I write the visitor walk without changing the grammar?
I don't understand why you need to change the grammar. When you keep the grammar like you mentioned:
thingList: thing+ ;
thing
: A aSpec # aRule
| B bSpec # bRule
;
then the following visitor could be used (again, there is no visitThing(...) method!):
public class TestVisitor extends TBaseVisitor<Object> {
#Override
public Object visitThingList(TParser.ThingListContext ctx) {
...
}
#Override
public Object visitARule(TParser.ARuleContext ctx) {
...
}
#Override
public Object visitBRule(TParser.BRuleContext ctx) {
...
}
#Override
public Object visitASpec(TParser.ASpecContext ctx) {
...
}
#Override
public Object visitBSpec(TParser.BSpecContext ctx) {
...
}
}
EDIT
I do not know how, as i iterate over that, to call the correct visitor for each element
You don't need to know. You can simply call the visitor's (super) visit(...) method and the correct method will be invoked:
class TestVisitor extends TBaseVisitor<Object> {
#Override
public Object visitThingList(TParser.ThingListContext ctx) {
for (TParser.ThingContext child : ctx.thing()) {
super.visit(child);
}
return null;
}
...
}
And you don't even need to implement all methods. The ones you don't implement, will have a default visitChildren(ctx) in them, causing (as the name suggests) all child nodes under them being traversed.
In your case, the following visitor will already cause the visitASpec and visitBSpec being invoked:
class TestVisitor extends TBaseVisitor<Object> {
#Override
public Object visitASpec(TParser.ASpecContext ctx) {
System.out.println("visitASpec");
return null;
}
#Override
public Object visitBSpec(TParser.BSpecContext ctx) {
System.out.println("visitBSpec");
return null;
}
}
You can test this (in Java) like this:
String source = "... your input here ...";
TLexer lexer = new TLexer(CharStreams.fromString(source));
TParser parser = new TParser(new CommonTokenStream(lexer));
TestVisitor visitor = new TestVisitor();
visitor.visit(parser.thingList());
I like to store simple functions which can be expressed as one line lambda in private and final instance variables when they are used several times by other methods in the class.
Also I do that sometimes with functions which are not used several times to make a big method shorter and to have a stronger expression of the functionality used in the method.
public class SomeClass {
private final UnaryOperator<Something> someMethod = s -> doSomething;
public void someMethod2(Something s) {
//some code which goes over several lines and uses someMethod variable
}
public void someMethod3(Something s) {
//some code which goes over several lines and uses someMethod variable
}
}
Another example in which the input is preapred for diffrent services in a helper class. The two same characters have to be replaced in the String for both services. The function for this is not stored a normal static method, it is stored in a static field which implements the UnaryOperator.
public class PrepareServicesInputHelper {
private static final UnaryOperator<String> replaceSignsForAllServices = s -> s.replace('+', '-')
.replace('/', '*');
public static String transformStringForServiceOne(String s) {
return "Additional transformation information for service one" + removeUnwantedSigns.apply(s);
}
public static String transformStringForServiceTwo(String s) {
return "Additional transformation information for service two:" + removeUnwantedSigns.apply(s);
}
}
It looks better and is clearer this way for me.
Is this a good idea or are there some disadvantages which are practical or hurt some paradigms of clean code with this approach and the functionality should be stored traditional in instance methods?
In your example I cannot see any added value of your solution compared with just plain call of a method. Your solution is an overkill.
Abraham Maslow (https://en.wikipedia.org/wiki/Law_of_the_instrument):
I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.
The proper use case for lambdas is where you need to pass a function, or to select a function from multiple possible ones. Here your use case is just a plain re-use of a method, obfuscated by a lambda.
Study the behavioural design patterns here or here, such as Command, Observer/Listener, Strategy, Visitor. Here you need to pass a behaviour and that's what lambdas are designed for in Java.
Another quick "rule of thumb" may be this:
Do you need to call a method right now? So call a method.
Do you need to pass a method to be called from inside another method, later, maybe called not once but multiple times, maybe even not at all (if the method in control decides to)? So pass a lambda.
For your use case the common way is this. It looks even better and is even clearer this way :)
public class PrepareServicesInputHelper {
private static String replaceSignsForAllServices(final String s) {
return s.replace('+', '-').replace('/', '*');
}
public static String transformStringForServiceOne(final String s) {
return "Additional transformation information for service one" + removeUnwantedSigns(s);
}
public static String transformStringForServiceTwo(final String s) {
return "Additional transformation information for service two:" + removeUnwantedSigns(s);
}
}
A good example, similar to the yours but not the same, is this. You have a logger which writes to a file, but only if you turn on the logging. Evaluating the log text might be costly and we want to calculate it only lazily, only when needed.
public class Logger {
private boolean logIsOn;
// constructor, setters, getters etc.
public log(final String message) {
if (logIsOn) {
printToFile(message);
}
}
public lazyLog(final Supplier<String> message) {
if (logIsOn) {
printToFile(message.get());
}
}
}
// Here the expensive calculation occurs always, even if the logging is off
logger.log("Operation x performed on " +
person.getFirstName() + " " +
person.getLastName() +
" with the result " + result.calculate());
// Here the expensive calculation occurs only when the logging is on
logger.lazyLog(() -> "Operation x performed on " +
person.getFirstName() + " " +
person.getLastName() +
" with the result " + result.calculate());
I wonder if can i convert any lambda expression into method reference
for example:
if there is a lambda that execute method with 2 parameters (one of them is from outside)
.map( t -> removeFilesIfNessasary( externalObj, t ) )
can this also converted into method reference?
thanks
Well you could create a class, sort of like this:
class Remover {
private final Object externalObj;
public Remover(Object externalObj){
this.externalObj = externalObj;
}
public removeIf(int t){
removeFilesIfNessasary( externalObj, t);
}
}
and then declare this and use it:
Remover remover = new Remover(externalObj);
.map(remover::remove);
But seriously, this looks really weird; there has to be a compelling reason for you to do this (I can't think of one).
I'm trying to write a C# repository with atomic contexts and feel like this is a perfect situation for the usage of a closure, but I can't quite grok how to get it done in C#. I have this as a main method in my repository:
...
protected virtual IQueryable<T> AsQueryable()
{
return _context.ObjectSet<T>().AsQueryable();
}
...
Meanwhile, I have derived classes with methods like:
...
public IQueryable<Arc> ByRun(Run run)
{
IQueryable<Arc> query = from o in AsQueryable()
from r in o.Runs
where r.Id == run.Id
select o;
return query;
}
...
and I want to change my query method to return IEnumerable and to dispose quickly of the context, so want to use (something like) this:
...
protected virtual IEnumerable<T> AsEnumerable()
{
using (IContextUnitOfWork unitOfWork = new EFUnitOfWork())
{
return unitOfWork.ObjectSet<T>().ToList();
}
}
...
The problem, of course, is that once the context is disposed, calling LINQ on the resulting IEnumerable set will fail. Thus, my thought is that I should bundle up the ByRun() method and pass it to AsEnumerable() to be used as a closure.
While not my original language style, I learned closures in Ruby. There, what I'm trying to do would look something like this mixed up pseudo-code:
ByRun(Run run)
AsEnumerable do |query|
from o in query
from r in o.Runs
where r.Id == run.Id
select o;
end
end
where the AsEnumerable method would open the context, perform the operation that was passed in, and return. I'm sure I can do this once I understand the syntax, so I'm looking for my desired AsEnumerable and ByRun methods implemented this way.
If I understand the question correctly, you want to have a wrapper on any query to ensure that AsEnumerable is called at the end and context is disposed just after the query?
If so (assuming that your base class is generic with T parameter), try this:
protected virtual IEnumerable<T> AsEnumerable(Func<ObjectSet<T>, IQueryable<T>> query)
{
using (IContextUnitOfWork unitOfWork = new EFUnitOfWork())
{
return query(unitOfWork.ObjectSet<T>()).AsEnumerable();
}
}
And usage example:
public IEnumerable<Arc> ByRun(Run run)
{
return AsEnumerable(query => from o in query
from r in o.Runs
where r.Id == run.Id
select o);
}
The parameter of AsEnumerable here is the lambda expression containing any delegate that takes ObjectSet<T> as the only parameter and returns IQueryable<T>. So it's logically equivalent to have the following code in the derived class:
public IEnumerable<Arc> ByRun(Run run)
{
using (IContextUnitOfWork unitOfWork = new EFUnitOfWork())
{
return (from o in unitOfWork.ObjectSet<T>()
from r in o.Runs
where r.Id == run.Id
select o).AsEnumerable();
}
}