Closed oojacoboo closed 4 years ago
Does this thing even work?
What's up with first
method generating a lambda if nothing is passed?
from($collection)->count()
gives me 1
.
from($collection)->first()
gives me an exception.
What gives?
Why aren't there braces around if
statements? That's not a good idea with the interpreter. Also, the first method shouldn't screw around with another loop and generating a lambda if null
is passed. It should just return the first element in the collection and get out of the way. It's wasting cycles!
Why aren't there any examples?
I'm bad at writing documentation. What documentation the library has is the adaptation of the documentation for original LINQ from MSDN. As examples there are completely alien to the PHP universe and adapting them would take an unfathomable amount fo time, I didn't do it. Some people did write introductory articles for YaLinqo though; you can find the links in the ReadMe file.
I appreciate the elegance of LINQ in filtering datasets, and PHP doesn't really have anything natively or other libs much for this.
What datasets are you filtering? I don't think it's mentioned in the docs, but if you're doing filtering of data from a database, you should use ORM directly for this. Mentioning this just in case, as I know some people have tried this.
I appreciate the elegance of LINQ in filtering datasets, and PHP doesn't really have anything natively or other libs much for this.
PHP has all sorts of native array functions for filtering. They suffer from inconsistency, but they do exist.
I'm trying to pass
from
a Doctrine Collection object.
Doctrine collection looks like a thin wrapper on top of PHP arrays with some weird ass expression building (which I have no idea who would ever use, but I digress). As the Doctrine collection exists for a somewhat similar purpose (providing nicer more consistent API on top of arrays), there's zero reason to wrap arrays in two layers of wrappers as it'll be very confusing what method of what library is called.
If you have to use a Doctrine collection for some reason (for example, they're produced by a third-party API you're using), then you can get raw arrays from these collections by calling toArray
on them, which will avoid the overhead of multiple wrappers and make some performance tricks inside the library possible.
Then call
first()
. However, I'm gettingSequence contains no matching elements.
. Why?
Do you reuse the results of from($collection)
? A sequence can only be iterated once. The code you show below suggests you don't reuse it, but I want to be sure that's not the issue.
Could you provide the full code? Your expectations and your code are correct, so maybe something important is missing outside of the provided code.
Why aren't there braces around
if
statements?
Where? What statements?
If you're reading the library code, you're doing it wrong. Every function has a lengthy documentation which is available both in source comments and on the web, generated from sources. Please use this documentation instead.
That's not a good idea with the interpreter.
I assure you it interprets these expressions just fine. And I don't think there's any reason for me to care about PSR-2 or any other random coding standards, as I've always been the one and only developer of the project. I'll consider changing my attitude if it ever changes.
Also, the first method shouldn't screw around with another loop and generating a lambda if
null
is passed.
All lambdas are cached, so no lambda is "generated". The "loop" only iterates once, so the overhead is minimal in this case, as this function isn't normally called in a loop. As YaLinqo sequence supports all sorts of iterators and not only arrays, the generic code has to be like this.
That being said, I did add some optimizations for specific cases and started working on major improvements in the usage of built-in array functions, but unfortunately this work hasn't been finished yet due to real life circumstances. I still hope to get back to it, especially now that PHP has proper array functions and the syntax is finally nice without any dirty hacks.
@Athari thank you for the excellent reply. Sorry if I came across as too critical. I was certainly quite frustrated when I submitted the issue.
Doctrine's Collection is the default output for relational collections within the Doctrine ORM. Doctrine is a very popular ORM for PHP. So, Doctrine collections are extremely common.
All said, it turns out there wasn't an issue all along. I was getting the same error/Exception after many attempts in an integration test. But, as it turns out, the issue was from another call to YaLinqo where the collection was empty and since the call stack looked so similar, I assumed it was the same one I was working with. firstOrDefault
did the trick here.
As always, a fresh look to the rescue. Thanks again for the input.
Regarding docs, it really would be super helpful to get, at least, a few rather simple examples added to the docs. Most of the articles I found in the README were performance related, no longer working, not in English, etc. And, Googling around isn't going to yield many results either. All in all, implementation details are quite lacking.
At the least, I'd suggest adding a section at the top of the project README requesting assistance with example documentation. IMO, there is no reason why a lib like this shouldn't have thousands of stars. From my knowledge, there really isn't another elegant way of handling dataset filtering in PHP.
Also, while on the example topic. As someone that doesn't come from C# or LINQ, the usage of a string argument like:
orderByDescending('$prod ==> $prod["quantity"]')
is very awkward. I think you should favor a proper lambda over the string syntax. I did notice that this seems to be a standard in C#, which makes sense that you chose to expose it in PHP as well, but I think that it should just be an option.
orderByDescending(fn ($prod) => $prod['quantity'])
At first sight of this lib, it's not clear that collections are even well supported. I realize that, if you dive into the lib, you'll see from
takes an Iterator
. I think this should be promoted much more though. It's much more common these days with modern PHP to use collection object wrappers over raw array datasets.
orderByDescending(fn ($prod) => $prod->getQuantity())
With object/collections and PHP's new lambda syntax, the DSL for this lib is looking quite nice. An update on the docs might really help push it's use. Also, as a suggestion, you might dig into what it is in a general sense. Many people in the PHP community are likely not familiar with LINQ at all. There is no reason why they must be to find or choose to use this lib.
Cheers!
@oojacoboo The arrow function syntax is a recent addition to PHP, it didn't exist back when the the library was created. As there's a massive difference in readability between $v ==> $v->foo
and function ($v) { return $v->foo; }
, these "string lambdas" were added as an ugly hack a compromise. This functionality is obsolete if you're using the newest versions of PHP.
IMO, there is no reason why a lib like this shouldn't have thousands of stars.
It all comes down to the way PHP is... PHP. As the article "PHP: a fractal of bad design" well put it:
I can’t even say what’s wrong with PHP, because— okay. Imagine you have uh, a toolbox. A set of tools. Looks okay, standard stuff in there.
You pull out a screwdriver, and you see it’s one of those weird tri-headed things. Okay, well, that’s not very useful to you, but you guess it comes in handy sometimes.
You pull out the hammer, but to your dismay, it has the claw part on both sides. Still serviceable though, I mean, you can hit nails with the middle of the head holding it sideways.
You pull out the pliers, but they don’t have those serrated surfaces; it’s flat and smooth. That’s less useful, but it still turns bolts well enough, so whatever.
And on you go. Everything in the box is kind of weird and quirky, but maybe not enough to make it completely worthless. And there’s no clear problem with the set as a whole; it still has all the tools.
Now imagine you meet millions of carpenters using this toolbox who tell you “well hey what’s the problem with these tools? They’re all I’ve ever used and they work fine!” And the carpenters show you the houses they’ve built, where every room is a pentagon and the roof is upside-down. And you knock on the front door and it just collapses inwards and they all yell at you for breaking their door.
That’s what’s wrong with PHP.
This library is in a weird spot of making a small part of writing code easier, but not looking useful enough for someone used to writing chains of calls to weird inconsistent native array functions and maybe even loops to work with arrays, and not being massive enough to attract attention of serious programmers. You aren't using Doctrine collections because they're good (frankly, they aren't), but because they're part of a big framework. And in most cases, they're kinda enough. Also, writing complex LINQ queries isn't easy and requires some practice, so it's hard to find an excuse to learn it even if eventually it makes your life easier.
LINQ in C# is a cornerstone since it was introduced, but here in PHP the library is limited to only working with collections, unlike C# where it works on everything from XML and JSON to any database. There were several attempts to do LINQ to database, but all of them ultimately failed. Last time I checked, the only actually functional PHP LINQ for DB was a "demo" — partly due to PHP limitations, partly due to overwhelming complexity of the task.
Good point on changing arrays to objects in the ReadMe — casting to object is probably worth making the rest of the code so much nicer.
Why aren't there any examples? I get that this is a port of LINQ and many people may be familiar, but I am not and would like to use this lib. I appreciate the elegance of LINQ in filtering datasets, and PHP doesn't really have anything natively or other libs much for this.
I'm trying to pass
from
a Doctrine Collection object. Then callfirst()
. However, I'm gettingSequence contains no matching elements.
. Why?