Git Product home page Git Product logo

phln's People

Contributors

jdreesen avatar radmen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

phln's Issues

Generators support

An example comes from kapolos/pramda: basically, all array-related functions are using generators.

It's quite a nice idea. Worth implementing.

Replace ƛfunctions with something more suitable

This prefix is horrible. It has to be removed.

TODO:

  • find better name for ƛand() / ƛor()
    IF NOT:
    • make both() / either() polymorphic - when arguments are primitives (booleans) they should return primitive value
    • remove ƛand() / ƛor()
  • Create bundle
  • Update docs

Add `collection\groupBy()`

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.

Introduce `RegExp` object

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:

  • determine whether match or replace should perform action for all matches
  • determine whether split should do it by regexp or plain text delimiter

Examples

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 '

TODO

  • RegExp class foundation
  • automatic delimiter wrapping of pattern (e.g new RegExp('^foo') -> /^foo/)
  • add regexp() function helper
  • add support for RegExp in match()
  • add support for RegExp in replace()

Function/partialRight

Similar to partial() yet arguments are applied starting from right side of the array.

Remove `nil` in favour of `null`

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:

  • remove nil const
  • update curry(), curryN() to eliminate null values and curry function as long as all arguments are non-null
  • update type hints
  • create bundle
  • update docs

String/test

Add test() function which validates string with given regex.

Version 2: draft of proposed changes

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.


Namespace

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.

Make Phln macroable

Phln should be extended by macros.

bundle.php should be responsible for require_once all of defined macros.

  • 💡add curriedMacro($name, $arity, $fn) method as a shorthand for Phln::macro($name, Phln::curryN($arity, $fn))

Structure of function files

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) {
    // ...
});

Function "references"

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.


Impact

  • remove the possibility to import individual functions. It will be possible only in the context of the package
  • given the proposed structure it won't be possible to use PHPDocs as the source of generated documentation. It will be required to update generated MD docs manually.
  • there won't be any need to have create:bundle and create:docs - they need to be removed
  • there will be no function constants (aka function references) - everything has to be done via Baethon\Phln\Phln

Function/invoker

Add invoker() function which will calls given method with selected arguments.

Refactor `reject`

Right now it looks like this function is not curried properly.

This function should be split to reject() (curried) and 𝑓reject(), as in template.

Support string in `collection` functions

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()?
  • check against Ramda docs if there're other functions which require update
  • contains()
  • concat()
  • append()
  • prepend()
  • reverse()
  • slice()
  • chunk()
  • head()
  • init()
  • last()
  • tail()
  • Update docs (if required)
  • create:bundle
  • create:docs

Add `collection\partition()`

From 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 as Array.

Unify variadics

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:

  1. use variadics everywhere
  2. use array argument
  3. use array in cases when passing arguments to function (apply, partial, curry); for rest (pipe, compose) use variadics

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.