Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


darnocian last won the day on July 30 2021

darnocian had the most liked content!

Community Reputation

52 Excellent

1 Follower

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. I could assume that if the structure in question is more complex and the snippet we see is a sample, the use of withValue() would be part of a bigger set of stuff where the structure is set using method chaining... e.g. myrec.withValue('abc').withNum(123)... returning a pointer would be slightly more optimal as the delphi syntax should still allow the chaining with the '.', and the original structure would be referenced rather than copies being made if the result of each withXyz() was an actual record. if part of the question is about record vs class, well records in Delphi can be heap or stack based, where classes in Delphi are heap based. Assignment of a record in general, even in a method chain would result in copies, vs using a class would simply be passing a pointer around. As David mentioned however, it is a trivial scenario, just using a constructor would do. Using method chaining is sometimes an opinion piece, commonly used when using builder type patterns.
  2. darnocian

    App for docker

    Using fork() is the Linux way, but you don't have to worry about that in a docker environment. In Docker, you can simply rely on creating a simple console app. You then just rely on Docker Swarm or Kubernetes to be running on the host machine running the container as required. You simply need to provide a CMD or ENTRYPOINT in the Dockerfile referencing your command line application. I forgot you mentioned NGINX... So it depends how 'pure' you want to be... the 'pure' way is you have 2 containers: 1) nginx and 2) your app.... However, there is nothing stopping you from creating one container with NGINX and your application in it, but it is a container anti-pattern.
  3. My point was less about how many tools can consume it, but about having something that could actually be used at the end of the day. It could be anything, I just happen to like ANTLR more compared to lex/yacc and flex/bison, which I used to use in the old days. I'm not sure 100% of our objective - do we just want to have a text document (which is valuable in its own right), or do we want to have a grammar that can be consumed by a tool as well?
  4. I mentioned ANTLR before (https://www.antlr.org/). I'm just wondering if it would not be worth adopting a syntax like that that can be consumed and used in tooling instantly? e.g. https://github.com/fabriciocolombo/sonar-delphi/blob/master/src/main/antlr3/org/sonar/plugins/delphi/antlr/Delphi.g (a version 3 grammar) https://github.com/gotthardsen/Delphi-ANTRL4-Grammar/blob/master/Delphi.g4 Unfortunately, there isn't a 'runtime' for delphi on the latest version which is very mature, but using another language run time, like java, c#, etc, we could easily make a simple parser for delphi, until someone has time to work on one for delphi.
  5. Re BNF vs diagrams… as the format should be formal, it would allow for diagrams to be created easily using tools like graphgviz/dot and sexier/modern versions thereof. Re benefits of a grammar it can be used as a basis for all kinds of things… once a model is created using a parser generator or manually crafted, you can create things that might be out of scope of the actual compiler. E.g. static code analysis, documentation generation, dependency analysis (between units), search tools, creating diagrams, etc. Writing parsers can take a bit of effort, and to do it correctly, the grammar needs to be right. There is a lot of boiler plate (repeated patterns) when it comes to parsing, so over time people have written parser generation tools to assist with this process more optimally (and avoid bugs). Their input would normally be a bnf type config file. Examples of such tools is yacc (yet another compiler compiler), etc. I personally like the ANTLR framework. Unfortunately, the latest version 4 doesn’t have a Delphi runtime, but version 3 had one. it would be convenient to update this to fit in with one of those tools as it also makes it easier to instantly validate and create test cases on the grammar.
  6. darnocian

    Class properties

    The issue is that for anything 'virtual' to work, a VMT needs to be available. Virtual methods are accessible on instances of a class through the class VMT. The only way to accomplish something like what you wanted would be to introduce some helper variables/procedures in delphi/pascal to accomplish this - something that is overly verbose in pascal compared to python. I've given an example below. From a python perspective, you would maybe have something like: class X: @staticmethod def do_something(): return '42' print(X.do_something()) # 42 # illustrating overriding with a lambda X.do_something = lambda: '43' print(X.do_something()) # 43 In Delphi, you could do the following: type TMyGetter = function : string; TTest = class private class var FValueGetter: TMyGetter; class function GetValue:string; public class constructor Create; class property ValueGetter: TMyGetter read FValueGetter write FValueGetter; class property Value : string read GetValue; end; function MyGetValue:string; begin exit('42'); end; function MyGetValue2:string; begin exit('43'); end; class constructor TTest.Create; begin TTest.FValueGetter := MyGetValue; end; class function TTest.GetValue:string; begin if assigned(TTest.FValueGetter) then begin result := TTest.FValueGetter(); exit; end; raise Exception.Create('no getter set'); end; begin writeln(TTest.Value); // 42 TTest.ValueGetter := MyGetValue2; writeln(TTest.Value); // 43 end. In the above the the 'ValueGetter' sort of provides the same behaviour of the VMT in allowing it to be overridden. However, this is not a polymorphic property - so inheritance does not work... child classes would essentially modify the same static variable - but this principle applies the same way for my python example above as well I think.
  7. darnocian

    task thread priority?

    You may know this, or for other readers... As Lars mentioned, 'waiting' correctly is important. Ideally we should not be sleep()ing before querying a queue. Be mindful not to create 1 thread per request. If there are too many threads, then your scheduler ends up spending more time spinning, which doesn't help. Ideally, it should be utilising thread synchronisation primitives such as TEvent SetEvent() and WaitFor() when adding requests to the queue and waiting for events in the queue respectively. Further, we need to ensure we have some locking around whatever structure is used for the queue so that concurrent access doesn't destroy the structure's consistency. I'll write a little example later.
  8. darnocian

    task thread priority?

    I agree with Anders. using threads can be for different reasons though… backgrounding a blocking io bound tasks is different to backgrounding a cpu bound tasks. you may want to consider thread pools, as they ensure threads are recycled efficiently, and don’t normally exceed the number of cores. On multi core systems, I’ve normally used threadpools usually helps in recycling threads. The Delphi tasks library essentially captures this concept at a high level. there is also thread affinity that can be assigned using SetThreadAffinityMask, (on windows) but not sure how effective it is. The docs also recommend letting the system do the scheduling.
  9. darnocian

    Parallel processing question

    If you use TTask.Run(), it returns an ITask which resembles the 'future' pattern - the interface provides a getStatus() to check if it is complete or not, as well as other helper methods. From OmniThreadLibrary does seem like the Parallel.Async() could be extended to return something similar. However, using ITask / IFuture requires 'polling' type behavior compared to callbacks ... but I think what Dalija has just suggested is closer to what you probably want.
  10. darnocian

    Debug Configuration Manager for the Delphi IDE

    I've added installers for both Delphi 10.4.2 and Delphi 11.
  11. darnocian

    Debug Configuration Manager for the Delphi IDE

    I've uploaded an update for interested parties to try. http://downloads.sempare.ltd/SempareDebugConfigurationManager/
  12. darnocian

    How to iterate a TDictionary using RTTI and TValue

    I wish RTTI embedded the generic type parameters and the TRttiType included a way to extract them. I've often had to rely on specific use cases and knowing that I can extract the types easily from known method return types as highlighted by the enumerator / pair example above... I've had times where I needed some really generic stuff and had to split the TWhatever<T> as a string and resolve the generic parameter however it is defined recursively - which is a bit annoying.
  13. I'm not sure if think you might be thinking that 'uses' works similarly to the 'import' statement in Java. In Java, you normally import the type from the fully qualified package as you have attempted. 'System.Generics.Collections' is the unit, with many types/functions defined within. if you just needed to use it, you simply do 'uses System.Generics.Collections;' From the online help, if you see something like 'System.Generic.Collections.TArray' - it normally means that 'TArray' will be defined in 'System.Generics.Collections', so you 'uses' as illustrated above.
  14. Hi delphi fans, I'm never sure how much attention is paid to the 'upvotes' on issues in quality portal... Anyways, as there has been considerable effort in getting LSP working and improving that by the Emb team, one feature I'd really like to see the IDE provide is a 'rad' experience from the code editor with auto completion of anonymous method signatures, etc. https://quality.embarcadero.com/browse/RSP-27293 and https://quality.embarcadero.com/browse/RSP-24310 to summarize, as an example: type TMyfunction = reference to procedure (const AArg:string); begin var func : TMyfunction := /* press ctrl+space which completes the following: */ procedure (const AArg:string) begin end; end; There can be many different ways in which the context of the type can be known based on the cursor position when ctrl+space is pressed... If you have some time and think it would also be valuable, please upvote... I don't know if the moderators should consider a separate forum section for these types of requests. regards, Conrad
  15. Hi @Edwin Yip I'm not sure why '<% getdata("somevalue", sharedstate) %>'; would be difficult? from a user perspective (someone you may have creating a template), they may not have to know about the parameter types - they just need to know what parameters are available to be passed in... I do understand however that you may have non technical users from which you may want to hide this detail. At this stage, the only way is to use class variables - which is what would be available to the class functions. Maybe a potential enhancement would be to allow the template context to be param 1: class function dosomething(const ACtx:ITemplateContext;const AFirstArg:string):string; From a usage perspective, the template engine could expect the following usage: <% dosomething('hello') %> where it auto inserts the context. The reason I mention the context is because it allows you to store data in there as well which can generally be accessed by the template.