baethon / phln Goto Github PK
View Code? Open in Web Editor NEWSet of small utility functions. Inspired by Ramda 💜
Home Page: https://baethon.github.io/phln/
License: MIT License
Set of small utility functions. Inspired by Ramda 💜
Home Page: https://baethon.github.io/phln/
License: MIT License
Generated phln\Phln
class is getting bigger.
A thing to consider - replace static methods with __callStatic()
.
Extra bonus - append methods API in class PHPDoc block
Add test()
function which validates string with given regex.
There's little confusion with those functions:
match()
matchAll()
replace()
replaceAll()
split()
splitRegexp()
Some of them require regexp, some of them require plain string. In fact all those functions could be simplified to only three:
match()
replace()
split()
This can be done by introducting RegExp
object which represents.. RegExp. It should be simply a ValueObject initialized in same fashion as in JS: new RegExp($regex, $modifiers)
.
It should be able to handle global (g
) modifier. For convenience it should be possible to create RegExp
instance via regexp()
function helper.
This should allow to:
match
or replace
should perform action for all matchessplit
should do it by regexp or plain text delimiterExamples
match('foo', 'foo bar foo'); // 'foo'
match(regexp('/foo/'), 'foo bar foo'); // 'foo'
match(regexp('/foo/', 'g'), 'foo bar foo'); // ['foo', 'foo']
replace('foo', 'foo bar foo'); // ' bar foo'
replace(regexp('/foo/'), 'foo bar foo'); // ' bar foo'
replace(regexp('/foo/', 'g'), 'foo bar foo'); // ' bar '
RegExp
class foundationnew RegExp('^foo') -> /^foo/
)regexp()
function helperRegExp
in match()
RegExp
in replace()
Add invoker()
function which will calls given method with selected arguments.
Example taken from Laravel:
Users::all()
->map(P::pick(['name', 'email']))
This will return empty collection.
length()
supports only arrays and strings. It should also support Countable
objects.
With PHP 7.3 comes is_countable()
which can be quite handy (there's a polyfill for lower versions).
I've thought that nil
is a required thing to define undefined
values.
Turns out that using null
will be enough. Current functions do not accept null values, probably the future ones also won't do that.
TODO:
nil
constcurry()
, curryN()
to eliminate null values and curry function as long as all arguments are non-nullFrom Ramda docs:
Takes a predicate and a list or other
Filterable
object and returns the pair of filterable objects of the same type of elements which do and do not satisfy, the predicate, respectively. Filterable objects include plain objects or any object that has a filter method such asArray
.
An example comes from kapolos/pramda: basically, all array-related functions are using generators.
It's quite a nice idea. Worth implementing.
Same as Ramdas objOf
map()
should pass to fn
only value of iterated object.
mapIndexed()
should pass to fn
value, key and reference to object.
There's some inconsistency with usage of variadics.
Some functions (eg. apply
, partial
) require to pass array of an arguments where others (curry
, curryN
, pipe
) accept variadics.
This behaviour should be unified.
Possible solutions:
apply
, partial
, curry
); for rest (pipe
, compose
) use variadicsIt would be nice if the generator would append a template of functions docblock.
For some time I was wondering about library structure.
In terms of DX I think that phln\Phln
class is easy to use. Yet, in terms of "internal" structure and further development it's quite complicated.
In most cases each function brings to scope two functions (curried and lamda fn) and a const. Later this has to be "compiled" so that Phln
knows how to handle stuff. There's also problem with PHPUnit tests which work basically on a hack.
After some time of usage I realized that I'm not using in projects any particular functions outside of Phln
context. This made me thinking and I think I've found better way to structure things.
Below is "draft" of mine idea. I'm leaving it here so that I won't loose it.
First I thought that phln
is good namespace name. Mostly because it was meant to introduce functions, not Phln
class. Yet, the latter is mostly used and this naming convention seems odd.
I'd like to change it to Baethon\Phln
.
Phln
macroablePhln
should be extended by macros.
bundle.php
should be responsible for require_once
all of defined macros.
curriedMacro($name, $arity, $fn)
method as a shorthand for Phln::macro($name, Phln::curryN($arity, $fn))
Get rid of functions declarations. Register Phln
macro.
<?php
// math/sum.php
use Baethon\Phln\Phln;
if (Phln::hasMacro('sum')) {
return;
}
Phln::macro('sum', Phln::curryN(2, function ($a, $b) {
return $a + $b;
});
It should be possible to require_once
those macros which are required:
<?php
// collection/head.php
use Baethon\Phln\Phln;
if (Phln::hasMacro('head')) {
return;
}
require_once (__DIR__."/../fn/compose.php");
require_once (__DIR__."/../logic/cond.php");
// ...
Phln::macro('head', Phln::curryN(1, function ($collection) {
// ...
});
Phln
contains a list of constants which are meant to be used as "references" of functions.
I realized that this can be avoided just by calling method without any arguments.
Since functions are curried, when called without arguments, they will return a closure (aka "reference") to the function. This should be enough to use in different contexts.
<?php
use Baethon\Phln\Phln;
$pipe = Phln::pipe([
Phln::prop('values'),
Phln::apply(Phln::sum()),
]);
This means that some of the "aliases" (T
, F
, otherwise
) should by default return a function which, when called, returns given value.
<?php
$t = Phln::T();
$t(); // true
This rule applies to every function with arity = 0.
create:bundle
and create:docs
- they need to be removedBaethon\Phln\Phln
From Ramda docs:
Splits a list into sub-lists stored in an object, based on the result of calling a String-returning function on each element, and grouping the results according to values returned.
Dispatches to the groupBy method of the second argument, if present.
This prefix is horrible. It has to be removed.
TODO:
ƛand()
/ ƛor()
both()
/ either()
polymorphic - when arguments are primitives (booleans) they should return primitive valueƛand()
/ ƛor()
Right now it looks like this function is not curried properly.
This function should be split to reject()
(curried) and 𝑓reject()
, as in template.
Right now object
functions can work only with hash arrays.
Those functions should also accept class instances.
Functions from collection
namespace should also support "strings" (and treat them as an array of chars).
This should be applied only for functions in which this makes sense:
contains()
concat()
append()
prepend()
reverse()
slice()
chunk()
?create:bundle
create:docs
Right now function constants point to original (non-curried) function. This makes lots of problems and confusion. Those constants should point to curried version of function.
Similar to partial()
yet arguments are applied starting from right side of the array.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.