Hacker Newsnew | past | comments | ask | show | jobs | submit | tommikaikkonen's commentslogin

The demo video is great, I would consider putting it higher up on the page and possibly on autoplay. I wonder when Amazon will integrate LLM into the native reader. Nice work!


Thanks! Yeah the landing page might need some work

re: Native LLM: The fact that Amazon just upgraded the web browser shows that they at least have some engineers working on Kindles, so one can always hope


and yet, there are some obvious things on my scribe that they haven't done:

- no way to disable auto-rotate

- can only write on PDFs from send-to-kindle, but that's limited to I think 50MB so textbooks etc. are not an option

- only works with audible audiobooks, no normal m4b supported

i believe the web browser is also still crazy cut down. i like the device but they're evidently understaffed on software


Fair point, yeah it's definitely still cut down


Indeed. I wrote a Python pretty printer that uses a Wadler/Leijen algorithm, and it's a great fit. It doesn't take too long to learn how to use the layout primitives, and it allows for easy creation of higher level abstractions while still maintaining plenty of control.

https://github.com/tommikaikkonen/prettyprinter


I love using attrs, like the idea of bringing something similar to the standard library, but strongly disagree with the dataclasses API. It treats untyped Python as a second class citizen.

This is what I'd prefer

  from dataclasses import dataclass, field

  @dataclass
  class MyClass:
    x = field()
but it produces an error because fields need to be declared with a type annotation. This is the GvR recommended way to get around it:

  @dataclass
  class MyClass:
    x: object
You could use the typing.Any type instead of object, but then you need to import a whole typing library to use untyped dataclasses. I highly prefer the former code block.

There's a big thread discussing the issue on python-dev somewhere. Also some discussion in https://github.com/ericvsmith/dataclasses/issues/2#issuecomm...

Anyway, it's not a huge issue—attrs is great and there's no reason not to use it instead for untyped Python.


Yeah, it seems strange to force people to use type hints when it has had such a mixed reception. I really tried to use type hints with a new project a few months ago, but ended up stripping it all out again because it's just so damn ugly. I wish it were possible to fully define type hints in a separate file for linters, and not mix it in with production code. It's kind of possible to do it, but not fully [1], and mixing type hints inline and in separate files is in my opinion even worse than one or the other.

[1] https://stackoverflow.com/questions/47350570/is-it-possible-...


I've always wanted a programming UI similar to RapGenius's UI. With annotations and docs being opened in a form panel.


I did my MSc thesis on SaaS pricing pages. I'll share what I found, since I think many people in this thread may find it useful.

I tested how Mechanical Turkers (N=~400) chose plans on pricing pages with 4-tiered subscriptions plans, for both a file sharing service and a payroll software service. Each respondent was randomly assigned to one of 4 conditions, where the presented pricing page was slightly different. The scenario was framed as choosing a SaaS plan for a company they're employed at.

The first variable I varied was plan order. Half the respondents saw a pricing page with plans in increasing price order (cheapest first), the other half in decreasing price order (most expensive first). There was a statistically significant difference between the plan choices for these groups; respondents in the most expensive plan first condition chose a more expensive plan. This phenomenon has been seen before outside SaaS, and it's called the price order effect.

Another variable I tested was exchanging the cheapest ($5) plan for a free plan. Half the respondents saw a free plan, the other half a $5 plan. There was no statistically significant difference in the plan choice for these groups.

Getting familiar with previous literature, I would surface a couple of general thoughts:

- The most expensive plan first approach may give the visitor a more expensive image of the product, a higher "reference price". If a prospective customer is comparing two products from two different companies, they may favor the one that seems cheaper (has a lower "reference price") even if the offerings may provide similar value.

- The hypothesized mechanism for the price order effect is that you don't look at all the options as a whole, but you begin by assessing the first option, which is the leftmost one for us reading left-to-right, and then judge the next option by comparing it to the previous one, and so on. You compare added (more features/less cost) and lost (less features/more cost) value. Because we weigh losses heavier than benefits, there's an inertia toward the initial options. Only options with benefits that greatly outweigh losses combat that inertia. Hence respondents tended to choose plans more on the left.


Fatal flaw: the turkers weren’t invested, it was just a nonsense game for them.


Agreed. I think this kind of research can give ideas on what kind of experiments to run on pricing pages, but there are so many factors affecting real life plan choice that everyone should have their own A/B testing setup to see what works for them specifically.


I agree, relying for Mech Turks would not produce real world results.


thanks for such beautiful insights. It's nice to see that there is no significant difference between free and almost-free plans.

Is that somehow possible to share your your thesis? I'd love to read end to end.


There's probably a flaw in paying people (MTurks) to choose pricing plans for something they don't really care about. Real consumers might act differently.


Thanks. The thesis is really mediocre academically, so I don't feel comfortable putting it out in the public, but if you leave an email address here or contact me through Twitter I'll gladly send it to you.


