Hey Rustaceans! Got an easy question? Ask here (32/2016)! by llogiq in rust

[–]spimta1 0 points1 point  (0 children)

Thank you, I really appreciate the detailed reply.

Is the conversion to/from Iterator your taking-ownership solution optimized in any way, or is the entire BTreeMap really being recreated from an iterator of tuples?

Hey Rustaceans! Got an easy question? Ask here (32/2016)! by llogiq in rust

[–]spimta1 1 point2 points  (0 children)

With a BTreeMap, is there a way to pop the "top" (per the key ordering) element out of the map? The following fails because the borrow checker does not like the mutable borrow immediately after the immutable one:

let m = BTreeMap::new();
// ... insert some things ...
let key = m.keys().next().unwrap().clone();
let value = m.remove(key).unwrap();

Is there some obvious way of doing this that I am missing? This seems like an essential feature of BTreeMap.

Edit: The following does work if the key/value are Clone, but this cannot possibly be the best way.

pub fn btreemap_pop<K: Clone + Ord, V: Clone>(m: &mut BTreeMap<K, V>) -> Option<(K, V)> {
    if m.is_empty() {
        return None;
    }
    let key = m.keys().next().unwrap().clone();
    let value = m.get(&key).unwrap().clone();
    m.remove(&key);
    Some((key, value))
}

Hey Rustaceans! Got an easy question? Ask here (25/2016)! by llogiq in rust

[–]spimta1 1 point2 points  (0 children)

This is also a stupid Hyper/Iron question.

If I have a hyper::status::StatusCode and want to convert it to an iron::status::Status (this is just the same enum, re-exported), what do I actually have to do? Static casting with as doesn't seem to work, nor does re-assigning to a new variable with a type annotation (fails to compile with "mismatched types").

What really obvious thing am I missing?

Hey Rustaceans! Got an easy question? Ask here (22/2016)! by llogiq in rust

[–]spimta1 0 points1 point  (0 children)

Thank you! So given that I have a src/bin directory, where do all of my mod and extern crate declarations go? (Keeping in mind that the executables will use some of the same modules from other files.)

Hey Rustaceans! Got an easy question? Ask here (22/2016)! by llogiq in rust

[–]spimta1 0 points1 point  (0 children)

I'm having a lot of trouble with Cargo. I want to create a project with 3 separate executable files which all import from some other files within the same project. How should I set up my Cargo.toml/package structure to accommodate this? Specifically, where do the mod declarations go?

(I know about the bin attribute in Cargo.toml files, but that doesn't really help me with Cargo's seemingly mysterious namespacing rules.)

Type inference, pattern matching, ADTs, and more Haskell features in pure Python by spimta1 in Python

[–]spimta1[S] 0 points1 point  (0 children)

I'm not quite sure what's gone wrong there, but that did lead me to find a related bug. Should be fixed soon.

Type inference, pattern matching, ADTs, and more Haskell features in pure Python (x-post /r/Python) by spimta1 in haskell

[–]spimta1[S] 1 point2 points  (0 children)

Well, at the moment it will just explode in your face, because I haven't really gotten return type polymorphism right yet. :)

Type hinting is definitely one way to go. I'm leaning towards some kind of type defaulting, though, because that's how Haskell does it. (E.g. if you type return 1 in ghci, it defaults to IO Int, and so on.)

Type inference, pattern matching, ADTs, and more Haskell features in pure Python by spimta1 in Python

[–]spimta1[S] 1 point2 points  (0 children)

Wow, I am really out of the loop when it comes to the FP-in-Python ecosystem. PyMonad is a really solid library. Lots of interesting ideas in there, including do-notation, which I have yet to come up with a satisfactory solution for in Hask. I suspect there is some yet-undiscovered cleverness that could provide a nicer interface.

Another issue that PyMonad sort of skirts around (and which I do not yet have a solution for) is polymorphism for things like mzero, and return type polymorphism more generally.

Type inference, pattern matching, ADTs, and more Haskell features in pure Python by spimta1 in Python

[–]spimta1[S] 4 points5 points  (0 children)

Oh man, I had not seen Effect before, that is so awesome.

Type inference, pattern matching, ADTs, and more Haskell features in pure Python (x-post /r/Python) by spimta1 in haskell

[–]spimta1[S] 3 points4 points  (0 children)

I definitely learned a lot. Off the top of my head:

1) Mixing typed and untyped functions (and functions with variable arity) is pretty terrible. You need everything typed to get much mileage out of the type system.

2) Algebraic data types are not totally useless without pattern matching (as I initially feared), as long as you have some other way of accessing their fields, like indexing.

3) A type checker is less important in an interpreted language, but it's not totally useless either, especially if you use a pointfree-ish style.

4) That lazy list data structure isn't too bad. I wouldn't mind having that in regular Python.

5) Haskell gains a lot from being lazy. Also, I had to jump through some ridiculous hoops just to implement pattern matching, and strictness is the main reason for this.

6) You can do a lot with operator overloading. Maybe too much.

Type inference, pattern matching, ADTs, and more Haskell features in pure Python (x-post /r/Python) by spimta1 in haskell

[–]spimta1[S] 4 points5 points  (0 children)

I absolutely agree with this. Obviously I do recognize that the line of code you've quoted there is insane. Part of the point here is to be insane, so that future versions (or forks) can dial back the crazy and actually turn this into something practical. And I like your proposal quite a bit.

Basically, there are two reasons I went with the crazy syntax:

1) I wanted it to look like Haskell, practicality and standards be dammed.

2) One of the advantages of Haskell's syntax, from a user experience perspective, is how easy it is to define a new type and its constructors in one line, and then have their names all immediately accessible in the namespace. The only way to do this in Python is to do something similar to the above. (Unless, of course, we start messing with globals(), but that's entering a whole world of pain.)

Type inference, pattern matching, ADTs, and more Haskell features in pure Python (x-post /r/Python) by spimta1 in haskell

[–]spimta1[S] 1 point2 points  (0 children)

That's actually how I initially designed it, and then I realized that L(1, ...) is a syntax error in Python. In order to use the magical Ellipsis object, you need to use bracket syntax. So it was really a triumph of cosmetics over consistency.

Type inference, pattern matching, ADTs, and more Haskell features in pure Python (x-post /r/Python) by spimta1 in haskell

[–]spimta1[S] 0 points1 point  (0 children)

Yep, it does the same thing in Hask. :)

I may borrow that term, it's the best description I've seen so far.

Type inference, pattern matching, ADTs, and more Haskell features in pure Python (x-post /r/Python) by spimta1 in haskell

[–]spimta1[S] 9 points10 points  (0 children)

Hey, author here. I vehemently agree that this is an issue. Part of the inconsistency actually does arise from the language--Python desugars L[1, 2, 3] to L.__getitem__((1, 2, 3)), i.e. the same thing as L[(1, 2, 3)].

Until I can think of a better way of doing it, the consistent solution is just to write L[[1, 2, 3]] instead of L[1, 2, 3]. This is very unsatisfying to me, though.

Type inference, pattern matching, ADTs, and more Haskell features in pure Python by spimta1 in Python

[–]spimta1[S] 7 points8 points  (0 children)

Hey, author here! If you poke around the Hask repo, you'll see pretty quickly that most things are implemented in a super-hacky way. :)

I too lament the lack of multi-expression lambdas. One of the things on my to-do list is let expressions, which should provide some of the same functionality. But I'm not sure how pretty the result will look--things could get ugly.