Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 03:58
    evhub edited #633
  • 01:06
    evhub commented #632
  • 01:01
    evhub reopened #632
  • Dec 06 23:37
    evhub milestoned #633
  • Dec 06 23:37
    evhub labeled #633
  • Dec 06 23:37
    evhub opened #633
  • Dec 06 10:17
    evhub closed #632
  • Dec 06 10:16
    evhub milestoned #632
  • Dec 06 10:16
    evhub labeled #632
  • Dec 06 10:16
    evhub labeled #632
  • Dec 06 10:16
    evhub labeled #632
  • Dec 06 10:16
    evhub opened #632
  • Dec 06 00:34
    evhub closed #628
  • Dec 06 00:34
    evhub commented #628
  • Dec 06 00:30
    evhub labeled #628
  • Dec 05 03:56
    evhub commented #628
  • Dec 05 03:55
    evhub commented #628
  • Dec 05 01:28
    evhub closed #631
  • Dec 05 01:28
    evhub labeled #631
  • Dec 05 01:25
    evhub commented #628
fakuivan
@fakuivan
the (key, value)*
Evan Hubinger
@evhub
yep! that's how fmap works on abc.Mapping objects.
servadestroya
@servadestroya
Hello
Is it possible to define fmap on new types?
Like addpattern fmap(f, obj is MyClass) = obj.map(f)
oh I see
the fmap dunder
it would be nice to have fmap be a pattern matched function so that this functionality could be added to third party libraries
Evan Hubinger
@evhub
@servadestroya __fmap__ is the way to do it, yep. If you want to add fmap support to a third-party object, you can always monkey-patch in an __fmap__ with
def ThirdPartyObject.__fmap__(self, func) = ...
Alternatively, if you want to use pattern-matching, you could also just define your own new fmap with
match def my_fmap(obj is ThirdPartyObject, func) = ...
addpattern def my_fmap(obj, func) = fmap(obj, func)
Pedro Queiroga
@pedroqueiroga

Hello friends, is this a bug?

>>> [-1] + rest = [-1,2,3,4]

CoconutParseError: parsing failed (line 1)

Coconut: Version 1.5.0 [Fish License] running on Python 3.9.2 and Cython cPyparsing v2.4.5.0.1.2

Evan Hubinger
@evhub
@pedroqueiroga Definitely a bug, but I just tested it on the latest coconut-develop and it looks like it's already fixed, so just pip install -U coconut-develop to get the fix.
anthonymccanny
@anthonymccanny

Hey all, I'm really new to coconut, and I think this is the right place for this question, but if I'm wrong, let me know.
Is there anyway in coconut to pipe an object and then call a method of that object, passing one of that objects' attributes as an argument of the method?
This question really arises from using pipes with pandas where I want to use a pipe to process a dataframe, and in that pipe change the index of that dataframe and then later access this new index as an argument within a .groupby() call or something similar. Of course I could assign a new dataframe variable, and complete this task but I was hoping there was a way to avoid it.
Here is a simple (and useless) example of what I'd like to do:

class A_Class:
    attribute = 1

    def method (self, argument):
        print(f"The argument is {argument}")

an_object = A_Class()

an_object |> \
.method(.attribute)

Output: The argument is operator.attrgetter('attribute')
My Desired Output: The argument is 1

Is there anyway to do what I'm trying to do? Am I misunderstanding something crucial? Thank you!

Evan Hubinger
@evhub
@anthonymccanny I think you probably just want to use a lambda for that case—so maybe something like:
result = (
    an_object
    |> o -> o.method(o.attribute)
)
anthonymccanny
@anthonymccanny
Thank you Evan! That is a great idea that I hadn't considered.
Gianpiero Cea
@GianpieroCea
Hi everyone, I am super new to Coconut and from what I can see it seems amazing. Anyway , my goal would be to use coconut for doing data science , I am very jealous of R's dplyr style pipes and so coconut seem to fix. I am pretty sure I am not the only one (I can see the question above is on how to work with a pandas DataFrame). My question: is there any tutorial for coconut with a focus on doing data science ? I do like the case studies on the documentation but they are very much "computer sciencey" in style, which is absolutely fine, is just that if you don't have a too strong background in functional programming I think it's difficult to see the advantage that coconut can bring to doing data science. Looking forward to hear your opinion on this :)
Evan Hubinger
@evhub
@GianpieroCea I don't know of any Coconut tutorial that specifically focuses on data science--you could try going through this tutorial (https://hmcfabfive.github.io/coconut-tutorial/) though, which isn't specifically focused on data science but might be more of what you're looking for.
Gianpiero Cea
@GianpieroCea
not what I was looking for but definitely a nice resource I had not seen before. If someone that has been using coconut to do data science for a while and has a blog post or something on best practices or cool example of coconut in action I would still like to see it. Thanks a lot Evan.
Ishaan Verma
@lazyprop

Hi! I was looking for a VI-Mode for the Coconut REPL. I couldn't find any such configuration option in the documentation or the FAQ. I took a look at the source and there is prompt_vi_mode in constants.py and it is initially set to false. How do I set it to true? (without changing the source obviously)

Also, I find it weird that Coconut doesn't use GNU Readline like the Python REPL. Just out of curiosity, is there any specific reason for that?

Evan Hubinger
@evhub
@lazyprop You should raise an issue for adding a flag/environment variable for enabling vi mode; it should be pretty easy since it's just that constant that you found. The reason for using prompt toolkit over readline is primarily for the syntax highlighting, though it's also just generally a pretty good prompt framework--it's the same framework that's used by Jupyter console.
Ishaan Verma
@lazyprop
alright I'll raise an issue and maybe open a PR
vip-ehowlett
@vip-ehowlett
Does Coconut support discriminated unions?
Evan Hubinger
@evhub
@vip-ehowlett No—Coconut just uses Python's type system (with a couple extra bells and whistles), which doesn't support anything like that.
vip-ehowlett
@vip-ehowlett
That's a shame. Disc. unions are one of my favorite features. Really liking coconut, though. I feel like just having pipe operators makes downloading it worth it. There's so much conciseness that comes from them.
What's the state of the language server implementation? I have some highlighting but almost no type-hinting in VSC. I've never tried to implement one but is that something you're looking for help on?
Evan Hubinger
@evhub
@vip-ehowlett If you have an idea for what a discriminated union implementation might look like in Coconut, feel free to raise an issue for it—that's definitely something I'd be interested in looking at trying to add. As for the language server, a language server isn't something I'm working on now or planning on working on in the near-term future, but it's definitely something I'd be pretty excited about having—I'd be happy to at least provide some guidance. Theoretically, it shouldn't be that hard, since you can just use an existing Python language server and map the results back and forth between the Python source and the compiled Coconut, but there could still be a lot of issues there like getting the right column mappings, compilation latency being an issue, etc. Also, if you want to take a look at the existing VSC package that just provides syntax highlighting, you can find that here.
vip-ehowlett
@vip-ehowlett

We could for sure use a lot of the Python language server, however, on top of what you said, I also see an issue with code completion/type inferencing when using the superset.

As for the implementation of disc. unions, that'd be a little clunky. Trying to think of something that'd run in all versions, we'd compile a class with an array of the field names and then when we match, we'd essentially just be matching on values in that array for which we can return self.field. I'm pretty sure type inferencing on that would be out the window, though.

Evan Hubinger
@evhub

@vip-ehowlett What would that discrete union implementation give you that something like

data Empty()
data Leaf(n)
data Node(l, r)

Tree = (Empty, Leaf, Node)

def size(Tree()) = 0
def size(Tree(_)) = 1
def size(Tree(_, _)) = 2

doesn't give you?

vip-ehowlett
@vip-ehowlett
You have to know the structure of the tuple with this. I"m not sure how often the case would be, but with the other implementation, you can just match on the name of the tag.
Evan Hubinger
@evhub

@vip-ehowlett Coconut can also do

Tree = (Empty, Leaf, Node)

def size(t is Tree) = 1 + sum(map(size, t))

where you don't have to know the structure of the tuple, if that would solve your use case.

vip-ehowlett
@vip-ehowlett

It might.

I usually use discriminated unions to wrap possible function arguments. Below is what I was hoping for.

possible_args = ( option1: str, option2: int, option3: MyCustomDeeplyNestedObject )

def my_function( args : possible_args ) :
     match args:
         case str instance_variable: exprs / stmnts on strings
         case int instance_variable: exprs / stmnts on ints
         case MyCustomDeeplyNestedObject instance_variable: exprs / stmnts on MyCustomDeeplyNestedObject

But I'm not sure if I can use is in that match statement. That would be checking to make sure the variable refers to the same object reference, right?

Evan Hubinger
@evhub

@vip-ehowlett is in pattern-matching just does type-checking, not check that it's the same object reference. Here are some ways you could write your example in Coconut:

def my_function(x is str) = exprs/stmts on strings
addpattern def my_function(x is int) = exprs/stmts on ints
addpattern def my_function(x is MyCustomDeeplyNestedObject) = exprs/stmts on MyCustomDeeplyNestedObjects

or

def my_function(arg):
    case arg:
        match _ is str: exprs/stmts on strings
        match _ is int: exprs/stmts on ints
        match _ is MyCustomDeeplyNestedObject: exprs/stmts on MyCustomDeeplyNestedObjects

or

possible_args = (str, int, MyCustomDeeplyNestedObject)

def my_function(arg is possible_args):
    case arg:
        match _ is str: exprs/stmts on strings
        match _ is int: exprs/stmts on ints
        match _ is MyCustomDeeplyNestedObject: exprs/stmts on MyCustomDeeplyNestedObjects
Evan Hubinger
@evhub