Thanks for your modesty. Unfortunately, I feel the same about my thesis (in progress) and would much rather share some weekend hack on GitHub...


I think that's natural and OK. I would compare writing my thesis to writing my first full application after learning how to read and write code—even after several iterations under a skilled supervisor, the codebase is still going to have a more or less fledgling and awkward quality to it, even if the functionality proves useful. The second attempt takes less effort and results in higher quality output.

Similar to how few people would put their first application out in public, I prefer to keep my thesis private unless someone finds the information really useful :)


Followed you on Twitter.


I've migrated a lot of code from moment to date-fns because of moment's bulky size and vast, mutable API. Luxon seems to fix the API issue. date-fns is still great for simple operations, but I'll definitely consider this for new projects with nontrivial datetime handling.


Yes, mutation in Moment has burned me a few times before I realized that occurs.

Edit: wow, I just looked at the repo and realized its made by the Moment team. That might be pretty cool.


How does this compare to elasticsearch-dsl?


Where can I order a physical copy?


What was the optimization?


Our version of shell_plus was trying to handle aliased models that were defined in settings.py.

In order to do this, it was maintaining a map of {appName: [list of imports]}.

When constructing this map, for some reason, it n^2 the imports - i.e., if an app "foo" had models "Bar", "Foo", "FooBar", then the import strings were, "from foo import Bar; from foo import Bar, Foo; from foo import Bar, Foo, FooBar" instead of "from foo import Bar, Foo, FooBar". Some apps had 50+ models, so instead of 1 import line for these 50 models, it was executing 2500 import lines. I fixed this so that it executed only one import line instead n^2 import lines.


Currying in JavaScript is really nice if you can remember the arities of each curried function you're using. If you forget to call up to the last argument, you'll be passing a curried function instead of the expected value, and it can throw an error really far away from the bug. And instead of normal data to inspect at the error site to point you to the bad call, you'll only have a generic function name to look at. I've spent more hours than I'd like to admit debugging these situations.

A type system would detect these cases, but TypeScript and Flow don't have great support for curried functions. Typing them is very verbose.


I think this exact problem is what makes currying in JS and dynamically typed languages not very practical.

In JS is even worse because of the weak typing, if by mistake you get a curried function instead of a value, JS will happily operate on it giving you things like "hellofunction () {}". When you realize that there is a problem, it would be hard to find the actual cause of the error.

I think this is the reason why dynamic functional languages such as Clojure don't use auto-currying. I a static typed world, like Haskell's this is not a problem at all.

Partial application on the other hand is very useful and practical in JS and other dynamic languages.


I beg to differ. Auto-currying (eg via Ramda) is awesome, powerful, and pragmatic.


The type of a curried function in Typescript is just something like:

  (a: number) => (b: number) => (c: number) => number
Sure, the parameter names and parentheses are a bit annoying, but I wouldn't call that "very verbose". Comparable concepts in C++ or Java would be a nightmare to type out.


I agree, that doesn't look bad. However, this type definition forces you to supply one argument per function call, which looks awful in JavaScript:

    fn(1)(2)(3)
That's a big drawback for me. Libraries like Ramda allow one or more arguments per function call:

    fn(1, 2, 3) === fn(1, 2)(3) === fn(1)(2, 3)
That's what makes the verbosity unbearable, as each type of call needs its own type.


At least in Flow it's actually possible to properly type curried functions!

Here's a gist of the type definitions I'm using: https://gist.github.com/noppa/c600cc43fd44e33768efe6c6eec4a9...

I think something similar might work in TS too.

Demo: https://goo.gl/w3aPsw


While Java’s option is quite painful

    Function<Number, Function<Number, Function<Number, Number>>>
The same in Kotlin is actually okayish:

    (Number) -> (Number) -> (Number) -> Number


I can't speak to Typescript but check out the Flow types for Ramda: https://github.com/flowtype/flow-typed/blob/master/definitio...

Maybe just a matter of perception but it looks verbose to me.


I've been using currying (via http://ramdajs.com/) in my projects for a while now and this is rarely a problem(yay for anecdotal evidence).

One reason for that is that my curried functions and their derivatives are usually named in a way that says exactly what they do.


Not only do you need to remember the arity, but the order as well, which is IMO worse (at least a type system can protect you from arity mistakes). If your function is not commutative for adjacent arguments of the same type, you're skipping through a minefield if you rely on currying.


How is that any different from having to remember the argument order in normal function application?


Conceptually it's not that different. Practically, it's pretty different because you're effectively fragmenting a single function application across your codebase, making it harder to reason about and more likely to make ordering mistakes.


Hypothesis has been highly useful in the team I work in. It is also one of the most robust property-based testing library in any language. Thanks to the project contributors and Stripe for investing resources in making it even better!


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: