coconut --display
to look at what various different uses of the pipe operator compile to.
hello, i'm a super noob to functional programming and the Coconut language. I went over the tutorial section to get a grasp of few of the concepts and was hoping to apply some of the learnings to a messy piece of code but i'm struggling to get started.
my current solution is to create layers of nesting to get some values out of a json object. i'm looking for some advise on how to take a functional approach to solve this problem.
here is my test json
{
"mobile/stats": {
"nestedStats": {
"kind": "stats",
"entries": {
"activeMemberCnt": {
"value": "3"
},
"totRequests": {
"value": 600
},
"mobile/members/stats": {
"nestedStats": {
"entries": {
"firePunch/stats": {
"nestedStats": {
"entries": {
"power": {
"value": 25
},
"pp": {
"value": 10
},
"type" : {
"value" : "Fire"
}
}
}
},
"icePunch/stats": {
"nestedStats": {
"entries": {
"power": {
"value": 75
},
"pp": {
"value": 15
},
"type" : {
"value" : "Ice"
}
}
}
},
"karateChop/stats": {
"nestedStats": {
"entries": {
"power": {
"value": 25
},
"pp": {
"value": 10
},
"type" : {
"value" : "Fighting"
}
}
}
}
}
}
}
}
}
}
}
stats = {}
for k, v in test_json.items():
for kk, vv in v.items():
if 'nestedStats' in kk:
for kkk, vvv in vv.items():
if 'entries' in kkk:
for kkk1, vvv1 in vvv.items():
if '/stats' in kkk1:
for kkkk, vvvv in vvv1.items():
for kkkkk, vvvvv in vvvv.items():
for kkkkkk, vvvvvv in vvvvv.items():
for kkkkkkk, vvvvvvv in vvvvvv.items():
for kkkkkkkk, vvvvvvvv in vvvvvvv.items():
stats[kkkkkk] = vvvvvvvv
poke_stats = json.dumps(stats).replace('\'', '"').replace('description', '').replace('{"":', '').replace('{"value":', '').replace('},', ',')[:-1]
nalix
> <@gitter_rawvnode:matrix.org> hello, i'm a super noob to functional programming and the Coconut language. I went over the tutorial section to get a grasp of few of the concepts and was hoping to apply some of the learnings to a messy piece of code but i'm struggling to get started.
my current solution is to create layers of nesting to get some values out of a json object. i'm looking for some advise on how to take a functional approach to solve this problem.
test json
```
The function approach to deeply nested data structures is lenses (at least the only one I know of). This seems like what you'd need, though I haven't used the package myself.
nalix
* The functional approach to deeply nested data structures is lenses (at least the only one I know of). This seems like what you'd need, though I haven't used the package myself.
i think i've somewhat simplified the code to be slightly less convoluted by adding a few things...
also i made a few assumptions to reduce the complexity within the flow like separating the logic to handle parent stats and its member stats.
the new function walks along the json tree path going from parent, child all the way down until it encounters an attribute labeled "value" and add its value to the member_stats
dict when there is a match and the value
is of type int. The key will be the second but previous element in the path
list.
I've replaced the deep nesting of for loops with a recursive function. I'm hoping to add more features like pattern matching and map/filter if possible and also eliminate the global level dicts to manage state :)
parent_stats = {}
member_stats = {}
def traverse(obj, path=None):
if path is None:
path = []
if isinstance(obj, dict):
value = { k: traverse(v, path + [k]) for k, v in obj.items()}
elif isinstance(obj, int):
value = obj
if "value" in path:
node_key = list(filter(lambda x: re.search('https.*members.*members/(.+)/stats\Z', x), path))
if node_key:
if node_key[0] not in member_stats.keys():
member_stats[node_key[0]] = {path[-2] : value}
else:
member_stats[node_key[0]].update({path[-2] : value})
else:
parent_stats[path[-2]] = value
else:
value = obj
return value
traverse(poke_stats)
parent_stats
{
"mobile/stats": {
"activeMemberCnt" : 3,
"totRequests" : 600
}
}
member_stats
{
"firePunch/stats" : {
"power" : 25,
"pp" : 10
},
"icePunch/stats" : {
"power" : 25,
"pp" : 15
},
"karateChop/stats" : {
"power" : 25,
"pp" : 10
}
}
@evhub Im planning to use data
to build a toolkit around network analysis. The big issue with graph data structures I've encountered is the need to constantly keep track of whether you're using an edge-oriented function or a node-oriented one. So, does my function operate on adjacency matrices, edgelists, etc.
The most elegant way I've seen this done imo is tidygraph https://tidygraph.data-imaginist.com/ which lets you switch modes.
in my case, I would like to build a graph data
object that stores both. Then, there are functions that work on either adjacency matrices, or on edgelists, etc. I would like to be able to pass a graph object to those functions and have them behave like the correct contents were passed
my intuition is to write a pattern-matching fmap
to turn the graph object into a sort of two-faced functor: if the function passed to fmap accepts e.g. square matrices, the fmap uses the adjacency representation....if it accepts lists/vectors, it instead uses the edgelist view.
A bit of a functional noob here, so just wanting some feedback if this is something ridiculous to do, w.r.t. coconut's design haha
__fmap__
the other way is to have to manually specify for every function whether it uses the edge or node view. the problem is, I would like to write them in terms of straight np.array
or jax.numpy.array
objects, and having to add a
@addpattern(myfunc)
def myfunc(g is graph)=
myfunc(g.adjacency)
seems like a lot of extra boilerplate...
Hello! I'm just starting with coconut and I'm integrating it with mypy
. I created a simple hello world example
"hello world" |> print
and I tried to compile it integrating it with mypy
:
coconut run.coco --mypy
but I'm getting this odd error:
Compiling run.coco ...
Compiled to run.py .
$HOME/.coconut_stubs/__coconut__.pyi:81: error: Module has no attribute "abc"
Found 1 error in 1 file (checked 1 source file)
Exiting due to MyPy error.
What could be the cause of this error?
FYI, I'm using a virtual environment and Python 3.7.
mypy
is getting mad at Coconut using collections.abc
, which is strange because it be available on Python 3.7. First, just try uninstalling coconut and reinstalling the latest dev version by running pip install --upgrade coconut-develop[mypy]
and see if that fixes the issue. If not, try running coconut run.coco --target sys --mypy
instead, which should tell mypy
to check according to the current Python version.
(coconut-sample-fvM68vJh-py3.7) ➜ coconut-sample git:(master) ✗ coconut run.coco --verbose --mypy
Using Cython cPyparsing v2.4.5.
Parsed args: Namespace(argv=None, code=None, dest=None, display=False, documentation=False, force=False, history_file=None, interact=False, jobs=None, jupyter=None, keep_lines=False, line_numbers=False, minify=False, mypy=[], no_tco=False, no_write=False, package=False, quiet=False, recursion_limit=None, run=False, source='run.coco', standalone=False, strict=False, style=None, target=None, tutorial=False, verbose=True, watch=False)
Compiler args: {'target': '', 'strict': False, 'minify': False, 'line_numbers': False, 'keep_lines': False, 'no_tco': False}
MyPy args: ['--python-version', '3.7', '--warn-incomplete-stub', '--warn-redundant-casts', '--warn-return-any', '--warn-unused-configs', '--show-error-context']
Hash args: {'VERSION_STR': '1.4.3 [Ernest Scribbler]', 'reduce_args': ('', False, False, False, False, False), 'package_level': 0}
Compiling $HOME/Documents/code/Coconut/coconut-sample/run.coco ...
Hash args: {'VERSION_STR': '1.4.3 [Ernest Scribbler]', 'reduce_args': ('', False, False, False, False, False), 'package_level': 0}
Time while parsing: 1.245418 seconds
Packrat parsing stats: 494 hits; 6419 misses
Compiled to $HOME/Documents/code/Coconut/coconut-sample/run.py .
Traceback (most recent call last):
File "$HOME/.cache/pypoetry/virtualenvs/coconut-sample-fvM68vJh-py3.7/lib/python3.7/site-packages/coconut/command/util.py", line 300, in symlink
os.symlink(link_to, link_from, target_is_directory=True)
FileExistsError: [Errno 17] File exists: '$HOME/.cache/pypoetry/virtualenvs/coconut-sample-fvM68vJh-py3.7/lib/python3.7/site-packages/coconut/stubs' -> '$HOME/.coconut_stubs'
MYPYPATH = $HOME/.coconut_stubs
> mypy $HOME/Documents/code/Coconut/coconut-sample/run.py --python-version 3.7 --warn-incomplete-stub --warn-redundant-casts --warn-return-any --warn-unused-configs --show-error-context
run.py:16: note: In module imported here:
$HOME/.coconut_stubs/__coconut__.pyi: note: In class "_coconut":
$HOME/.coconut_stubs/__coconut__.pyi:81: error: Module has no attribute "abc"
Found 1 error in 1 file (checked 1 source file)
Exiting due to MyPy error.
What a coincidence, I ran face-first into this same issue just last night. I too am in a venv on Linux, but using the Python 3.8.5 from the Manjaro repos. Below are some details of the environment, edited for clarity:
$ coconut -v
Coconut: Version 1.4.3 [Ernest Scribbler] running on Python 3.8.5
$ python
Python 3.8.5 (default, Sep 5 2020, 10:50:12)
[GCC 10.2.0] on linux
import collections.abc
abc = collections.abc
import sys
sys.version_info
sys.version_info(major=3, minor=8, micro=5, releaselevel='final', serial=0)
sys.version_info > (3,3)
True
sys.version_info < (3,3)
False
$ mypy -V
mypy 0.790
$ coconut -t 38 -j 4 -k --no-tco --force . --mypy
Compiling main.coco ...
Compiled to main.py .$HOME/.coconut_stubs/coconut.pyi:99: error: Module has no attribute "abc"
It would appear that the mypy error is happening on the "abc = collections.abc" assignment in coconut.pyi which is strange since that works fine in the repl.
lrwxrwxrwx 1 me me 59 Nov 3 15:46 $HOME/.coconut_stubs -> $HOME/.local/lib/python3.8/site-packages/coconut/stubs
and yet I'm still getting, on compile, $HOME/.coconut_stubs/__coconut__.pyi:81: error: Module has no attribute "abc"
with no other changes.
(print)((sq)((_coconut.operator.add)(*(1, 2))))
for me
print(sq(operator.add(1, 2)))