If you're using coconut-develop (or in the next released Coconut version), you'll also be able to do

def my_function(arg):
    match arg:
        case class str(): exprs/stmts on strings
        case class int(): exprs/stmts on ints
        case class MyCustomDeeplyNestedObject(): exprs/stmts on MyCustomDeeplyNestedObjects

if you prefer that syntax, which is making use of Coconut's implementation of PEP 622, which is fully supported in develop now and will come out in the next release.

dontmindmehere
@dontmindmehere
hello
I'm just learning coconut
thought I understood the syntax pretty ok but can't get this to work on the coconut-lang.org repl:
num = next(filter(lambda i: i<3, nums), 0)
num = nums |> filter$((i -> i<3), ?) |> next$(?, 0)
Evan Hubinger
@evhub

@dontmindmehere When I use the website interpreter to run

nums = count()
num = next(filter(lambda i: i<3, nums), 0)
print(num)
num = nums |> filter$((i -> i<3), ?) |> next$(?, 0)
print(num)

I get

0
0

which seems right to me. What error are you seeing instead? Also, though this should work with the website interpreter, I think it is running a relatively outdated version of Coconut, so it won't have all the new features (though it should support everything you're using there).

dontmindmehere
@dontmindmehere
oh
it was the newlines
I had written it like this
num = nums
    |> filter$((i -> i<3), ?)
    |> next$(?, 0)
works when I escape newlines
dontmindmehere
@dontmindmehere
thanks
I started learning Rust and now I'm missing the functional stuff in python xd
Evan Hubinger
@evhub
@dontmindmehere Ah, yes. Coconut handles whitespace just like Python, which means you can escape newlines with backslashes, but the preferred way is just to use parentheses, as in
num = (nums
    |> filter$((i -> i<3), ?)
    |> next$(?, 0))
dontmindmehere
@dontmindmehere
oh nice, didn't know you could do that
Aaron Virshup
@avirshup

Hi - I was wondering if there's any way to reproduce the functionality of pip install -e for a project with coconut files in it.

My guess is that you'd need to set up a file watcher (e.g., watchdog) to handle recompiling files when they're changed? But was wondering whether there might be alternative strategies

Evan Hubinger
@evhub
@avirshup Like you were saying, you could use coconut --watch—but better might be to use automatic compilation. If you make sure in the root of your project (e.g. the top-level __init__.coco) you import coconut.convenience then compile fully once, pip install -e should do what you want. Also, if you're using coconut-develop (which you can get via pip install -U coconut-develop), you can run coconut --site-install which will make coconut.convenience imported automatically on Python start so you don't have to import it in the project root.
Aaron Virshup
@avirshup
@evhub - Ah, apologies - I completely missed that in the documentation. That looks excellent, I'll try it out. Thanks!!!
Peter Henry
@mosbasik

Just heard of this via the recent HN thread; started going through the interactive tutorial. The pattern matching "now you try it" page (https://hmcfabfive.github.io/coconut-tutorial/Patternmatch/Patternmatch_p3.html) is a little rough around the edges, imo. I get that its purpose is to teach pattern matching syntax, but the solution makes a lot of choices the motivations behind which I don't understand.

fwiw, my solution was

from collections import Counter
items |> Counter |> print

(which btw I was pretty tickled to hit on, coconut makes that pretty darn clean :) )

  1. Why the choice to make itemsan iterator? Seems like it'd be fine to leave it as a list.
  2. Relatedly, later we could use a for loop instead of a whileloop and avoid manually defining a stop condition, manually calling next(), etc.
  3. Why mess around with a current variable inside the match branches? wouldn't an aluminums[0] += 1 work?
  4. I get that you need to pass mutable structure(s) into countItems() to accumulate results, which explains the single-element lists. One could use a single dict instead (arguably more Pythonic), but then of course you actually don't need the pattern matching at all because you just use the item string as the key and you only need to write a single case (which is how I hit on using Counter in the end).

I was surprised enough at these choices that I was expecting another page saying things like "we prefer to use iterators in coconut because...", but that was the end of the pattern matching section. So I was considering thinking for a little bit to come up with a toy problem that really demonstrates how pattern matching can improve on vanilla python's approach - but I hesitated because I haven't gone through the whole tutorial yet and wanted to make sure I wasn't being totally oblivious to something.

Peter Henry
@mosbasik
(some minutes later) naturally, of course, the tutorial continued to expand on pattern matching and showed off some meatier uses for it - so my point 4 is maybe moot.
Evan Hubinger
@evhub
@mosbasik The real answer is that the interactive tutorial was written by a group of non-core Coconut contributors (which is to say, not me), so I can't really comment on the particular choices that it makes. The non-interactive tutorial was written by me, but it's also pretty old and obviously non-interactive. If you wanted to make some changes to the interactive tutorial, I'd be happy to pull them in and put them up.
Peter Henry
@mosbasik
cool, thanks for the response. I'll read with an eye to how I might improve things then.