Open EasyArray opened 2 years ago
I think having a class for explicit functions is a good idea, and it could even replace the set class (a set would be a function that maps every input to None
). Is there ever a reason we'd want a function as the input to another function though? This wouldn't be possible using dict
, since they are hashable, and I don't think frozendict
is built into Python...
I'm starting to wonder if these should actually be LambdaVal's? Pros / Cons for that idea? There would be a different syntax, maybe something like: λ{ 1→2, 2→4, 3→6 }
This seems reasonable. Under the hood it might get a little bit complicated because (the way I imagine it) you'd have two different representations depending on whether the function is an actual lambda or an explicit function, but it would make all functions the same.
I was thinking that we could store the explicit function as the body of a standard LambdaVal. The body is a "Span" so it's basically just some phosphorus code that later gets evaluated. So (note the square brackets, like the book uses), λ[1→2, 2→4, 3→6]
might be stored exactly like the phosphorus lambda function λx . {1:2, 2:4, 3:6}[x]
. (Modulo the problem you noted with dicts: I don't know if LambdaVals are hashable.)
Update: LambdaVal's are not hashable. But we could make them so, if we wanted: https://hynek.me/articles/hashes-and-equality/
Yes, was thinking something along those lines. Probably the easiest, actually, would be to hash them based on their repr. This would not be perfect, as in the same function with a slightly different definition would not hash the same, but it would probably suffice for our purposes. Especially since we are hand-creating these explicit function LambdaVals and can do things like sorting to canonicalize the reprs.
Yeah I think this should be relatively straightforward, although I don't know how storing as a Span affects things. But Python functions are hashable so in principle we could just get the corresponding Python lambda and hash that.
Ha, I think we are commenting at the same time -- check my comment about hashing the repr
Yep that makes a lot of sense! Is this something I should look into? It seems like this might be something that happens when things are parsed - allowing LambdaVals to be constructed with explicit functions. Also, should sets that are explicit functions be automatically turned into LambdaVals?
Something I can do is take out the ability of SetVals to be called as explicit functions. This would simplify SetVal.__call__
quite a bit! But I assume that shouldn't be done until whatever we're doing with explicit functions as LambdaVals is implemented.
You are right that this is perhaps a parsing / input conversion issue. I'm thinking that sets will not (any longer) automatically get interpreted as explicit functions. Instead, the new syntax will be required, and will generate a LambdaVal. Some care will have to be used in generating a repr for such a LambdaVal, since it might be confusing to input something like λ[1→2, 2→4, 3→6]
only for the system to output λx . {1:2, 2:4, 3:6}[x]
. Perhaps LambdaVal could store a flag as to whether it is an explicit or code-based function? And then print out explicit functions as they were input.
To this end, perhaps you could do the following:
I will work on parsing the explicit format correctly (shouldn't be too hard) -- just let me know the "API" for the LambdaVal constructor. We can later turn off the logic for explicit functions in SetVal.__call__
.
Great! This sounds doable.
I'm having a little trouble understanding how LambdaVals work, so this is not going too well. For instance, I'm not sure what the current arguments of the constructor function are or what they do later on. I think maybe I need to learn a little more about parsing — do you have any recommendations for resources? Or if you have other ideas for figuring out how these objects work, that would be great! I have some debugging tools with JupyterLab, so maybe seeing how things flow as the notebook runs would be helpful? I'm open to ideas!
Never mind, I figured it out! VSCode's Jupyter debugging tools are incredible — exactly what I needed. I just stepped through the parse/constructor functions and was able to figure everything out. I think I have everything done now, so I'll do a bit of testing and hopefully push a version for you to look at tomorrow.
Great! I should try out VSCode again -- do you mind sending me your configuration / plugins /etc? Oh, and also could you document what you found out / what confused you at first, if you haven't already?
Sure! I love VSCode. The one drawback is that tab-completion doesn't work in Jupyter notebooks, which makes using Phosphorus a pain sometimes. But the debugging is great — exactly what I wanted with stepping into function calls in phosphorus etc.
The relevant Python/Jupyter extensions I have are: Python, Pylance, Jupyter, Jupyter Keymap, and Jupyter Notebook Renderers, all from Microsoft. I'm not sure if it affects anything, but I also have the following in my settings file:
"python.showStartPage": false,
"workbench.editorAssociations": {
"*.ipynb": "jupyter-notebook"
},
"python.pythonPath": "~/miniforge3/bin/python",
"python.defaultInterpreterPath": "~/miniforge3/bin/python",
"notebook.cellToolbarLocation": {
"default": "right",
"jupyter-notebook": "left"
},
The miniforge path is just where I have the conda installation.
I will definitely add some documentation for what I figured out!
S = {<1,2>->A, ...); S(1,2) #returns false