I somewhat have the vision of something like
var user_id = 20 var row = sql: FROM user WHERE id = nim: user_id
and the dev system understanding id is primary thus row is a Record.
https://github.com/launchbadge/sqlx -> search anonymous records.
With JS/TS you can just do query as Promise<record-type> and be done.
What would be the fastest closest way to get at least anonymous records in Nim?
Thus being able to write macro code which returns Records with fields which needn't be defined ?
Think you might be looking for tuples
let x = (20, "something")
echo x[0] # Echo 20
echo x[1] # Echo "something"
You don't want row = db.query('SELECT * FROM user ') echo row[3] // what is this ? you want echo row['lastname']
Because it's human writing code and you eventually do not want to depend or column order of db.
tuples can also be named
let x = (id: 20, lastname: "something")
echo x.id # Echo 20
echo x.lastname # Echo "something"
But like Araq said, if you know what the data is like ahead of time then using objects is likely better
- you will not have typos (cause it fits the type system)
- you can add additional simple checks like age < 100
- no need to worry about order such eg INSERT .. (id, name) VALUES (..)
How about querying ? SQL is very flexible. Eg windows, sums, selecting what you need only .. much less work for CPU.
So looks like all the benefits of ORM above could be simulated by a good type system.
Like if age should be < 100 you can have a proof that it exists or have the compile add an assertion at some point before passing the values.
What else is the point of ORM ? By defining the ORM you can get the scheme. Maybe even migrations.
So you can workaround that by defining the Scheme on type level.
So it somehow feels its just the best solution unless you start thinking on a different level like 1/0 and head or inserting age > 100 being potential runtime issues you can either switch off (eg rust style) or try to enforce stupid proofs (agda whatever) or you can have a smart code template which either adds runtime assertions (slow) or avoids them if you can proof or user says 'assume its true' ..
However thinking about proof sytsems is kinda above my head and maybe causes slower compilation times.
ANyway
foo = SELECT * FROM user echo foo['id']
Is there anything I missed about why ORM are so cool which would not be fixed by anonymous rows as in Rust ?
It's not only abuot ORM. It's about JSON from geo api (there was a lib in packages.json). If you could give JSON a subtype you could just return and be done. So no need to define and convert the data at all.
Not saying what I propose / think about is easy. Its more like if I follow the paths my brain can do it. So I want the compiler to do it but faster and help me. And this kinda always ends in trying to teach the machine takes 1000 times longer than I know it might work :-/
Eg Python & QT: You're supposed to use QuickQT and within that JS. Yeah, but I have nim/PYthon ? Why use JS ?
So the question I have is can the stacks be simplified by making the tools smarter. By having a concept qf quick QT written in some abstract whatever which can be turned into Python/C++ or with JS / Nim attributes ?
Same with OpenCV: You have C++ for speed (but sucks typing). So you use Python to make it better. But Pyright cannot cope with it and even img.imread/write fail typing. So you end up looking at the code and searching for .. what for ? the C++ ? how does it translate to Python ? Where is the .. -> takes much time.
Same embedding Python within Nim
x of type Pivar = pyinterp "np.array("foo")
Now because Nim cannot type Python it cannot type x. So you cannot pass it around easily and yes you can turn Py into wrappers etc what's done. But the question should you abuse a host language's type system or wrtite something new understanding both. Cause then if you want to Embed Python in C/Java/C#/Nim/.. it happens to be the same. And yes the Python integration seems to outperform the Java/Python/... versions for compatibility reason (you know it works) or whatever.
The subtyping is kinda just one step touching the question does dev env make sense allowing to type multiple languages and integrate them .
I mean even mercurial VCS or so mixes C / Python or such. So its eventually more common.
QT mixes ..
Other tools get rewritten like Gimp vs Krita or jackd was written in C and C++ cause community couldn't decide what's better.
Once you switch the view and say the typing system is more important than the language. Like introducing Rust checking for C .. (ownership.. maybe macro like preprocessor adding code) .. you have one project again. You just switch the dev env :/
Maybe I am dreaming to big and missing a lot. My sight is limited.
Nim is freaking cool. Just trying to understand whether I should work on getting what I miss or accept its not there. And if working on what's quickest path to get there.
And anonymous records is just one missing piece.
Once you understand that ORM doesn't solve everything I mean why are the tree selection libs (forgot teh name) so popular .. you even can use our own DSL doing joins automatically etc. Like if you need CD name and have tracks add it. Can ORM copmete ?
Like SELECT track_name, cd_name FROM tracks (LEFT JOIN cds on cd_id) could be added cause cd_name is not in tracks.
The missing rule is like if theer is an unknwown name look at n:1 relations and get data from there.
SELECT * FROM tracks WHERE cd_name = "foo" no join required anymore.
How could ORMs compete ?
So the fun thing is embedding SQL (just another language) and embedding Python (just another language) - what's the difference ?
If subtpes would exist they could be used to hint about what something is.
like pyvar = lambda/class of type/ 2, ...
if you have suptypes you can give the pyvar a type and know how you can ues it later whwen writing more Python code or passing it to Py code or.
Same about JSON within string.
Same about SQL within NIM.
row = ..
It's a string once queried will yield a hash with keys A,B,C.
Again subtype of a string.
Once you add biderictional typing you can do crazy shit like
row = FROM users WHERE id =10
echo row{"name"] // row will flow back and add itself to users
and now think about the cd case :-)
row = FROM tracks WHERE id = 20
echo row["cd_name"] // will add the join
And that's what's cool. Its about typing speed. Best code is the one you never write, right ?
time = money (review/write/test)
And that's gonna lead to fastest code by itself So nice for embedded systems with limited resources ?
And its how human thinks "Give me a beer" (you know I know where the freezer is so be like a humna and look in the kitchen .. you'll find it)
How to talk to a PC? Be a robot, move into ktichen, obet the freezer. Activate machine learning .. You get me . I am tried of that. I want to make my life easier. I want to say "I want beer". I want tracks. So if there is no pool add a parameter to the function that somewhere needs to be passed a pool when calling this function but don't show and ask me to write the code cause its' trivila cause at some point I will have a config passing the pool, okay ?
But coding is like dear robot: Let me tell you where the config (the kitchen is) - am I missing something ?
Does it at least make some sense to you ?
So ORMs to me feel like best solution within the wrong approach (objects). Even Haxe tried objcets wanted to inline them for ages .. but never did it cause "too complicated" So maybe the object is the problem ?
Not in all cases cause you need to fix stuff like in Dart/Flutter to understand what parts to replace / reload. But that's a diffenent story.
https://forum.nim-lang.org/t/2823 found this talking about tuples vs anonymous objects. So looks like while verbose they might get it done.
I wrote a lot code like SELECT a, (SELECT count from other WHERE id = m.id) as b FROM m as m.
Unsure how such would fit ORM. Looking at the examples which will take much more time to fully understand I only found some simple joins.
Its like querying all cds and counting the records (yes triggers and storing the sum could be used depending on use case).
I want a cdrom drive for my head..
I'm also dislike ORM.
Working with Nim is like 15% of all my work, it's not worth to learn a new Nim ORM API only to use it very little, like maybe 0.5% of the time, a little bit here and there. No matter how good benefits and safety it provides, it's just not worth time and effort.
So, I just use tiny Nim wrapper over SQL driver that allows you to write good old SQL and return plain Nim tuples.
db.exec sql"""insert into users (name, age) values ({"Jim"}, {30})"""
let users = db.filter(sql"select name, age from users order by name", tuple[name: string, age: int])
assert users == @[(name: "Jim", age: 30)]
assert db.get_value(sql"select count(*) from users where age = {30}", int) == 1
I worked on projects having like 10 joins. So matching with 10 objects is more painful than just using PHP's row["foo"] and be done. And we use alias.* a lot to be done. So matching with tuples means knowing the order. And I don't like things going wrong.
But I understood how tuples in Nim work. And assigning names is quite cool.
So while Nim does incredible work I still feel like some edges which would make programming for me more convenient are missing.
However named tuples and anonymous objects already exist so that code could be derived from macros easily.
Can you assign a tuple with first/last name to a tuple which only needs first?
Its something I use often in JS have a big config dictionary and pass more values than required and things just work.
So does Nim support something like tuple[first: string, ....] ?